<commit_before>
var fs = require('fs');
var path = require('path');

var DSStore = require('ds-store');
var sizeOf = require('image-size');

var util = require('./util');
var hdiutil = require('./hdiutil');
var Pipeline = require('./pipeline');

module.exports = exports = function (source, target, cb) {

  if (process.platform !== 'darwin') {
    cb(new Error('Platform not supported: ' + process.platform));
    return ;
  }

  var resolveBase = path.dirname(source);
  var resolvePath = function (to) {
    return path.resolve(resolveBase, to);
  };

  var global = {
    source: source,
    target: target
  };

  delete source;
  delete target;

  var pipeline = new Pipeline();

  /**
   **
   **/

  pipeline.addStep('Looking for target', function (next) {

    fs.exists(global.target, function (exists) {
      if(exists) {
        next(new Error('Target already exists'));
      } else {
        next(null);
      }
    });

  });

  /**
   **
   **/

  pipeline.addStep('Reading JSON Specification', function (next) {

    fs.readFile(global.source, function(err, buffer) {
      global.specbuffer = buffer;
      next(err);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Parsing JSON Specification', function (next) {

    try {
      global.opts = JSON.parse(global.specbuffer.toString());
      next(null);
    } catch (err) {
      next(err);
    }

  });

  /**
   **
   **/

  pipeline.addStep('Validating JSON Specification', function (next) {

    var missing = [];
    var check = function (root, key, title) {
      if (!root[key]) { missing.push(title || key); }
    }

    check(global.opts, 'title');
    check(global.opts, 'app');
    check(global.opts, 'background');
    check(global.opts, 'icons');

    if (global.opts.icons) {
      check(global.opts.icons, 'size', 'icons.size');
      check(global.opts.icons, 'app', 'icons.app');
      check(global.opts.icons, 'alias', 'icons.alias');
    }

    if (missing.length > 0) {
      next(new Error('`' + (missing.join('`,`')) + '` missing from JSON Specification'));
    } else {
      next(null);
    }

  });

  /**
   **
   **/

  pipeline.addStep('Calculating size of image', function (next) {

    util.dusm(resolvePath(global.opts.app), function (err, megabytes) {
      if (err) { return next(err); }

      // FIXME: I think that this has something to do
      // with blocksize and minimum file size...
      // This should work for now but requires more
      // space than it should. Note that this does
      // not effect the final image.
      megabytes = megabytes * 1.5;

      global.megabytes = (megabytes + 32);
      next(null);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Creating temporary image', function (next) {

    hdiutil.create(global.opts.title, global.megabytes + 'm', function (err, temporaryImagePath) {
      if (err) { return next(err); }

      pipeline.addCleanupStep('unlink-temporay-image', 'Removing temporary image', function (next) {
        fs.unlink(temporaryImagePath, next);
      });

      global.temporaryImagePath = temporaryImagePath;
      next(null);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Mounting temporary image', function (next) {

    hdiutil.attach(global.temporaryImagePath, function (err, temporaryMountPath) {
      if (err) { return next(err); }

      pipeline.addCleanupStep('unmount-temporary-image', 'Unmounting temporary image', function (next) {
        hdiutil.detach(temporaryMountPath, next);
      });

      global.temporaryMountPath = temporaryMountPath;
      next(null);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Making hidden background folder', function (next) {
    global.bkgdir = path.join(global.temporaryMountPath, '.background');
    fs.mkdir(global.bkgdir, function (err) { next(err); });
  });

  /**
   **
   **/

  pipeline.addStep('Copying background', function (next) {

    var absolutePath = resolvePath(global.opts.background);
    var retinaPath = absolutePath.replace(/\.([a-z]+)$/, '@2x.$1');

    var copyRetinaBackground = function (next) {
      var originalExt = path.extname(global.opts.background);
      var outputName = path.basename(global.opts.background, originalExt) + '.tiff';
      var finalPath = path.join(global.bkgdir, outputName);
      global.bkgname = path.join('.background', outputName);
      util.tiffutil(absolutePath, retinaPath, finalPath, function (err) { next(err); });
    };

    var copyPlainBackground = function (next) {
      var finalPath = path.join(global.bkgdir, path.basename(global.opts.background));
      global.bkgname = path.join('.background', path.basename(global.opts.background));
      util.cp(absolutePath, finalPath, function (err) { next(err); });
    };

    fs.exists(retinaPath, function (exists) {
      if (exists) {
        copyRetinaBackground(next);
      } else {
        copyPlainBackground(next);
      }
    });

  });

  /**
   **
   **/

  pipeline.addStep('Reading background dimensions', function (next) {
    sizeOf(resolvePath(global.opts.background), function (err, value) {
      if (err) { return next(err); }

      global.bkgsize = [value.width, value.height];
      next(null);

    });
  });

  /**
   **
   **/

  pipeline.addStep('Copying icon', function (next) {
    if (global.opts.icon) {
      var finalPath = path.join(global.temporaryMountPath, '.VolumeIcon.icns');
      util.cp(resolvePath(global.opts.icon), finalPath, function (err) { next(err); });
    } else {
      next.skip();
    }
  });

  /**
   **
   **/

  pipeline.addStep('Setting icon', function (next) {
    if (global.opts.icon) {
      util.seticonflag(global.temporaryMountPath, function (err) { next(err); });
    } else {
      next.skip();
    }
  });

  /**
   **
   **/

  pipeline.addStep('Creating Applications alias', function (next) {

    var finalPath = path.join(global.temporaryMountPath, 'Applications');

    fs.symlink('/Applications', finalPath, function (err) { next(err); });

  });

  /**
   **
   **/

  pipeline.addStep('Copying application', function (next) {

    global.appname = path.basename(global.opts.app);
    var finalPath = path.join(global.temporaryMountPath, global.appname);

    util.sh('cp', ['-R', resolvePath(global.opts.app), finalPath], next);

  });

  /**
   **
   **/

  pipeline.addStep('Making all the visuals', function (next) {

    var ds = new DSStore();

    ds.vSrn(1);
    ds.setIconSize(global.opts.icons.size);
    ds.setBackground(path.join(global.temporaryMountPath, global.bkgname));
    ds.setWindowSize(global.bkgsize[0], global.bkgsize[1]);

    ds.setIconPos('Applications', global.opts.icons.alias[0], global.opts.icons.alias[1]);
    ds.setIconPos(global.appname, global.opts.icons.app[0], global.opts.icons.app[1]);

    ds.write(path.join(global.temporaryMountPath, '.DS_Store'), function (err) {
      next(err);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Blessing image', function (next) {

    args = [];
    args.push('--folder', global.temporaryMountPath);
    args.push('--openfolder', global.temporaryMountPath);

    util.sh('bless', args, next);

  });

  /**
   **
   **/

  pipeline.addStep('Unmounting temporary image', function (next) {
    pipeline.runCleanup('unmount-temporary-image', next);
  });

  /**
   **
   **/

  pipeline.addStep('Finalizing image', function (next) {
    hdiutil.convert(global.temporaryImagePath, global.target, next);
  });

  /**
   **
   **/

  pipeline.expectAdditional(1);

  pipeline.run(function (err) {
    cb(err, ( err ? undefined : global.target ));
  });

};
<commit_msg>appdmg: nice error on ENOENT<commit_after>
var fs = require('fs');
var path = require('path');

var DSStore = require('ds-store');
var sizeOf = require('image-size');

var util = require('./util');
var hdiutil = require('./hdiutil');
var Pipeline = require('./pipeline');

module.exports = exports = function (source, target, cb) {

  if (process.platform !== 'darwin') {
    cb(new Error('Platform not supported: ' + process.platform));
    return ;
  }

  var resolveBase = path.dirname(source);
  var resolvePath = function (to) {
    return path.resolve(resolveBase, to);
  };

  var global = {
    source: source,
    target: target
  };

  delete source;
  delete target;

  var pipeline = new Pipeline();

  /**
   **
   **/

  pipeline.addStep('Looking for target', function (next) {

    fs.exists(global.target, function (exists) {
      if(exists) {
        next(new Error('Target already exists'));
      } else {
        next(null);
      }
    });

  });

  /**
   **
   **/

  pipeline.addStep('Reading JSON Specification', function (next) {

    fs.readFile(global.source, function(err, buffer) {
      if (err && err.code === 'ENOENT' && err.path) {
        next(new Error('JSON Specification not found at: ' + err.path));
      } else {
        global.specbuffer = buffer;
        next(err);
      }
    });

  });

  /**
   **
   **/

  pipeline.addStep('Parsing JSON Specification', function (next) {

    try {
      global.opts = JSON.parse(global.specbuffer.toString());
      next(null);
    } catch (err) {
      next(err);
    }

  });

  /**
   **
   **/

  pipeline.addStep('Validating JSON Specification', function (next) {

    var missing = [];
    var check = function (root, key, title) {
      if (!root[key]) { missing.push(title || key); }
    }

    check(global.opts, 'title');
    check(global.opts, 'app');
    check(global.opts, 'background');
    check(global.opts, 'icons');

    if (global.opts.icons) {
      check(global.opts.icons, 'size', 'icons.size');
      check(global.opts.icons, 'app', 'icons.app');
      check(global.opts.icons, 'alias', 'icons.alias');
    }

    if (missing.length > 0) {
      next(new Error('`' + (missing.join('`,`')) + '` missing from JSON Specification'));
    } else {
      next(null);
    }

  });

  /**
   **
   **/

  pipeline.addStep('Calculating size of image', function (next) {

    util.dusm(resolvePath(global.opts.app), function (err, megabytes) {
      if (err) { return next(err); }

      // FIXME: I think that this has something to do
      // with blocksize and minimum file size...
      // This should work for now but requires more
      // space than it should. Note that this does
      // not effect the final image.
      megabytes = megabytes * 1.5;

      global.megabytes = (megabytes + 32);
      next(null);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Creating temporary image', function (next) {

    hdiutil.create(global.opts.title, global.megabytes + 'm', function (err, temporaryImagePath) {
      if (err) { return next(err); }

      pipeline.addCleanupStep('unlink-temporay-image', 'Removing temporary image', function (next) {
        fs.unlink(temporaryImagePath, next);
      });

      global.temporaryImagePath = temporaryImagePath;
      next(null);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Mounting temporary image', function (next) {

    hdiutil.attach(global.temporaryImagePath, function (err, temporaryMountPath) {
      if (err) { return next(err); }

      pipeline.addCleanupStep('unmount-temporary-image', 'Unmounting temporary image', function (next) {
        hdiutil.detach(temporaryMountPath, next);
      });

      global.temporaryMountPath = temporaryMountPath;
      next(null);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Making hidden background folder', function (next) {
    global.bkgdir = path.join(global.temporaryMountPath, '.background');
    fs.mkdir(global.bkgdir, function (err) { next(err); });
  });

  /**
   **
   **/

  pipeline.addStep('Copying background', function (next) {

    var absolutePath = resolvePath(global.opts.background);
    var retinaPath = absolutePath.replace(/\.([a-z]+)$/, '@2x.$1');

    var copyRetinaBackground = function (next) {
      var originalExt = path.extname(global.opts.background);
      var outputName = path.basename(global.opts.background, originalExt) + '.tiff';
      var finalPath = path.join(global.bkgdir, outputName);
      global.bkgname = path.join('.background', outputName);
      util.tiffutil(absolutePath, retinaPath, finalPath, function (err) { next(err); });
    };

    var copyPlainBackground = function (next) {
      var finalPath = path.join(global.bkgdir, path.basename(global.opts.background));
      global.bkgname = path.join('.background', path.basename(global.opts.background));
      util.cp(absolutePath, finalPath, function (err) { next(err); });
    };

    fs.exists(retinaPath, function (exists) {
      if (exists) {
        copyRetinaBackground(next);
      } else {
        copyPlainBackground(next);
      }
    });

  });

  /**
   **
   **/

  pipeline.addStep('Reading background dimensions', function (next) {
    sizeOf(resolvePath(global.opts.background), function (err, value) {
      if (err) { return next(err); }

      global.bkgsize = [value.width, value.height];
      next(null);

    });
  });

  /**
   **
   **/

  pipeline.addStep('Copying icon', function (next) {
    if (global.opts.icon) {
      var finalPath = path.join(global.temporaryMountPath, '.VolumeIcon.icns');
      util.cp(resolvePath(global.opts.icon), finalPath, function (err) { next(err); });
    } else {
      next.skip();
    }
  });

  /**
   **
   **/

  pipeline.addStep('Setting icon', function (next) {
    if (global.opts.icon) {
      util.seticonflag(global.temporaryMountPath, function (err) { next(err); });
    } else {
      next.skip();
    }
  });

  /**
   **
   **/

  pipeline.addStep('Creating Applications alias', function (next) {

    var finalPath = path.join(global.temporaryMountPath, 'Applications');

    fs.symlink('/Applications', finalPath, function (err) { next(err); });

  });

  /**
   **
   **/

  pipeline.addStep('Copying application', function (next) {

    global.appname = path.basename(global.opts.app);
    var finalPath = path.join(global.temporaryMountPath, global.appname);

    util.sh('cp', ['-R', resolvePath(global.opts.app), finalPath], next);

  });

  /**
   **
   **/

  pipeline.addStep('Making all the visuals', function (next) {

    var ds = new DSStore();

    ds.vSrn(1);
    ds.setIconSize(global.opts.icons.size);
    ds.setBackground(path.join(global.temporaryMountPath, global.bkgname));
    ds.setWindowSize(global.bkgsize[0], global.bkgsize[1]);

    ds.setIconPos('Applications', global.opts.icons.alias[0], global.opts.icons.alias[1]);
    ds.setIconPos(global.appname, global.opts.icons.app[0], global.opts.icons.app[1]);

    ds.write(path.join(global.temporaryMountPath, '.DS_Store'), function (err) {
      next(err);
    });

  });

  /**
   **
   **/

  pipeline.addStep('Blessing image', function (next) {

    args = [];
    args.push('--folder', global.temporaryMountPath);
    args.push('--openfolder', global.temporaryMountPath);

    util.sh('bless', args, next);

  });

  /**
   **
   **/

  pipeline.addStep('Unmounting temporary image', function (next) {
    pipeline.runCleanup('unmount-temporary-image', next);
  });

  /**
   **
   **/

  pipeline.addStep('Finalizing image', function (next) {
    hdiutil.convert(global.temporaryImagePath, global.target, next);
  });

  /**
   **
   **/

  pipeline.expectAdditional(1);

  pipeline.run(function (err) {
    cb(err, ( err ? undefined : global.target ));
  });

};

{'fraction_non_alphanumeric': 0.17036795831976556, 'fraction_numerical': 0.0019537609899055682, 'mean_word_length': 2.8915357323872275, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2677521', 'n_tokens_mistral': 5076, 'n_tokens_neox': 4901, 'n_words': 941}