<commit_before>/*
cacophony-api: The Cacophony Project API server
Copyright (C) 2018  The Cacophony Project

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

var mime = require('mime');
var moment = require('moment-timezone');
var Sequelize = require('sequelize');
const Op = Sequelize.Op;
const assert = require('assert');

var util = require('./util/util');
var validation = require('./util/validation');

module.exports = function(sequelize, DataTypes) {
  var name = 'Recording';

  var attributes = {
    // recording metadata.
    type: DataTypes.STRING,
    duration: DataTypes.INTEGER,
    recordingDateTime: DataTypes.DATE,
    location: {
      type: DataTypes.GEOMETRY,
      set: util.geometrySetter,
      validate: { isLatLon: validation.isLatLon },
    },
    relativeToDawn: DataTypes.INTEGER,
    relativeToDusk: DataTypes.INTEGER,
    version: DataTypes.STRING,
    additionalMetadata: DataTypes.JSONB,
    comment: DataTypes.STRING,
    public: { type: DataTypes.BOOLEAN, defaultValue: false},

    // Raw file data.
    rawFileKey: DataTypes.STRING,
    rawFileSize: DataTypes.INTEGER,
    rawMimeType: DataTypes.STRING,

    // Processing fields. Fields set by and for the processing.
    fileKey: DataTypes.STRING,
    fileSize: DataTypes.STRING,
    fileMimeType: DataTypes.STRING,
    processingStartTime: DataTypes.DATE,
    processingMeta: DataTypes.JSONB,
    processingState: DataTypes.STRING,
    passedFilter: DataTypes.BOOLEAN,
    jobKey: DataTypes.STRING,

    // Battery relevant fields.
    batteryLevel: DataTypes.DOUBLE,
    batteryCharging: DataTypes.STRING,
    airplaneModeOn: DataTypes.BOOLEAN,
  };

  var Recording = sequelize.define(name, attributes);

  //---------------
  // CLASS METHODS
  //---------------
  var models = sequelize.models;

  Recording.addAssociations = function(models) {
    models.Recording.belongsTo(models.Group);
    models.Recording.belongsTo(models.Device);
    models.Recording.hasMany(models.Tag);
  };

  Recording.isValidTagMode = function(mode) {
    return validTagModes.includes(mode);
  };

  /**
    * Return one or more recordings for a user matching the query
    * arguments given.
    */
  Recording.query = async function(user, where, tagMode, tags, offset, limit, order, filterOptions) {
    if (order == null) {
      order = [
        // Sort by recordingDatetime but handle the case of the
        // timestamp being missing and fallback to sorting by id.
        [sequelize.fn("COALESCE", sequelize.col('recordingDateTime'), '1970-01-01'), "DESC"],
        ["id", "DESC"],
      ];
    }

    var q = {
      where: {
        [Op.and]: [
          where, // User query
          await recordingsFor(user),
          sequelize.literal(handleTagMode(tagMode)),
        ],
      },
      order: order,
      include: [
        { model: models.Group },
        { model: models.Tag, where: makeTagsWhere(tags) },
        { model: models.Device, where: {}, attributes: ["devicename", "id"] },
      ],
      limit: limit,
      offset: offset,
      attributes: this.userGetAttributes,
    };

    var queryResponse = await this.findAndCount(q);
    filterOptions = makeFilterOptions(user, filterOptions);
    queryResponse.rows.map(rec => rec.filterData(filterOptions));
    return queryResponse;
  };

  // local
  var handleTagMode = (tagMode) => {
    switch (tagMode) {
    case 'any':
      return '';
    case 'untagged':
      return 'NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id)';
    case 'tagged':
      return 'EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id)';
    case 'no-human':
      return `NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)`;
    case 'automatic-only':
      return `EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND automatic)
              AND NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)`;
    case 'human-only':
      return `EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)
              AND NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND automatic)`;
    case 'automatic+human':
      return `EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND automatic)
              AND EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)`;
    default:
      throw `invalid tag mode: ${tagMode}`;
    }
  };

  // local
  var makeTagsWhere = (tags) => {
    if (!tags || tags.length === 0) {
      return null;
    }

    var parts = [];
    for (var i = 0; i < tags.length; i++) {
      var tag = tags[i];
      switch (tag) {
      case "interesting":
        parts.push({
          [Op.not]: {
            [Op.or]: [
              {animal: null, event: "false positive"},
              {animal: "bird"},
            ]},
        });
        break;
      default:
        parts.push({animal: tag});
      }
    }
    if (parts.length == 1) {
      return parts[0];
    }
    return {[Op.or]: parts};
  };

  /**
   * Return a single recording for a user.
   */
  Recording.getOne = async function(user, id, type, filterOptions) {
    var query = {
      where: {
        [Op.and]: [
          { id: id },
          await recordingsFor(user),
        ],
      },
      include: [
        { model: models.Tag, },
        { model: models.Device, where: {}, attributes: ["devicename", "id"] },
      ],
      attributes: this.userGetAttributes.concat(['rawFileKey']),
    };
    if (type) {
      query.where[Op.and].push({'type': type});
    }

    filterOptions = makeFilterOptions(user, filterOptions);
    var recording = await this.findOne(query);
    recording.filterData(filterOptions);
    return recording;
  };

  /**
   * Deletes a single recording if the user has permission to do so.
   */
  Recording.deleteOne = async function(user, id) {
    var recording = await this.getOne(user, id);
    if (recording == null) {
      return false;
    }
    var userPermissions = await recording.getUserPermissions(user);
    if (userPermissions.canDelete != true) {
      return false;
    } else {
      await recording.destroy();
      return true;
    }
  };

  /**
   * Updates a single recording if the user has permission to do so.
   */
  Recording.updateOne = async function(user, id, updates) {
    for (var key in updates) {
      if (apiUpdatableFields.indexOf(key) == -1) {
        return false;
      }
    }
    var recording = await this.getOne(user, id);
    if (recording == null) {
      return false;
    }
    var userPermissions = await recording.getUserPermissions(user);
    if (userPermissions.canUpdate != true) {
      return false;
    } else {
      await recording.update(updates);
      return true;
    }
  };

  // local
  var recordingsFor = async function(user) {
    if (user.hasGlobalRead()) {
      return null;
    }
    var deviceIds = await user.getDeviceIds();
    var groupIds = await user.getGroupsIds();
    return {[Op.or]: [
      {public: true},
      {GroupId: {[Op.in]: groupIds}},
      {DeviceId: {[Op.in]: deviceIds}},
    ]};
  };

  //------------------
  // INSTANCE METHODS
  //------------------

  Recording.prototype.getFileBaseName = function() {
    return moment(new Date(this.recordingDateTime)).tz("Pacific/Auckland")
      .format("YYYYMMDD-HHmmss");
  };

  Recording.prototype.getRawFileName = function() {
    return this.getFileBaseName() + this.getRawFileExt();
  };

  Recording.prototype.getFileName = function() {
    return this.getFileBaseName() + this.getFileExt();
  };

  Recording.prototype.getRawFileExt = function() {
    if (this.rawMimeType == 'application/x-cptv') {
      return ".cptv";
    }
    const ext = mime.getExtension(this.rawMimeType);
    if (ext) {
      return '.' + ext;
    }
    switch (this.type) {
    case 'thermalRaw':
      return '.cptv';
    case 'audio':
      return '.mpga';
    default:
      return "";
    }
  };

  /**
   * Returns JSON describing what the user can do to the recording.
   * Permission types: DELETE, TAG, VIEW,
   * //TODO This will be edited in the future when recordings can be public.
   */
  Recording.prototype.getUserPermissions = async function(user) {
    if (user.hasGlobalWrite() || await user.isInGroup(this.GroupId)) {
      return {
        canDelete: true,
        canTag: true,
        canView: true,
        canUpdate: true,
      };
    }

    if (user.hasGlobalRead()) {
      return {
        canDelete: false,
        canTag: false,
        canView: true,
        canUpdate: false,
      };
    }
    return {
      canDelete: false,
      canTag: false,
      canView: false,
      canUpdate: false,
    };
  };

  Recording.prototype.getFileExt = function() {
    if (this.fileMimeType == 'video/mp4') {
      return ".mp4";
    }
    const ext = mime.getExtension(this.fileMimeType);
    if (ext) {
      return "." + ext;
    }
    return "";
  };

  Recording.prototype.isInGroup = async function(id) {
    var groupIds = await this.getGroupsIds();
    return (groupIds.includes(id));
  };

  Recording.prototype.filterData = function(options) {
    if (this.location) {
      this.location.coordinates = reduceLatLonPrecision(
        this.location.coordinates, options.latLongPrec);
    }
  };

  function makeFilterOptions(user, options = {}) {
    if (typeof options.latLongPrec != 'number') {
      options.latLongPrec = 100;
    }
    if (!user.hasGlobalWrite()) {
      options.latLongPrec = Math.max(options.latLongPrec, 100);
    }
    return options;
  }

  function reduceLatLonPrecision(latLon, prec) {
    assert (latLon.length == 2);
    const resolution = prec * 360 / 40000000;
    const half_resolution = resolution / 2;
    return latLon.map((val) => {
      val = val - (val % resolution);
      if (val > 0) {
        val += half_resolution;
      } else {
        val -= half_resolution;
      }
      return val;
    });
  }

  Recording.userGetAttributes = [
    'id',
    'rawFileSize',
    'rawMimeType',
    'fileSize',
    'fileMimeType',
    'processingState',
    'duration',
    'recordingDateTime',
    'relativeToDawn',
    'relativeToDusk',
    'location',
    'version',
    'batteryLevel',
    'batteryCharging',
    'airplaneModeOn',
    'type',
    'additionalMetadata',
    'GroupId',
    'fileKey',
    'comment',
  ];

  Recording.apiSettableFields = [
    'type',
    'duration',
    'recordingDateTime',
    'relativeToDawn',
    'relativeToDusk',
    'location',
    'version',
    'batteryCharging',
    'batteryLevel',
    'airplaneModeOn',
    'additionalMetadata',
    'processingMeta',
    'comment',
  ];

  // local
  var apiUpdatableFields = [
    'location',
    'comment',
    'additionalMetadata',
  ];

  Recording.processingStates = {
    thermalRaw: ['toMp4', 'FINISHED'],
    audio: ['toMp3', 'FINISHED'],
  };

  Recording.processingAttributes = [
    'id',
    'type',
    'jobKey',
    'rawFileKey',
    'rawMimeType',
    'fileKey',
    'fileMimeType',
    'processingState',
    'processingMeta',
  ];

  // local
  const validTagModes = Object.freeze([
    'any',
    'untagged',
    'tagged',
    'no-human',  // untagged or automatic only
    'automatic-only',
    'human-only',
    'automatic+human',
  ]);

  return Recording;
};
<commit_msg>removed isInGrooup from recordings<commit_after>/*
cacophony-api: The Cacophony Project API server
Copyright (C) 2018  The Cacophony Project

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

var mime = require('mime');
var moment = require('moment-timezone');
var Sequelize = require('sequelize');
const Op = Sequelize.Op;
const assert = require('assert');

var util = require('./util/util');
var validation = require('./util/validation');

module.exports = function(sequelize, DataTypes) {
  var name = 'Recording';

  var attributes = {
    // recording metadata.
    type: DataTypes.STRING,
    duration: DataTypes.INTEGER,
    recordingDateTime: DataTypes.DATE,
    location: {
      type: DataTypes.GEOMETRY,
      set: util.geometrySetter,
      validate: { isLatLon: validation.isLatLon },
    },
    relativeToDawn: DataTypes.INTEGER,
    relativeToDusk: DataTypes.INTEGER,
    version: DataTypes.STRING,
    additionalMetadata: DataTypes.JSONB,
    comment: DataTypes.STRING,
    public: { type: DataTypes.BOOLEAN, defaultValue: false},

    // Raw file data.
    rawFileKey: DataTypes.STRING,
    rawFileSize: DataTypes.INTEGER,
    rawMimeType: DataTypes.STRING,

    // Processing fields. Fields set by and for the processing.
    fileKey: DataTypes.STRING,
    fileSize: DataTypes.STRING,
    fileMimeType: DataTypes.STRING,
    processingStartTime: DataTypes.DATE,
    processingMeta: DataTypes.JSONB,
    processingState: DataTypes.STRING,
    passedFilter: DataTypes.BOOLEAN,
    jobKey: DataTypes.STRING,

    // Battery relevant fields.
    batteryLevel: DataTypes.DOUBLE,
    batteryCharging: DataTypes.STRING,
    airplaneModeOn: DataTypes.BOOLEAN,
  };

  var Recording = sequelize.define(name, attributes);

  //---------------
  // CLASS METHODS
  //---------------
  var models = sequelize.models;

  Recording.addAssociations = function(models) {
    models.Recording.belongsTo(models.Group);
    models.Recording.belongsTo(models.Device);
    models.Recording.hasMany(models.Tag);
  };

  Recording.isValidTagMode = function(mode) {
    return validTagModes.includes(mode);
  };

  /**
    * Return one or more recordings for a user matching the query
    * arguments given.
    */
  Recording.query = async function(user, where, tagMode, tags, offset, limit, order, filterOptions) {
    if (order == null) {
      order = [
        // Sort by recordingDatetime but handle the case of the
        // timestamp being missing and fallback to sorting by id.
        [sequelize.fn("COALESCE", sequelize.col('recordingDateTime'), '1970-01-01'), "DESC"],
        ["id", "DESC"],
      ];
    }

    var q = {
      where: {
        [Op.and]: [
          where, // User query
          await recordingsFor(user),
          sequelize.literal(handleTagMode(tagMode)),
        ],
      },
      order: order,
      include: [
        { model: models.Group },
        { model: models.Tag, where: makeTagsWhere(tags) },
        { model: models.Device, where: {}, attributes: ["devicename", "id"] },
      ],
      limit: limit,
      offset: offset,
      attributes: this.userGetAttributes,
    };

    var queryResponse = await this.findAndCount(q);
    filterOptions = makeFilterOptions(user, filterOptions);
    queryResponse.rows.map(rec => rec.filterData(filterOptions));
    return queryResponse;
  };

  // local
  var handleTagMode = (tagMode) => {
    switch (tagMode) {
    case 'any':
      return '';
    case 'untagged':
      return 'NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id)';
    case 'tagged':
      return 'EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id)';
    case 'no-human':
      return `NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)`;
    case 'automatic-only':
      return `EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND automatic)
              AND NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)`;
    case 'human-only':
      return `EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)
              AND NOT EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND automatic)`;
    case 'automatic+human':
      return `EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND automatic)
              AND EXISTS (SELECT * FROM "Tags" WHERE  "Tags"."RecordingId" = "Recording".id AND NOT automatic)`;
    default:
      throw `invalid tag mode: ${tagMode}`;
    }
  };

  // local
  var makeTagsWhere = (tags) => {
    if (!tags || tags.length === 0) {
      return null;
    }

    var parts = [];
    for (var i = 0; i < tags.length; i++) {
      var tag = tags[i];
      switch (tag) {
      case "interesting":
        parts.push({
          [Op.not]: {
            [Op.or]: [
              {animal: null, event: "false positive"},
              {animal: "bird"},
            ]},
        });
        break;
      default:
        parts.push({animal: tag});
      }
    }
    if (parts.length == 1) {
      return parts[0];
    }
    return {[Op.or]: parts};
  };

  /**
   * Return a single recording for a user.
   */
  Recording.getOne = async function(user, id, type, filterOptions) {
    var query = {
      where: {
        [Op.and]: [
          { id: id },
          await recordingsFor(user),
        ],
      },
      include: [
        { model: models.Tag, },
        { model: models.Device, where: {}, attributes: ["devicename", "id"] },
      ],
      attributes: this.userGetAttributes.concat(['rawFileKey']),
    };
    if (type) {
      query.where[Op.and].push({'type': type});
    }

    filterOptions = makeFilterOptions(user, filterOptions);
    var recording = await this.findOne(query);
    recording.filterData(filterOptions);
    return recording;
  };

  /**
   * Deletes a single recording if the user has permission to do so.
   */
  Recording.deleteOne = async function(user, id) {
    var recording = await this.getOne(user, id);
    if (recording == null) {
      return false;
    }
    var userPermissions = await recording.getUserPermissions(user);
    if (userPermissions.canDelete != true) {
      return false;
    } else {
      await recording.destroy();
      return true;
    }
  };

  /**
   * Updates a single recording if the user has permission to do so.
   */
  Recording.updateOne = async function(user, id, updates) {
    for (var key in updates) {
      if (apiUpdatableFields.indexOf(key) == -1) {
        return false;
      }
    }
    var recording = await this.getOne(user, id);
    if (recording == null) {
      return false;
    }
    var userPermissions = await recording.getUserPermissions(user);
    if (userPermissions.canUpdate != true) {
      return false;
    } else {
      await recording.update(updates);
      return true;
    }
  };

  // local
  var recordingsFor = async function(user) {
    if (user.hasGlobalRead()) {
      return null;
    }
    var deviceIds = await user.getDeviceIds();
    var groupIds = await user.getGroupsIds();
    return {[Op.or]: [
      {public: true},
      {GroupId: {[Op.in]: groupIds}},
      {DeviceId: {[Op.in]: deviceIds}},
    ]};
  };

  //------------------
  // INSTANCE METHODS
  //------------------

  Recording.prototype.getFileBaseName = function() {
    return moment(new Date(this.recordingDateTime)).tz("Pacific/Auckland")
      .format("YYYYMMDD-HHmmss");
  };

  Recording.prototype.getRawFileName = function() {
    return this.getFileBaseName() + this.getRawFileExt();
  };

  Recording.prototype.getFileName = function() {
    return this.getFileBaseName() + this.getFileExt();
  };

  Recording.prototype.getRawFileExt = function() {
    if (this.rawMimeType == 'application/x-cptv') {
      return ".cptv";
    }
    const ext = mime.getExtension(this.rawMimeType);
    if (ext) {
      return '.' + ext;
    }
    switch (this.type) {
    case 'thermalRaw':
      return '.cptv';
    case 'audio':
      return '.mpga';
    default:
      return "";
    }
  };

  /**
   * Returns JSON describing what the user can do to the recording.
   * Permission types: DELETE, TAG, VIEW,
   * //TODO This will be edited in the future when recordings can be public.
   */
  Recording.prototype.getUserPermissions = async function(user) {
    if (user.hasGlobalWrite() || await user.isInGroup(this.GroupId)) {
      return {
        canDelete: true,
        canTag: true,
        canView: true,
        canUpdate: true,
      };
    }

    if (user.hasGlobalRead()) {
      return {
        canDelete: false,
        canTag: false,
        canView: true,
        canUpdate: false,
      };
    }
    return {
      canDelete: false,
      canTag: false,
      canView: false,
      canUpdate: false,
    };
  };

  Recording.prototype.getFileExt = function() {
    if (this.fileMimeType == 'video/mp4') {
      return ".mp4";
    }
    const ext = mime.getExtension(this.fileMimeType);
    if (ext) {
      return "." + ext;
    }
    return "";
  };

  Recording.prototype.filterData = function(options) {
    if (this.location) {
      this.location.coordinates = reduceLatLonPrecision(
        this.location.coordinates, options.latLongPrec);
    }
  };

  function makeFilterOptions(user, options = {}) {
    if (typeof options.latLongPrec != 'number') {
      options.latLongPrec = 100;
    }
    if (!user.hasGlobalWrite()) {
      options.latLongPrec = Math.max(options.latLongPrec, 100);
    }
    return options;
  }

  function reduceLatLonPrecision(latLon, prec) {
    assert (latLon.length == 2);
    const resolution = prec * 360 / 40000000;
    const half_resolution = resolution / 2;
    return latLon.map((val) => {
      val = val - (val % resolution);
      if (val > 0) {
        val += half_resolution;
      } else {
        val -= half_resolution;
      }
      return val;
    });
  }

  Recording.userGetAttributes = [
    'id',
    'rawFileSize',
    'rawMimeType',
    'fileSize',
    'fileMimeType',
    'processingState',
    'duration',
    'recordingDateTime',
    'relativeToDawn',
    'relativeToDusk',
    'location',
    'version',
    'batteryLevel',
    'batteryCharging',
    'airplaneModeOn',
    'type',
    'additionalMetadata',
    'GroupId',
    'fileKey',
    'comment',
  ];

  Recording.apiSettableFields = [
    'type',
    'duration',
    'recordingDateTime',
    'relativeToDawn',
    'relativeToDusk',
    'location',
    'version',
    'batteryCharging',
    'batteryLevel',
    'airplaneModeOn',
    'additionalMetadata',
    'processingMeta',
    'comment',
  ];

  // local
  var apiUpdatableFields = [
    'location',
    'comment',
    'additionalMetadata',
  ];

  Recording.processingStates = {
    thermalRaw: ['toMp4', 'FINISHED'],
    audio: ['toMp3', 'FINISHED'],
  };

  Recording.processingAttributes = [
    'id',
    'type',
    'jobKey',
    'rawFileKey',
    'rawMimeType',
    'fileKey',
    'fileMimeType',
    'processingState',
    'processingMeta',
  ];

  // local
  const validTagModes = Object.freeze([
    'any',
    'untagged',
    'tagged',
    'no-human',  // untagged or automatic only
    'automatic-only',
    'human-only',
    'automatic+human',
  ]);

  return Recording;
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

