<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', ou<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', out<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Keywords Popup
////////////////////////////////////////////////////////////////////////////////
/*global jQuery */
var yalp = yalp || {};

yalp.controls = function (controls, $) {
	controls.preview = function () {
		var self = Object.create(controls.popup()),
				keywords = [],
				hash = '';

		//////////////////////////////
		// Setters

		self.keywords = function (value) {
			keywords = value;
			return self;
		};

		self.hash = function (value) {
			hash = value;
			return self;
		};

		//////////////////////////////
		// Overrides

		self.contents = function (elem) {
			return [
				function () {
					if (hash.length) {
						return [''].join('');
					}
				}(),
				'
',
				function () {
					var result = [],
							i, keyword;
					for (i = 0; i < keywords.length; i++) {
						keyword = keywords[i].split(':');
						result.push([
							'
',
							'', keyword[0], '	',
							'', keyword.slice(1).join(':'), '	',
							'
'
						].join(''));
					}
					return result.join('');
				}(),
				'
'
			].join('');
		};

		return self;
	}();

	return controls;
}(yalp.controls || {},
	jQuery);

<commit_msg>redundant code removed from preview.js<commit_after>////////////////////////////////////////////////////////////////////////////////
// Keywords Popup
////////////////////////////////////////////////////////////////////////////////
/*global jQuery */
var yalp = yalp || {};

yalp.controls = function (controls, $) {
	controls.preview = function () {
		var self = Object.create(controls.popup()),
				keywords = [],
				hash = '';

		//////////////////////////////
		// Setters

		self.keywords = function (value) {
			keywords = value;
			return self;
		};

		self.hash = function (value) {
			hash = value;
			return self;
		};

		//////////////////////////////
		// Overrides

		self.contents = function () {
			return [
				function () {
					if (hash.length) {
						return [''].join('');
					}
				}(),
				'
',
				function () {
					var result = [],
							i, keyword;
					for (i = 0; i < keywords.length; i++) {
						keyword = keywords[i].split(':');
						result.push([
							'
',
							'', keyword[0], '	',
							'', keyword.slice(1).join(':'), '	',
							'
'
						].join(''));
					}
					return result.join('');
				}(),
				'
'
			].join('');
		};

		return self;
	}();

	return controls;
}(yalp.controls || {},
	jQuery);

<|endoftext|>


<commit_before>'use strict';

