function deploy(context) {
    var executeDfd = Q.defer(),
        config,
        credentials,
        ignore = context.ignoredFiles();

    try {
      config = fs.readFileSync(context.defaultConfig, 'utf-8');
      config = JSON.parse(config);
    } catch (e) {
      console.log('Cannot parse cordova-hcp.json. Did you run cordova-hcp init?');
      process.exit(0);
    }
    if (!config) {
      console.log('You need to run "cordova-hcp init" before you can run "cordova-hcp login".');
      console.log('Both commands needs to be invoked in the root of the project directory.');
      process.exit(0);
    }
    try {
      credentials = fs.readFileSync(loginFile, 'utf-8');
      credentials = JSON.parse(credentials);
    } catch (e) {
      console.log('Cannot parse .chcplogin: '******'You need to run "cordova-hcp login" before you can run "cordova-hcp deploy".');
      process.exit(0);
    }

    ignore = ignore.filter(function (ignoredFile) {
      return !ignoredFile.match(/^chcp/);
    });
    ignore = ignore.map(function (ignoredFile) {
      return '!' + ignoredFile;
    });

    // console.log('Credentials: ', credentials);
    // console.log('Config: ', config);
    //console.log('Ignore: ', ignore);

    var files = readdirp({
      root: context.sourceDirectory,
      fileFilter: ignore,
      directoryFilter: ignore
    });

    var uploader = s3sync({
      key: credentials.key,
      secret: credentials.secret,
      region: config.s3region,
      bucket: config.s3bucket,
      acl: 'public-read',
      headers: {
        CacheControl: 'no-cache, no-store, must-revalidate',
        Expires: 0
      },
      concurrency: 20
    }).on('data', function (file) {
      if (file.fresh) {
        console.log("Updated " + file.fullPath + ' -> ' + file.url);
      }
    });

    files.pipe(uploader);

    console.log('Deploy started');
    uploader.on('error', function (err) {
      console.error("unable to sync:", err.stack);
      executeDfd.reject();
    });
    uploader.on('fail', function (err) {
      console.error("unable to sync:", err);
      executeDfd.reject();
    });

    //uploader.on('progress', function() {
    //  var progress = uploader.progressTotal - uploader.progressAmount;
    //  console.log("progress", progress, uploader.progressTotal, uploader.progressAmount);
    //});
    uploader.on('end', function () {
      console.log("Deploy done");
      executeDfd.resolve();
    });
    return executeDfd.promise;
  }
module.exports = function(args) {
  var publicDir = this.config.public_dir;
  var log = this.log;

  if (!args.hasOwnProperty('concurrency')) {
    args.concurrency = 8;
  }

  if (!args.hasOwnProperty('aws_key')) {
    args.aws_key = process.env.AWS_KEY;
  }

  if (!args.hasOwnProperty('aws_secret')) {
    args.aws_secret = process.env.AWS_SECRET;
  }

  if (!args.hasOwnProperty('force_overwrite')) {
    args.force_overwrite = true;
  }

  if (!args.hasOwnProperty('headers')) {
    args.headers = {};
  }

  if (!args.hasOwnProperty('prefix')) {
    args.prefix = false;
  }

  if (!args.bucket || !args.aws_key || !args.aws_secret) {
    var help = '';

    help += 'You should configure deployment settings in _config.yml first!\n\n';
    help += 'Example:\n';
    help += '  deploy:\n';
    help += '    type: s3-cloudfront\n';
    help += '    bucket: <bucket>\n';
    help += '    [aws_key]: <aws_key>        # Optional, if provided as environment variable\n';
    help += '    [aws_secret]: <aws_secret>  # Optional, if provided as environment variable\n';
    help += '    [concurrency]: <concurrency> # Optional\n';
    help += '    [force_overwrite]: <true/false>   # Optional, default true\n';
    help += '    [region]: <region>          # Optional, default "us-standard"\n';
    help += '    [prefix]: <S3 key prefix ending in /> # Optional\n';
    help += '    [cf_distribution]: <cf_distribution> # Optional\n';
    help += '    [headers]: <headers in json format> # Optional\n\n';
    help += 'For more help, you can check the docs: ' + chalk.underline('https://github.com/Wouter33/hexo-deployer-s3-cloudfront');

    console.log(help);
    return;
  }

  // s3sync takes the same options arguments as `knox`,
  // plus some additional options listed above

  var syncinput = {
    key: args.aws_key,
    secret: args.aws_secret,
    bucket: args.bucket,
    concurrency: args.concurrency,
    region: args.region,
    headers: args.headers
  };

  // Level db for cache, makes less S3 requests
  db = level('./cache-s3-cf-deploy')

  if(args.force_overwrite){
      syncinput.force = true;
  }
  if(args.prefix){
      syncinput.prefix = args.prefix;
  }

  return readdirp({root: publicDir, entryType: 'both'})
      .pipe(s3sync(db, syncinput).on('data', function(file) {
        log.info(file.fullPath + ' -> ' + file.url)
      }).on('end', function() {
        log.info('Deployed to S3');

        if(args.cf_distribution){

            log.info('Invalidating Cloudfront distribution now');

            var cf = cloudfront.createClient(args.aws_key, args.aws_secret);

            var cfPath = '/' + args.prefix + '*' || '/*';

            return cf.createInvalidation(args.cf_distribution, 'dsadasds' + Math.round(new Date().getTime()/1000), cfPath, function(err, invalidation) {
                if (err){
                    console.log(err);
                } else {
                    log.info('Deployment completed');
                }
            })
        } else {
            log.info('Deployment completed');
        }

      }).on('fail', function(err) {
        log.error(err)
      }));
};