/*
 * Loads a number of verbose JSON files and writes them a 'compacted'
 * JSON-file.
 *
 * The verbose files are designed to be easy to edit by hand; the compact ones
 * are smaller to store and send over the wire.
 *
 * Any number of verbose files can be compacted into one large compact file.
 *
 * Verbose files:
 *     {
 *         { "→": { "alias": ["->", "arrow"] },
 *         { "…": { "alias": ["...", "dots"] },
 *         …
 *     }
 *
 * Compact:
 *     [
 *         {
 *             c: characterCodeInDecimal,
 *             n: "lowercase unicode name"
 *             b: "unicode block"
 *             a: ["alias", "can", "be", "here"]
 *         },
 *         …
 *     ]
 *
 */

var JSONStream = require('JSONStream'),
    _ = require('underscore'),
    fs = require('fs');

var argparse = require('optimist')
    .usage('Usage: $0 [-v] [-o <outfile>] <infile> ... <infile>')
    .demand(1)
    .alias('o', 'output');
var args = argparse.argv;

var output = args.output ? fs.createWriteStream(args.output) : process.stdout,
    jsonStream = JSONStream.stringify("[", ",\n", "]\n");

jsonStream.pipe(output);

function verbose2compact(obj, key) {
    var out = {};
    if ('alias' in obj) { out.a = obj.alias; }
    if ('name' in obj) { out.n = obj.name; }
    if ('block' in obj) { out.b = obj.block; }
    if ('code' in obj) { out.c = obj.code; }
    else if (key) { out.c = key.charCodeAt(0); }

    return out;
}