RMModule.factory('RMRecordApi', ['RMUtils', function(Utils) {

  /**
   * @class RelationScope
   *
   * @description
   *
   * Special scope a record provides to resources related via hasMany or hasOne relation.
   */
  var RelationScope = function(_scope, _target, _partial) {
    this.$scope = _scope;
    this.$target = _target;
    this.$partial = Utils.cleanUrl(_partial);
  };

  RelationScope.prototype = {

    $nestedUrl: function() {
      return Utils.joinUrl(this.$scope.$url(), this.$partial);
    },

    // url is nested for collections and nested records
    $urlFor: function(_resource) {
      if(_resource.$isCollection || this.$target.isNested()) {
        return this.$nestedUrl();
      } else {
        return this.$target.$urlFor(_resource);
      }
    },

    // a record's fetch url is always nested
    $fetchUrlFor: function(/* _resource */) {
      return this.$nestedUrl();
    },

    // create is not posible in nested members
    $createUrlFor: function() {
      return null;
    }
  };

  /**
   * @class RecordApi
   * @extends CommonApi
   *
   * @property {object} $scope The record's scope (see {@link ScopeApi})
   * @property {mixed} $pk The record's primary key
   *
   * @description
   *
   * Provides record synchronization and manipulation methods. This is the base API for every restmod record.
   *
   * TODO: Talk about the object lifecycle.
   *
   * ### Object lifecycle hooks
   *
   * For `$fetch`:
   *
   * * before-fetch
   * * before-request
   * * after-request[-error]
   * * after-feed (only called if no errors)
   * * after-fetch[-error]
   *
   * For `$save` when creating:
   *
   * * before-render
   * * before-save
   * * before-create
   * * before-request
   * * after-request[-error]
   * * after-feed (only called if no errors)
   * * after-create[-error]
   * * after-save[-error]
   *
   * For `$save` when updating:
   *
   * * before-render
   * * before-save
   * * before-update
   * * before-request
   * * after-request[-error]
   * * after-feed (only called if no errors)
   * * after-update[-error]
   * * after-save[-error]
   *
   * For `$destroy`:
   *
   * * before-destroy
   * * before-request
   * * after-request[-error]
   * * after-destroy[-error]
   *
   * @property {mixed} $pk The record primary key
   * @property {object} $scope The collection scope (hierarchical scope, not angular scope)
   */
	return {

    /**
     * @memberof RecordApi#
     *
     * @description Called by record constructor on initialization.
     *
     * Note: Is better to add a hook to after-init than overriding this method.
     */
    $initialize: function() {
      // apply defaults
      this.$super();

      // after initialization hook
      // TODO: put this on $new so it can use stacked DSP?
      this.$dispatch('after-init');
    },

    /**
     * @memberof RecordApi#
     *
     * @description Called the resource's scope $urlFor method to build the url for the record using the proper scope.
     *
     * By default the resource partial url is just its `$pk` property. This can be overriden to provide other routing approaches.
     *
     * @return {string} The resource partial url
     */
    $buildUrl: function(_scope) {
      return (this.$pk === undefined || this.$pk === null) ? null : Utils.joinUrl(_scope.$url(), this.$pk + '');
    },

    /**
     * @memberof RecordApi#
     *
     * @description Default item child scope factory.
     *
     * By default, no create url is provided and the update/destroy url providers
     * attempt to first use the unscoped resource url.
     *
     * // TODO: create special api to hold scope (so it is not necessary to recreate the whole object every time.)
     *
     * @param {mixed} _for Scope target type, accepts any model class.
     * @param {string} _partial Partial route.
     * @return {RelationScope} New scope.
     */
    $buildScope: function(_for, _partial) {
      if(_for.$buildOwnScope) {
        // TODO
      } else {
        return new RelationScope(this, _for, _partial);
      }
    },

    /**
     * @memberof RecordApi#
     *
     * @description Iterates over the object non-private properties
     *
     * @param {function} _fun Function to call for each
     * @return {RecordApi} self
     */
    $each: function(_fun, _ctx) {
      for(var key in this) {
        if(this.hasOwnProperty(key) && key[0] !== '$') {
          _fun.call(_ctx || this[key], this[key], key);
        }
      }

      return this;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Feed raw data to this instance.
     *
     * @param {object} _raw Raw data to be fed
     * @param {string} _mask 'CRU' mask
     * @return {RecordApi} this
     */
    $decode: function(_raw, _mask) {
      // IDEA: let user override serializer
      this.$type.decode(this, _raw, _mask || Utils.READ_MASK);
      if(this.$pk === undefined || this.$pk === null) this.$pk = this.$type.inferKey(_raw); // TODO: warn if key changes
      this.$dispatch('after-feed', [_raw]);
      return this;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Generate data to be sent to the server when creating/updating the resource.
     *
     * @param {string} _mask 'CRU' mask
     * @return {string} raw data
     */
    $encode: function(_mask) {
      var raw = this.$type.encode(this, _mask || Utils.CREATE_MASK);
      this.$dispatch('before-render', [raw]);
      return raw;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Begin a server request for updated resource data.
     *
     * The request's promise can be accessed using the `$asPromise` method.
     *
     * @param {object} _params Optional list of params to be passed to object request.
     * @return {RecordApi} this
     */
    $fetch: function(_params) {
      return this.$action(function() {
        var url = this.$url('fetch');
        Utils.assert(!!url, 'Cant $fetch if resource is not bound');

        var request = { method: 'GET', url: url, params: _params };

        this.$dispatch('before-fetch', [request]);
        this.$send(request, function(_response) {
          this.$unwrap(_response.data);
          this.$dispatch('after-fetch', [_response]);
        }, function(_response) {
          this.$dispatch('after-fetch-error', [_response]);
        });
      });
    },

    /**
     * @memberof RecordApi#
     *
     * @description Copyies another object's non-private properties.
     *
     * This method runs inside the promise chain, so calling
     *
     * ```javascript
     * Bike.$find(1).$extend({ size: "L" }).$save();
     * ```
     * Will first fetch the bike data and after it is loaded the new size will be applied and then the
     * updated model saved.
     *
     * @param {object} _other Object to merge.
     * @return {RecordApi} self
     */
    $extend: function(_other) {
      return this.$action(function() {
        for(var tmp in _other) {
          if (_other.hasOwnProperty(tmp) && tmp[0] !== '$') {
            this[tmp] = _other[tmp];
          }
        }
      });
    },

    /**
     * @memberof RecordApi#
     *
     * @description Shortcut method used to extend and save a model.
     *
     * This method will not force a PUT, if object is new `$update` will attempt to POST.
     *
     * @param {object} _other Data to change
     * @return {RecordApi} self
     */
    $update: function(_other) {
      return this.$extend(_other).$save();
    },

    /**
     * @memberof RecordApi#
     *
     * @description Begin a server request to create/update/patch resource.
     *
     * A patch is only executed if model is identified and a patch property list is given. It is posible to
     * change the method used for PATCH operations by setting the `patchMethod` configuration.
     *
     * If resource is new and it belongs to a collection and it hasnt been revealed, then it will be revealed.
     *
     * The request's promise can be accessed using the `$asPromise` method.
     *
     * @param {array} _patch Optional list of properties to send in update operation.
     * @return {RecordApi} this
     */
    $save: function(_patch) {
      return this.$action(function() {
        var url = this.$url('update'), request;

        if(url) {

          // If bound, update
          if(_patch) {
            request = {
              method: this.$type.getProperty('patchMethod', 'PATCH'), // allow user to override patch method
              url: url,
              // Use special mask for patches, mask everything that is not in the patch list.
              data: this.$wrap(function(_name) {
                _name = _name.replace('[]', '');
                for(var i = 0, l = _patch.length; i < l; i++) {
                  if(_name === _patch[i] ||
                    _name.indexOf(_patch[i] + '.') === 0 ||
                    _patch[i].indexOf(_name + '.') === 0
                  ) { return false; }
                }

                return true;
              })
            };
          } else {
            request = { method: 'PUT', url: url, data: this.$wrap(Utils.UPDATE_MASK) };
          }

          this
            .$dispatch('before-update', [request, !!_patch])
            .$dispatch('before-save', [request])
            .$send(request, function(_response) {
              this
                .$unwrap(_response.data)
                .$dispatch('after-update', [_response, !!_patch])
                .$dispatch('after-save', [_response]);
            }, function(_response) {
              this
                .$dispatch('after-update-error', [_response, !!_patch])
                .$dispatch('after-save-error', [_response]);
            });
        } else {
          // If not bound create.
          url = this.$url('create') || this.$scope.$url();
          Utils.assert(!!url, 'Cant $create if parent scope is not bound');

          request = { method: 'POST', url: url, data: this.$wrap(Utils.CREATE_MASK) };
          this
            .$dispatch('before-save', [request])
            .$dispatch('before-create', [request])
            .$send(request, function(_response) {
              this.$unwrap(_response.data);

              // reveal item (if not yet positioned)
              if(this.$scope.$isCollection && this.$position === undefined && !this.$preventReveal) {
                this.$scope.$add(this, this.$revealAt);
              }

              this
                .$dispatch('after-create', [_response])
                .$dispatch('after-save', [_response]);
            }, function(_response) {
              this
                .$dispatch('after-create-error', [_response])
                .$dispatch('after-save-error', [_response]);
            });
        }
      });
    },

    /**
     * @memberof RecordApi#
     *
     * @description Begin a server request to destroy the resource.
     *
     * The request's promise can be accessed using the `$asPromise` method.
     *
     * @return {RecordApi} this
     */
    $destroy: function() {
      return this.$action(function() {
        var url = this.$url('destroy');
        if(url)
        {
          var request = { method: 'DELETE', url: url };

          this
            .$dispatch('before-destroy', [request])
            .$send(request, function(_response) {

              // remove from scope
              if(this.$scope.$remove) {
                this.$scope.$remove(this);
              }

              this.$dispatch('after-destroy', [_response]);
            }, function(_response) {
              this.$dispatch('after-destroy-error', [_response]);
            });
        }
        else
        {
          // If not yet bound, just remove from parent
          if(this.$scope.$remove) this.$scope.$remove(this);
        }
      });
    },

    // Collection related methods.

    /**
     * @memberof RecordApi#
     *
     * @description Changes the location of the object in the bound collection.
     *
     * If object hasn't been revealed, then this method will change the index where object will be revealed at.
     *
     * @param  {integer} _to New object position (index)
     * @return {RecordApi} this
     */
    $moveTo: function(_to) {
      if(this.$position !== undefined) {
        // TODO: move item to given index.
        // TODO: callback
      } else {
        this.$revealAt = _to;
      }
      return this;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Reveal in collection
     *
     * If instance is bound to a collection and it hasnt been revealed (because it's new and hasn't been saved),
     * then calling this method without parameters will force the object to be added to the collection.
     *
     * If this method is called with **_show** set to `false`, then the object wont be revealed by a save operation.
     *
     * @param  {boolean} _show Whether to reveal inmediatelly or prevent automatic reveal.
     * @return {RecordApi} this
     */
    $reveal: function(_show) {
      if(_show === undefined || _show) {
        this.$scope.$add(this, this.$revealAt);
      } else {
        this.$preventReveal = true;
      }
      return this;
    }
  };

}]);<commit_msg>feat(RecordApi): adds $isNew method<commit_after>'use strict';

RMModule.factory('RMRecordApi', ['RMUtils', function(Utils) {

  /**
   * @class RelationScope
   *
   * @description
   *
   * Special scope a record provides to resources related via hasMany or hasOne relation.
   */
  var RelationScope = function(_scope, _target, _partial) {
    this.$scope = _scope;
    this.$target = _target;
    this.$partial = Utils.cleanUrl(_partial);
  };

  RelationScope.prototype = {

    $nestedUrl: function() {
      return Utils.joinUrl(this.$scope.$url(), this.$partial);
    },

    // url is nested for collections and nested records
    $urlFor: function(_resource) {
      if(_resource.$isCollection || this.$target.isNested()) {
        return this.$nestedUrl();
      } else {
        return this.$target.$urlFor(_resource);
      }
    },

    // a record's fetch url is always nested
    $fetchUrlFor: function(/* _resource */) {
      return this.$nestedUrl();
    },

    // create is not posible in nested members
    $createUrlFor: function() {
      return null;
    }
  };

  /**
   * @class RecordApi
   * @extends CommonApi
   *
   * @property {object} $scope The record's scope (see {@link ScopeApi})
   * @property {mixed} $pk The record's primary key
   *
   * @description
   *
   * Provides record synchronization and manipulation methods. This is the base API for every restmod record.
   *
   * TODO: Talk about the object lifecycle.
   *
   * ### Object lifecycle hooks
   *
   * For `$fetch`:
   *
   * * before-fetch
   * * before-request
   * * after-request[-error]
   * * after-feed (only called if no errors)
   * * after-fetch[-error]
   *
   * For `$save` when creating:
   *
   * * before-render
   * * before-save
   * * before-create
   * * before-request
   * * after-request[-error]
   * * after-feed (only called if no errors)
   * * after-create[-error]
   * * after-save[-error]
   *
   * For `$save` when updating:
   *
   * * before-render
   * * before-save
   * * before-update
   * * before-request
   * * after-request[-error]
   * * after-feed (only called if no errors)
   * * after-update[-error]
   * * after-save[-error]
   *
   * For `$destroy`:
   *
   * * before-destroy
   * * before-request
   * * after-request[-error]
   * * after-destroy[-error]
   *
   * @property {mixed} $pk The record primary key
   * @property {object} $scope The collection scope (hierarchical scope, not angular scope)
   */
	return {

    /**
     * @memberof RecordApi#
     *
     * @description Called by record constructor on initialization.
     *
     * Note: Is better to add a hook to after-init than overriding this method.
     */
    $initialize: function() {
      // apply defaults
      this.$super();

      // after initialization hook
      // TODO: put this on $new so it can use stacked DSP?
      this.$dispatch('after-init');
    },

    /**
     * @memberof RecordApi#
     *
     * @description Checks whether a record is new or not
     *
     * @return {boolean} True if record is new.
     */
    $isNew: function() {
      return this.$pk === undefined || this.$pk === null;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Called the resource's scope $urlFor method to build the url for the record using the proper scope.
     *
     * By default the resource partial url is just its `$pk` property. This can be overriden to provide other routing approaches.
     *
     * @return {string} The resource partial url
     */
    $buildUrl: function(_scope) {
      return this.$isNew() ? null : Utils.joinUrl(_scope.$url(), this.$pk + '');
    },

    /**
     * @memberof RecordApi#
     *
     * @description Default item child scope factory.
     *
     * By default, no create url is provided and the update/destroy url providers
     * attempt to first use the unscoped resource url.
     *
     * // TODO: create special api to hold scope (so it is not necessary to recreate the whole object every time.)
     *
     * @param {mixed} _for Scope target type, accepts any model class.
     * @param {string} _partial Partial route.
     * @return {RelationScope} New scope.
     */
    $buildScope: function(_for, _partial) {
      if(_for.$buildOwnScope) {
        // TODO
      } else {
        return new RelationScope(this, _for, _partial);
      }
    },

    /**
     * @memberof RecordApi#
     *
     * @description Iterates over the object non-private properties
     *
     * @param {function} _fun Function to call for each
     * @return {RecordApi} self
     */
    $each: function(_fun, _ctx) {
      for(var key in this) {
        if(this.hasOwnProperty(key) && key[0] !== '$') {
          _fun.call(_ctx || this[key], this[key], key);
        }
      }

      return this;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Feed raw data to this instance.
     *
     * @param {object} _raw Raw data to be fed
     * @param {string} _mask 'CRU' mask
     * @return {RecordApi} this
     */
    $decode: function(_raw, _mask) {
      // IDEA: let user override serializer
      this.$type.decode(this, _raw, _mask || Utils.READ_MASK);
      if(this.$isNew()) this.$pk = this.$type.inferKey(_raw); // TODO: warn if key changes
      this.$dispatch('after-feed', [_raw]);
      return this;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Generate data to be sent to the server when creating/updating the resource.
     *
     * @param {string} _mask 'CRU' mask
     * @return {string} raw data
     */
    $encode: function(_mask) {
      var raw = this.$type.encode(this, _mask || Utils.CREATE_MASK);
      this.$dispatch('before-render', [raw]);
      return raw;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Begin a server request for updated resource data.
     *
     * The request's promise can be accessed using the `$asPromise` method.
     *
     * @param {object} _params Optional list of params to be passed to object request.
     * @return {RecordApi} this
     */
    $fetch: function(_params) {
      return this.$action(function() {
        var url = this.$url('fetch');
        Utils.assert(!!url, 'Cant $fetch if resource is not bound');

        var request = { method: 'GET', url: url, params: _params };

        this.$dispatch('before-fetch', [request]);
        this.$send(request, function(_response) {
          this.$unwrap(_response.data);
          this.$dispatch('after-fetch', [_response]);
        }, function(_response) {
          this.$dispatch('after-fetch-error', [_response]);
        });
      });
    },

    /**
     * @memberof RecordApi#
     *
     * @description Copyies another object's non-private properties.
     *
     * This method runs inside the promise chain, so calling
     *
     * ```javascript
     * Bike.$find(1).$extend({ size: "L" }).$save();
     * ```
     * Will first fetch the bike data and after it is loaded the new size will be applied and then the
     * updated model saved.
     *
     * @param {object} _other Object to merge.
     * @return {RecordApi} self
     */
    $extend: function(_other) {
      return this.$action(function() {
        for(var tmp in _other) {
          if (_other.hasOwnProperty(tmp) && tmp[0] !== '$') {
            this[tmp] = _other[tmp];
          }
        }
      });
    },

    /**
     * @memberof RecordApi#
     *
     * @description Shortcut method used to extend and save a model.
     *
     * This method will not force a PUT, if object is new `$update` will attempt to POST.
     *
     * @param {object} _other Data to change
     * @return {RecordApi} self
     */
    $update: function(_other) {
      return this.$extend(_other).$save();
    },

    /**
     * @memberof RecordApi#
     *
     * @description Begin a server request to create/update/patch resource.
     *
     * A patch is only executed if model is identified and a patch property list is given. It is posible to
     * change the method used for PATCH operations by setting the `patchMethod` configuration.
     *
     * If resource is new and it belongs to a collection and it hasnt been revealed, then it will be revealed.
     *
     * The request's promise can be accessed using the `$asPromise` method.
     *
     * @param {array} _patch Optional list of properties to send in update operation.
     * @return {RecordApi} this
     */
    $save: function(_patch) {
      return this.$action(function() {
        var url = this.$url('update'), request;

        if(url) {

          // If bound, update
          if(_patch) {
            request = {
              method: this.$type.getProperty('patchMethod', 'PATCH'), // allow user to override patch method
              url: url,
              // Use special mask for patches, mask everything that is not in the patch list.
              data: this.$wrap(function(_name) {
                _name = _name.replace('[]', '');
                for(var i = 0, l = _patch.length; i < l; i++) {
                  if(_name === _patch[i] ||
                    _name.indexOf(_patch[i] + '.') === 0 ||
                    _patch[i].indexOf(_name + '.') === 0
                  ) { return false; }
                }

                return true;
              })
            };
          } else {
            request = { method: 'PUT', url: url, data: this.$wrap(Utils.UPDATE_MASK) };
          }

          this
            .$dispatch('before-update', [request, !!_patch])
            .$dispatch('before-save', [request])
            .$send(request, function(_response) {
              this
                .$unwrap(_response.data)
                .$dispatch('after-update', [_response, !!_patch])
                .$dispatch('after-save', [_response]);
            }, function(_response) {
              this
                .$dispatch('after-update-error', [_response, !!_patch])
                .$dispatch('after-save-error', [_response]);
            });
        } else {
          // If not bound create.
          url = this.$url('create') || this.$scope.$url();
          Utils.assert(!!url, 'Cant $create if parent scope is not bound');

          request = { method: 'POST', url: url, data: this.$wrap(Utils.CREATE_MASK) };
          this
            .$dispatch('before-save', [request])
            .$dispatch('before-create', [request])
            .$send(request, function(_response) {
              this.$unwrap(_response.data);

              // reveal item (if not yet positioned)
              if(this.$scope.$isCollection && this.$position === undefined && !this.$preventReveal) {
                this.$scope.$add(this, this.$revealAt);
              }

              this
                .$dispatch('after-create', [_response])
                .$dispatch('after-save', [_response]);
            }, function(_response) {
              this
                .$dispatch('after-create-error', [_response])
                .$dispatch('after-save-error', [_response]);
            });
        }
      });
    },

    /**
     * @memberof RecordApi#
     *
     * @description Begin a server request to destroy the resource.
     *
     * The request's promise can be accessed using the `$asPromise` method.
     *
     * @return {RecordApi} this
     */
    $destroy: function() {
      return this.$action(function() {
        var url = this.$url('destroy');
        if(url)
        {
          var request = { method: 'DELETE', url: url };

          this
            .$dispatch('before-destroy', [request])
            .$send(request, function(_response) {

              // remove from scope
              if(this.$scope.$remove) {
                this.$scope.$remove(this);
              }

              this.$dispatch('after-destroy', [_response]);
            }, function(_response) {
              this.$dispatch('after-destroy-error', [_response]);
            });
        }
        else
        {
          // If not yet bound, just remove from parent
          if(this.$scope.$remove) this.$scope.$remove(this);
        }
      });
    },

    // Collection related methods.

    /**
     * @memberof RecordApi#
     *
     * @description Changes the location of the object in the bound collection.
     *
     * If object hasn't been revealed, then this method will change the index where object will be revealed at.
     *
     * @param  {integer} _to New object position (index)
     * @return {RecordApi} this
     */
    $moveTo: function(_to) {
      if(this.$position !== undefined) {
        // TODO: move item to given index.
        // TODO: callback
      } else {
        this.$revealAt = _to;
      }
      return this;
    },

    /**
     * @memberof RecordApi#
     *
     * @description Reveal in collection
     *
     * If instance is bound to a collection and it hasnt been revealed (because it's new and hasn't been saved),
     * then calling this method without parameters will force the object to be added to the collection.
     *
     * If this method is called with **_show** set to `false`, then the object wont be revealed by a save operation.
     *
     * @param  {boolean} _show Whether to reveal inmediatelly or prevent automatic reveal.
     * @return {RecordApi} this
     */
    $reveal: function(_show) {
      if(_show === undefined || _show) {
        this.$scope.$add(this, this.$revealAt);
      } else {
        this.$preventReveal = true;
      }
      return this;
    }
  };

}]);<|endoftext|>


<commit_before>var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-33360321-1']);
_gaq.push(['_setDomainName', 'netforce.com']);
_gaq.push(['_trackPageview']);

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
<commit_msg>remove GA<commit_after><|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");
    fs.writeSync(outFD, data.slice(counter, counter+step), 0, step)
    child_process.execFileSync('/Applications/Xcode.app/Contents/Developer/usr/bi<commit_msg>Fixing punctuation<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");
    fs.writeSync(outFD, data.slice(counter, counter+step), 0, step)
    child_process.execFileSync('/Applications/Xcode.app/Contents/Developer/usr/bin<|endoftext|>


<commit_before>const { Command } = require('discord-akairo');
const { RichEmbed } = require('discord.js');
const xkcd = require('relevant-xkcd');

function exec(message, args){
    const sendComic = comic => {
        const embed = new RichEmbed()
        .setTitle(comic.title)
        .setURL(comic.explainURL)
        .setDescription(comic.altText)
        .setImage(comic.imageURL)
        .setFooter(comic.xkcdURL);

        return message.edit('', { embed });
    };

    if (!args.content){
        return xkcd.fetchRandom().then(sendComic);
    }

    if (!isNaN(args.content) && parseInt(args.content) === 0){
        return xkcd.fetchCurrent().then(sendComic);
    }

    if (!isNaN(args.content)){
        return xkcd.fetchComic(parseInt(args.content)).then(sendComic);
    }

    return xkcd.fetchRelevant(args.content).then(sendComic);
}

module.exports = new Command('xkcd', exec, {
    aliases: ['xkcd'],
    args: [
        {
            id: 'content',
            match: 'content'
        }
    ]
});
<commit_msg>Set xkcd embed color<commit_after>const { Command } = require('discord-akairo');
const { RichEmbed } = require('discord.js');
const xkcd = require('relevant-xkcd');

function exec(message, args){
    const sendComic = comic => {
        const color = this.client.config.color === 'random'
        ? (1 << 24) * Math.random() | 0
        : this.client.config.color === 'auto'
        ? message.guild
        ? this.client.util.displayColor(message.member)
        : 0
        : this.client.config.color || 0;

        const embed = new RichEmbed()
        .setColor(color)
        .setTitle(comic.title)
        .setURL(comic.explainURL)
        .setDescription(comic.altText)
        .setImage(comic.imageURL)
        .setFooter(comic.xkcdURL);

        return message.edit('', { embed });
    };

    if (!args.content){
        return xkcd.fetchRandom().then(sendComic);
    }

    if (!isNaN(args.content) && parseInt(args.content) === 0){
        return xkcd.fetchCurrent().then(sendComic);
    }

    if (!isNaN(args.content)){
        return xkcd.fetchComic(parseInt(args.content)).then(sendComic);
    }

    return xkcd.fetchRelevant(args.content).then(sendComic);
}

module.exports = new Command('xkcd', exec, {
    aliases: ['xkcd'],
    args: [
        {
            id: 'content',
            match: 'content'
        }
    ]
});
<|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 [ 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", le<commit_msg>Who you calling a fool?<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 [ 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", len<|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 [ 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.<commit_msg>Re-updating the readme.<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 [ 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.l<|endoftext|>


<commit_before>'use strict';

var forEach = require('lodash/forEach');
var DocumentSession = require('../model/DocumentSession');
var DocumentChange = require('../model/DocumentChange');
var debounce = require('lodash/debounce');
var cloneDeep = require('lodash/cloneDeep');
var Selection = require('../model/Selection');
var Err = require('../util/Error');

/*
  Session that is connected to a Substance Hub allowing
  collaboration in real-time.

  Requires a connected and authenticated collabClient.
*/
function CollabSession(doc, config) {
  CollabSession.super.call(this, doc, config);

  config = config || {};
  this.config = config;

  this.collabClient = config.collabClient;

  if (config.docVersion) {
    console.warn('config.docVersion is deprecated: Use config.version instead');
  }

  if (config.docVersion) {
    console.warn('config.docId is deprecated: Use config.documentId instead');
  }

  this.version = config.version || config.docVersion;
  this.documentId = config.documentId || config.docId;

  if (config.autoSync !== undefined) {
    this.autoSync = config.autoSync;
  } else {
    this.autoSync = true;
  }

  if (!this.documentId) {
    throw new Err('InvalidArgumentsError', {message: 'documentId is mandatory'});
  }

  if (!this.version) {
    throw new Err('InvalidArgumentsError', {message: 'version is mandatory'});
  }

  // Internal state
  this._connected = false; // gets flipped to true in syncDone
  this._nextChange = null; // next change to be sent over the wire
  this._pendingChange = null; // change that is currently being synced
  this._error = null;

  // Bind handlers
  this._broadCastSelectionUpdateDebounced = debounce(this._broadCastSelectionUpdate, 250);

  // Keep track of collaborators in a session
  this.collaborators = {};

  // This happens on a reconnect
  this.collabClient.on('connected', this._onCollabClientConnected, this);
  this.collabClient.on('disconnected', this._onCollabClientDisconnected, this);

  // Constraints used for computing color indexes
  this.__maxColors = 5;
  this.__nextColorIndex = 0;
  this.collabClient.on('message', this._onMessage.bind(this));

  // Attempt to open a document immediately, but only if the collabClient is
  // already connected. If not the _onConnected handler will take care of it
  // once websocket connection is ready.
  if (this.collabClient.isConnected() && this.autoSync) {
    this.sync();
  }
}

CollabSession.Prototype = function() {

  var _super = CollabSession.super.prototype;

  /*
    A new authenticated collabClient connection is available.

    This happens in a reconnect scenario.
  */
  this._onCollabClientConnected = function() {
    console.log('CollabClient connected');
    // Attempt to sync
    if (this.autoSync) {
      this.sync();
    }
  };

  /*
    Implicit disconnect (server connection drop out)
  */
  this._onCollabClientDisconnected = function() {
    console.log('CollabClient disconnected');
    this._abortSync();
    if (this._connected) {
      this._afterDisconnected();
    }
  };

  /*
    Sets the correct state after a collab session has been disconnected
    either explicitly or triggered by a connection drop out.
  */
  this._afterDisconnected = function() {
    // We remove all collaborators
    this.collaborators = {};
    this.emit('collaborators:changed');
    this._connected = false;
    this.emit('disconnected');
  };

  /*
    Dispatching of remote messages.
  */
  this._onMessage = function(msg) {
    // Skip if message is not addressing this document
    if (msg.documentId !== this.documentId) {
      return false;
    }

    // Delegate
    var actionFn = this[msg.type].bind(this);
    if (!actionFn) {
      console.error('CollabSession: unsupported message', msg.type, msg);
      return false;
    }
    actionFn(cloneDeep(msg));
    return true;
  };

  /*
    Handle errors. This gets called if any request produced
    an error on the server. The error object holds te original
    message we could inspect in a custom error handler to trigger
    certain behavior.
  */
  this.error = function(error) {
    console.error('An error occured', error);
    this._error = error;
    this.emit('error,', error);
    this._abortSync();
  };

  /*
    Unregister event handlers. Call this before throw away
    a CollabSession reference. Otherwise you will leak memory
  */
  this.dispose = function() {
    this.disconnect();
    this.collabClient.off(this);
  };

  /*
    Explicit disconnect initiated by user
  */
  this.disconnect = function() {
    // Let the server know we no longer want to edit this document
    var msg = {
      type: 'disconnect',
      documentId: this.documentId
    };

    // We abort pening syncs
    this._abortSync();
    this._send(msg);
  };

  this.disconnectDone = function() {
    // console.log('disconnect done');
    // Let the server know we no longer want to edit this document
    this._afterDisconnected();
  };

  /*
    Abots the currently running sync.

    This is called _onDisconnect and could be called after a sync request
    times out (not yet implemented)
  */
  this._abortSync = function() {
    var newNextChange = this._nextChange;

    if (this._pendingChange) {
      newNextChange = this._pendingChange;
      // If we have local changes also, we append them to the new nextChange
      if (this._nextChange) {
        newNextChange.ops = newNextChange.ops.concat(this._nextChange.ops);
        newNextChange.after = this._nextChange.after;
      }
      this._pendingChange = null;
    }
    this._error = null;
    this._nextChange = newNextChange;
  };

  /*
    Get next change for sync.

    If there are no local changes we create a change that only
    holds the current selection.
  */
  this._getNextChange = function() {
    var nextChange = this._nextChange;
    if (!nextChange) {
      // Change only holds the current selection
      nextChange = this._getChangeForSelection(this.selection, this.selection);
    }
    return nextChange;
  };

  this.__canSync = function() {
    return this.collabClient.isConnected() && !this._pendingChange;
  };

  /*
    Synchronize with collab server
  */
  this.sync = function() {
    // If there is something to sync and there is no running sync
    if (this.__canSync()) {
      var nextChange = this._getNextChange();
      var msg = {
        type: 'sync',
        documentId: this.documentId,
        version: this.version,
        change: this.serializeChange(nextChange)
      };

      this._send(msg);
      this._pendingChange = nextChange;

      this._nextChange = null;
      this._error = null;
    } else {
      console.error('Can not sync. Either collabClient is not connected or we are already syncing');
    }
  };

  /*
    Sync has completed

    We apply server changes that happened in the meanwhile and we update
    the collaborators (=selections etc.)
  */
  this.syncDone = function(args) {
    var serverChange = args.serverChange;
    var collaborators = args.collaborators;
    var serverVersion = args.version;

    if (serverChange) {
      serverChange = this.deserializeChange(serverChange);
      this._applyRemoteChange(serverChange);
    }

    this.version = serverVersion;

    // Only apply updated collaborators if there are no local cahnges
    // Otherwise they will not be accurate. We can safely skip this
    // here as we know the next sync will be triggered soon. And if
    // followed by an idle phase (_nextChange = null) will give us
    // the latest collaborator records

    this._updateCollaborators(collaborators);
    if (this._nextChange) {
      this._transformCollaboratorSelections(this._nextChange);
    }

    // Important: after sync is done we need to reset _pendingChange and _error
    // In this state we can safely listen to
    this._pendingChange = null;
    this._error = null;

    // Each time the sync worked we consider the system connected
    this._connected = true;

    // TODO: this would trigger too many renders potentially
    // once we have our phases in place we can do this in one go
    if (serverChange) {
      this._notifyChangeListeners(serverChange, { replay: false, remote: true });
    }

    this.emit('collaborators:changed');
    this.emit('connected');

    // Attempt to sync again (maybe we have new local changes)
    this._requestSync();
  };

  /*
    Triggers a new sync if there is a new change and no pending sync
  */
  this._requestSync = function() {
    if (this._nextChange && this.__canSync()) {
      this.sync();
    }
  };

  /*
    We record all local changes into a single change (aka commit) that
  */
  this._recordChange = function(change) {
    if (!this._nextChange) {
      this._nextChange = change;
    } else {
      // Merge new change into nextCommit
      this._nextChange.ops = this._nextChange.ops.concat(change.ops);
      this._nextChange.after = change.after;
    }
    this._requestSync();
  };

  /*
    When selection is changed explicitly by the user we broadcast
    that update to other collaborators
  */
  this.setSelection = function(sel) {
    // We just remember beforeSel on the CollabSession (need for connect use-case)
    var beforeSel = this.selection;
    _super.setSelection.call(this, sel);
    this._broadCastSelectionUpdateDebounced(beforeSel, sel);
  };

  /*
    Takes beforeSel + afterSel and wraps it in a no-op DocumentChange
  */
  this._getChangeForSelection = function(beforeSel, afterSel) {
    var change = new DocumentChange([], {
      selection: beforeSel
    }, {
      selection: afterSel
    });
    return change;
  };

  /*
    Returns true if there are local changes
  */
  this._hasLocalChanges = function() {
    return this._nextChange && this._nextChange.ops.length > 0;
  };

  /*
    Send selection update to other collaborators
  */
  this._broadCastSelectionUpdate = function(beforeSel, afterSel) {
    if (this._nextChange) {
      this._nextChange.after.selection = afterSel;
    } else {
      this._nextChange = this._getChangeForSelection(beforeSel, afterSel);
    }
    this._requestSync();
  };

  this.afterDocumentChange = function(change, info) {
    _super.afterDocumentChange.apply(this, arguments);

    // Record local changes into nextCommit
    if (!info.remote) {
      this._recordChange(change);
    }
  };

  /*
    Apply a change to the document
  */
  this._applyRemoteChange = function(change) {
    this.stage._apply(change);
    this.doc._apply(change);

    // Only undo+redo history is updated according to the new change
    this._transformLocalChangeHistory(change);
    this._transformSelection(change);

    // We need to notify the change listeners so the UI gets updated
    // We pass replay: false, so this does not become part of the undo
    // history.
    // this._notifyChangeListeners(change, { replay: false, remote: true });
    return change;
  };

  this.getCollaborators = function() {
    return this.collaborators;
  };

  /*
    Get a session index which is used e.g. for styling user selections.

    Note: this implementation considers that collaborators can disappear,
          thus sessionIndex can be used when a new collaborator
          appears.
  */
  this._getNextSessionIndex = function() {
    if (this.sessionIdPool.length === 0) {
      var collabCount = Object.keys(this.collaborators).length;
      this.sessionIdPool.push(collabCount);
    }
    return this.sessionIdPool.shift();
  };

  this.isConnected = function() {
    return this._connected;
  };

  /*
    IDEA: we could check if anything changes and only then
    emit the collaborators:changed event
    this would solve cases where the user selection gets destroyed
    because of many collaboratorSelection updates
  */
  this._updateCollaborators = function(collaborators) {
    forEach(collaborators, function(collaborator, collaboratorId) {
      if (collaborator) {
        var old = this.collaborators[collaboratorId];
        // Assign colorIndex (try to restore from old record)
        collaborator.colorIndex = old ? old.colorIndex : this._getNextColorIndex();
        // Parse selection from record
        collaborator.selection = Selection.fromJSON(collaborator.selection);
        collaborator.selection.attach(this.doc);

        this.collaborators[collaboratorId] = collaborator;
      } else {
        delete this.collaborators[collaboratorId];
      }
    }.bind(this));
    // this.emit('collaborators:changed');
  };

  /*
    Apply remote update

    We receive an update from the server. We only apply the remote change if
    there's no pending commit. applyRemoteUpdate is also called for selection
    updates.

    If we are currently in the middle of a sync or have local changes we just
    ignore the update. We will receive all server updates on the next syncDone.
  */
  this.update = function(args) {
    var serverChange = args.change;
    var collaborators = args.collaborators;
    var serverVersion = args.version;

    if (!this._nextChange && !this._pendingChange) {
      if (serverChange) {
        serverChange = this.deserializeChange(serverChange);
        this._applyRemoteChange(serverChange);
      }
      if (serverVersion) {
        this.version = serverVersion;
      }
      this._updateCollaborators(collaborators);
      if (serverChange) {
        this._notifyChangeListeners(serverChange, { replay: false, remote: true });
      }
      this.emit('collaborators:changed');
    } else {
      console.log('skipped update. we wait for a sync to complete');
    }
  };

  this.serializeChange = function(change) {
    return change.toJSON();
  };

  this.deserializeChange = function(serializedChange) {
    return DocumentChange.fromJSON(serializedChange);
  };

  /*
    Send message

    Returns true if sent, false if not sent (e.g. when not connected)
  */
  this._send = function(msg) {
    if (this.collabClient.isConnected()) {
      this.collabClient.send(msg);
      return true;
    } else {
      console.warn('Try not to call _send when disconnected. Skipping message', msg);
      return false;
    }
  };

  /*
    Get color index for rendering cursors and selections in round robin style.
    Note: This implementation considers a configured maxColors value. The
    first color will be reused as more then maxColors collaborators arrive.
  */
  this._getNextColorIndex = function() {
    var colorIndex = this.__nextColorIndex;
    this.__nextColorIndex = (this.__nextColorIndex + 1) % this.__maxColors;
    return colorIndex + 1; // so we can 1..5 instead of 0..4
  };
};

DocumentSession.extend(CollabSession);

module.exports = CollabSession;
<commit_msg>Only emit collaborators:changed when there are real changes.<commit_after>'use strict';

var forEach = require('lodash/forEach');
var DocumentSession = require('../model/DocumentSession');
var DocumentChange = require('../model/DocumentChange');
var debounce = require('lodash/debounce');
var cloneDeep = require('lodash/cloneDeep');
var Selection = require('../model/Selection');
var Err = require('../util/Error');

/*
  Session that is connected to a Substance Hub allowing
  collaboration in real-time.

  Requires a connected and authenticated collabClient.
*/
function CollabSession(doc, config) {
  CollabSession.super.call(this, doc, config);

  config = config || {};
  this.config = config;
  this.collabClient = config.collabClient;

  if (config.docVersion) {
    console.warn('config.docVersion is deprecated: Use config.version instead');
  }

  if (config.docVersion) {
    console.warn('config.docId is deprecated: Use config.documentId instead');
  }

  this.version = config.version || config.docVersion;
  this.documentId = config.documentId || config.docId;

  if (config.autoSync !== undefined) {
    this.autoSync = config.autoSync;
  } else {
    this.autoSync = true;
  }

  if (!this.documentId) {
    throw new Err('InvalidArgumentsError', {message: 'documentId is mandatory'});
  }

  if (!this.version) {
    throw new Err('InvalidArgumentsError', {message: 'version is mandatory'});
  }

  // Internal state
  this._connected = false; // gets flipped to true in syncDone
  this._nextChange = null; // next change to be sent over the wire
  this._pendingChange = null; // change that is currently being synced
  this._error = null;

  // Bind handlers
  this._broadCastSelectionUpdateDebounced = debounce(this._broadCastSelectionUpdate, 250);

  // Keep track of collaborators in a session
  this.collaborators = {};

  // This happens on a reconnect
  this.collabClient.on('connected', this._onCollabClientConnected, this);
  this.collabClient.on('disconnected', this._onCollabClientDisconnected, this);

  // Constraints used for computing color indexes
  this.__maxColors = 5;
  this.__nextColorIndex = 0;
  this.collabClient.on('message', this._onMessage.bind(this));

  // Attempt to open a document immediately, but only if the collabClient is
  // already connected. If not the _onConnected handler will take care of it
  // once websocket connection is ready.
  if (this.collabClient.isConnected() && this.autoSync) {
    this.sync();
  }
}

CollabSession.Prototype = function() {

  var _super = CollabSession.super.prototype;

  /*
    A new authenticated collabClient connection is available.

    This happens in a reconnect scenario.
  */
  this._onCollabClientConnected = function() {
    console.log('CollabClient connected');
    // Attempt to sync
    if (this.autoSync) {
      this.sync();
    }
  };

  /*
    Implicit disconnect (server connection drop out)
  */
  this._onCollabClientDisconnected = function() {
    console.log('CollabClient disconnected');
    this._abortSync();
    if (this._connected) {
      this._afterDisconnected();
    }
  };

  /*
    Sets the correct state after a collab session has been disconnected
    either explicitly or triggered by a connection drop out.
  */
  this._afterDisconnected = function() {
    // We remove all collaborators
    this.collaborators = {};
    this.emit('collaborators:changed');
    this._connected = false;
    this.emit('disconnected');
  };

  /*
    Dispatching of remote messages.
  */
  this._onMessage = function(msg) {
    // Skip if message is not addressing this document
    if (msg.documentId !== this.documentId) {
      return false;
    }

    // Delegate
    var actionFn = this[msg.type].bind(this);
    if (!actionFn) {
      console.error('CollabSession: unsupported message', msg.type, msg);
      return false;
    }
    actionFn(cloneDeep(msg));
    return true;
  };

  /*
    Handle errors. This gets called if any request produced
    an error on the server. The error object holds te original
    message we could inspect in a custom error handler to trigger
    certain behavior.
  */
  this.error = function(error) {
    console.error('An error occured', error);
    this._error = error;
    this.emit('error,', error);
    this._abortSync();
  };

  /*
    Unregister event handlers. Call this before throw away
    a CollabSession reference. Otherwise you will leak memory
  */
  this.dispose = function() {
    this.disconnect();
    this.collabClient.off(this);
  };

  /*
    Explicit disconnect initiated by user
  */
  this.disconnect = function() {
    // Let the server know we no longer want to edit this document
    var msg = {
      type: 'disconnect',
      documentId: this.documentId
    };

    // We abort pening syncs
    this._abortSync();
    this._send(msg);
  };

  this.disconnectDone = function() {
    // console.log('disconnect done');
    // Let the server know we no longer want to edit this document
    this._afterDisconnected();
  };

  /*
    Abots the currently running sync.

    This is called _onDisconnect and could be called after a sync request
    times out (not yet implemented)
  */
  this._abortSync = function() {
    var newNextChange = this._nextChange;

    if (this._pendingChange) {
      newNextChange = this._pendingChange;
      // If we have local changes also, we append them to the new nextChange
      if (this._nextChange) {
        newNextChange.ops = newNextChange.ops.concat(this._nextChange.ops);
        newNextChange.after = this._nextChange.after;
      }
      this._pendingChange = null;
    }
    this._error = null;
    this._nextChange = newNextChange;
  };

  /*
    Get next change for sync.

    If there are no local changes we create a change that only
    holds the current selection.
  */
  this._getNextChange = function() {
    var nextChange = this._nextChange;
    if (!nextChange) {
      // Change only holds the current selection
      nextChange = this._getChangeForSelection(this.selection, this.selection);
    }
    return nextChange;
  };

  this.__canSync = function() {
    return this.collabClient.isConnected() && !this._pendingChange;
  };

  /*
    Synchronize with collab server
  */
  this.sync = function() {
    // If there is something to sync and there is no running sync
    if (this.__canSync()) {
      var nextChange = this._getNextChange();
      var msg = {
        type: 'sync',
        documentId: this.documentId,
        version: this.version,
        change: this.serializeChange(nextChange)
      };

      this._send(msg);
      this._pendingChange = nextChange;

      this._nextChange = null;
      this._error = null;
    } else {
      console.error('Can not sync. Either collabClient is not connected or we are already syncing');
    }
  };

  /*
    Sync has completed

    We apply server changes that happened in the meanwhile and we update
    the collaborators (=selections etc.)
  */
  this.syncDone = function(args) {
    var serverChange = args.serverChange;
    var collaborators = args.collaborators;
    var serverVersion = args.version;

    if (serverChange) {
      serverChange = this.deserializeChange(serverChange);
      this._applyRemoteChange(serverChange);
    }

    this.version = serverVersion;

    // Only apply updated collaborators if there are no local cahnges
    // Otherwise they will not be accurate. We can safely skip this
    // here as we know the next sync will be triggered soon. And if
    // followed by an idle phase (_nextChange = null) will give us
    // the latest collaborator records
    var collaboratorsChanged = this._updateCollaborators(collaborators);
    if (this._nextChange) {
      this._transformCollaboratorSelections(this._nextChange);
    }

    // Important: after sync is done we need to reset _pendingChange and _error
    // In this state we can safely listen to
    this._pendingChange = null;
    this._error = null;

    // Each time the sync worked we consider the system connected
    this._connected = true;

    // TODO: this would trigger too many renders potentially
    // once we have our phases in place we can do this in one go
    if (serverChange) {
      this._notifyChangeListeners(serverChange, { replay: false, remote: true });
    }

    if (collaboratorsChanged) {
      this.emit('collaborators:changed');
    }
    this.emit('connected');

    // Attempt to sync again (maybe we have new local changes)
    this._requestSync();
  };

  /*
    Triggers a new sync if there is a new change and no pending sync
  */
  this._requestSync = function() {
    if (this._nextChange && this.__canSync()) {
      this.sync();
    }
  };

  /*
    We record all local changes into a single change (aka commit) that
  */
  this._recordChange = function(change) {
    if (!this._nextChange) {
      this._nextChange = change;
    } else {
      // Merge new change into nextCommit
      this._nextChange.ops = this._nextChange.ops.concat(change.ops);
      this._nextChange.after = change.after;
    }
    this._requestSync();
  };

  /*
    When selection is changed explicitly by the user we broadcast
    that update to other collaborators
  */
  this.setSelection = function(sel) {
    // We just remember beforeSel on the CollabSession (need for connect use-case)
    var beforeSel = this.selection;
    _super.setSelection.call(this, sel);
    this._broadCastSelectionUpdateDebounced(beforeSel, sel);
  };

  /*
    Takes beforeSel + afterSel and wraps it in a no-op DocumentChange
  */
  this._getChangeForSelection = function(beforeSel, afterSel) {
    var change = new DocumentChange([], {
      selection: beforeSel
    }, {
      selection: afterSel
    });
    return change;
  };

  /*
    Returns true if there are local changes
  */
  this._hasLocalChanges = function() {
    return this._nextChange && this._nextChange.ops.length > 0;
  };

  /*
    Send selection update to other collaborators
  */
  this._broadCastSelectionUpdate = function(beforeSel, afterSel) {
    if (this._nextChange) {
      this._nextChange.after.selection = afterSel;
    } else {
      this._nextChange = this._getChangeForSelection(beforeSel, afterSel);
    }
    this._requestSync();
  };

  this.afterDocumentChange = function(change, info) {
    _super.afterDocumentChange.apply(this, arguments);

    // Record local changes into nextCommit
    if (!info.remote) {
      this._recordChange(change);
    }
  };

  /*
    Apply a change to the document
  */
  this._applyRemoteChange = function(change) {
    this.stage._apply(change);
    this.doc._apply(change);

    // Only undo+redo history is updated according to the new change
    this._transformLocalChangeHistory(change);
    this._transformSelection(change);

    // We need to notify the change listeners so the UI gets updated
    // We pass replay: false, so this does not become part of the undo
    // history.
    // this._notifyChangeListeners(change, { replay: false, remote: true });
    return change;
  };

  this.getCollaborators = function() {
    return this.collaborators;
  };

  /*
    Get a session index which is used e.g. for styling user selections.

    Note: this implementation considers that collaborators can disappear,
          thus sessionIndex can be used when a new collaborator
          appears.
  */
  this._getNextSessionIndex = function() {
    if (this.sessionIdPool.length === 0) {
      var collabCount = Object.keys(this.collaborators).length;
      this.sessionIdPool.push(collabCount);
    }
    return this.sessionIdPool.shift();
  };

  this.isConnected = function() {
    return this._connected;
  };

  /*
    IDEA: we could check if anything changes and only then
    emit the collaborators:changed event
    this would solve cases where the user selection gets destroyed
    because of many collaboratorSelection updates
  */
  this._updateCollaborators = function(collaborators) {
    var changed = false;

    forEach(collaborators, function(collaborator, collaboratorId) {
      if (collaborator) {
        var oldSelection;
        var old = this.collaborators[collaboratorId];
        if (old) {
          oldSelection = old.selection;
        }
        var newSelection = Selection.fromJSON(collaborator.selection);
        newSelection.attach(this.doc);

        // Assign colorIndex (try to restore from old record)
        collaborator.colorIndex = old ? old.colorIndex : this._getNextColorIndex();
        collaborator.selection = newSelection;
        this.collaborators[collaboratorId] = collaborator;
        if (!newSelection.equals(oldSelection)) {
          changed = true;
        }
      } else {
        changed = true; // Collaborator left, so we need an update
        delete this.collaborators[collaboratorId];
      }
    }.bind(this));
    return changed;
  };

  /*
    Apply remote update

    We receive an update from the server. We only apply the remote change if
    there's no pending commit. applyRemoteUpdate is also called for selection
    updates.

    If we are currently in the middle of a sync or have local changes we just
    ignore the update. We will receive all server updates on the next syncDone.
  */
  this.update = function(args) {
    var serverChange = args.change;
    var collaborators = args.collaborators;
    var serverVersion = args.version;

    if (!this._nextChange && !this._pendingChange) {
      if (serverChange) {
        serverChange = this.deserializeChange(serverChange);
        this._applyRemoteChange(serverChange);
      }
      if (serverVersion) {
        this.version = serverVersion;
      }
      var collaboratorsChanged = this._updateCollaborators(collaborators);
      if (serverChange) {
        this._notifyChangeListeners(serverChange, { replay: false, remote: true });
      }
      if (collaboratorsChanged) {
        this.emit('collaborators:changed');
      }
    } else {
      console.log('skipped update. we wait for a sync to complete');
    }
  };

  this.serializeChange = function(change) {
    return change.toJSON();
  };

  this.deserializeChange = function(serializedChange) {
    return DocumentChange.fromJSON(serializedChange);
  };

  /*
    Send message

    Returns true if sent, false if not sent (e.g. when not connected)
  */
  this._send = function(msg) {
    if (this.collabClient.isConnected()) {
      this.collabClient.send(msg);
      return true;
    } else {
      console.warn('Try not to call _send when disconnected. Skipping message', msg);
      return false;
    }
  };

  /*
    Get color index for rendering cursors and selections in round robin style.
    Note: This implementation considers a configured maxColors value. The
    first color will be reused as more then maxColors collaborators arrive.
  */
  this._getNextColorIndex = function() {
    var colorIndex = this.__nextColorIndex;
    this.__nextColorIndex = (this.__nextColorIndex + 1) % this.__maxColors;
    return colorIndex + 1; // so we can 1..5 instead of 0..4
  };
};

DocumentSession.extend(CollabSession);

module.exports = CollabSession;
<|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, '<commit_msg>Work in Progress<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, '-<|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",
  "Rea<commit_msg>AAAAAAAAAAARGH!<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",
  "Real<|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<commit_msg>Really commit all the required changes<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 <|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_proces<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<|endoftext|>