function mergeCompact(existing, added) {
    // Update "single" attributes, if missing
    if (added.n && !existing.n) { existing.n = added.n; }
    if (added.b && !existing.b) { existing.b = added.b; }
    if (added.c && !existing.c) { existing.c = added.c; }
    // Update alia
    existing.a = _.union(existing.a || [], added.a || []);

    return existing;
}

var data = {};

args._.forEach(function(file) {
    console.warn("Reading", file);
    var json = JSON.parse(fs.readFileSync(file));

    if (_.isArray(json)) {
        console.warn("File " + file + " isn't a verbose JSON-file (it's an array)");
        return;
    }

    console.warn(" · Loaded", _(json).size(), "codepoints");

    // Convert to code → compact block
    _(json).forEach(function (value, key) {
        //if (!json.hasOwnProperty(key)) { return; }
        var compact = verbose2compact(value, key),
            code = compact.c;

        // Merge with existing key?
        if (code in data) {
            data[code] = mergeCompact(data[code], compact);
        } else {
            //console.warn("Inserting", code);
            data[code] = compact;
        }
    });
});

_(data).forEach(function (elem, key) {
    jsonStream.write(elem);
});

console.warn("Wrote", _(data).size(), "elements to output");

jsonStream.end();
<commit_msg>Don't in include empty alias-lists in output.<commit_after>#!/usr/bin/env node

/*
 * Loads a number of verbose JSON files and writes them a 'compacted'
 * JSON-file.
 *
 * The verbose files are designed to be easy to edit by hand; the compact ones
 * are smaller to store and send over the wire.
 *
 * Any number of verbose files can be compacted into one large compact file.
 *
 * Verbose files:
 *     {
 *         { "→": { "alias": ["->", "arrow"] },
 *         { "…": { "alias": ["...", "dots"] },
 *         …
 *     }
 *
 * Compact:
 *     [
 *         {
 *             c: characterCodeInDecimal,
 *             n: "lowercase unicode name"
 *             b: "unicode block"
 *             a: ["alias", "can", "be", "here"]
 *         },
 *         …
 *     ]
 *
 */

var JSONStream = require('JSONStream'),
    _ = require('underscore'),
    fs = require('fs');

var argparse = require('optimist')
    .usage('Usage: $0 [-v] [-o <outfile>] <infile> ... <infile>')
    .demand(1)
    .alias('o', 'output');
var args = argparse.argv;

var output = args.output ? fs.createWriteStream(args.output) : process.stdout,
    jsonStream = JSONStream.stringify("[", ",\n", "]\n");

jsonStream.pipe(output);

function verbose2compact(obj, key) {
    var out = {};
    if ('alias' in obj) { out.a = obj.alias; }
    if ('name' in obj) { out.n = obj.name; }
    if ('block' in obj) { out.b = obj.block; }
    if ('code' in obj) { out.c = obj.code; }
    else if (key) { out.c = key.charCodeAt(0); }

    return out;
}

function mergeCompact(existing, added) {
    // Update "single" attributes, if missing
    if (added.n && !existing.n) { existing.n = added.n; }
    if (added.b && !existing.b) { existing.b = added.b; }
    if (added.c && !existing.c) { existing.c = added.c; }
    // Update alia
    if (existing.a || added.a) {
        existing.a = _.union(existing.a || [], added.a || []);
    }

    return existing;
}

var data = {};

args._.forEach(function(file) {
    console.warn("Reading", file);
    var json = JSON.parse(fs.readFileSync(file));

    if (_.isArray(json)) {
        console.warn("File " + file + " isn't a verbose JSON-file (it's an array)");
        return;
    }

    console.warn(" · Loaded", _(json).size(), "codepoints");

    // Convert to code → compact block
    _(json).forEach(function (value, key) {
        //if (!json.hasOwnProperty(key)) { return; }
        var compact = verbose2compact(value, key),
            code = compact.c;

        // Merge with existing key?
        if (code in data) {
            data[code] = mergeCompact(data[code], compact);
        } else {
            //console.warn("Inserting", code);
            data[code] = compact;
        }
    });
});

_(data).forEach(function (elem, key) {
    jsonStream.write(elem);
});

console.warn("Wrote", _(data).size(), "elements to output");

jsonStream.end();
<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout,<commit_msg>One more User Story done<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout, <|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [<commit_msg>Fixing an important issue with the universe.<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ <|endoftext|>


<commit_before><commit_msg>Ok that didn't work<commit_after><|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",<commit_msg>Grammar fix<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue w<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an <commit_msg>Quick fix<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an e<|endoftext|>


<commit_before>var fs = <commit_msg>Update character<commit_after>var fs = r<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bulle<commit_msg>Found an issue with the letter 'a', so I fixed it.<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullet<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var args = ['commit', outFile, '-m', 'Update character']
    for (var counter = 0; counter < length; counter++)
    {
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
 <commit_msg>Update character<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var args = ['commit', outFile, '-m', 'Update character']
    for (var counter = 0; counter < length; counter++)
    {
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
  <|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)<commit_msg>Can work my way through the Kanban<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue <commit_msg>Re-commiting last<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue w<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var c<commit_msg>Sprint complete<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var co<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    var timeout = randomIntFromInterval(0, max_sleep) * 1000
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    setTimeout(commit, timeout, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(outFD, outFile, data, counter, length)
{
  if (counter < length)
  {
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', <commit_msg>Found an issue with the letter 'a', so I fixed it.<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    var timeout = randomIntFromInterval(0, max_sleep) * 1000
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    setTimeout(commit, timeout, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(outFD, outFile, data, counter, length)
{
  if (counter < length)
  {
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    if (counter + step >= <|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the re<commit_msg>Logic error<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the rea<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      consol<commit_msg>Updated the readme<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout, t_offset, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(t_offset, outFD, outFile, data, counter, length)
{
  if (counter < length)
  {
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    if (counter + step >= length) step = length - counter
    process.stdout.write("\033[2K Writing " + counter + "/" + length + " bytes: " + message + "\r")<commit_msg>Correcting style<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout, t_offset, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(t_offset, outFD, outFile, data, counter, length)
{
  if (counter < length)
  {
    var message = commit_messages[randomIntFromInterval(0, commit_messages.length - 1)]
    var args = ['commit', outFile, '-m', message]
    if (counter + step >= length) step = length - counter
    process.stdout.write("\033[2K Writing " + counter + "/" + length + " bytes: " + message + "\r");<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack u<commit_msg>Ooops!<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goa<commit_msg>GET A HAIRCUT!<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes",
  "Merging in private branch",
  "Time machines are real man!"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 10% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.1;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.w<commit_msg>Sprint complete<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes",
  "Merging in private branch",
  "Time machines are real man!"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 10% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.1;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up th<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well tha<commit_msg>Re-updating the readme.<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var args = ['commit', outFile, '-m', 'Update character']
    for (var counter = 0; counter < length; counter++)
    {
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
    }
  })
}

function sleep(seconds) {
  v<commit_msg>Update character<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var args = ['commit', outFile, '-m', 'Update character']
    for (var counter = 0; counter < length; counter++)
    {
      fs.writeSync(outFD, data.slice(counter, counter+1), 0, 1)
      sleep(Math.random() * max_sleep)
      child_process.execFileSync('/usr/bin/git', args)
    }
  })
}

function sleep(seconds) {
  va<|endoftext|>