<commit_before>var _ = require('lodash');
var buildConfig = require('./scripts/build/config');
var fs = require('fs');
var gulp = require('gulp');
var karma = require('karma').server;
var path = require('path');
var VinylFile = require('vinyl');
var argv = require('yargs').argv;
var cached = require('gulp-cached');
var concat = require('gulp-concat');
var del = require('del');
var gulpif = require('gulp-if');
var rename = require('gulp-rename');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var through2 = require('through2');
var runSequence = require('run-sequence');
var watch = require('gulp-watch');
var exec = require('child_process').exec;
var babel = require('gulp-babel');
var traceur = require('gulp-traceur');
var webpack = require('gulp-webpack');
var lazypipe = require('lazypipe');
var cache = require('gulp-cached');

gulp.task('clean.build', function() {
  runSequence(
    'clean',
    'transpile',
    'bundle.deps',
    'bundle.js',
    'examples',
    'sass',
    'fonts',
    'polyfills');
})

gulp.task('build', function() {
  runSequence(
    'transpile',
    'bundle.js',
    'examples',
    'sass',
    'fonts',
    'polyfills');
})

gulp.task('watch', function() {

  runSequence(
    'transpile',
    'bundle.js',
    'examples',
    'sass',
    'fonts',
    'polyfills',

    function() {
      watch(['ionic/**/*.js', '!ionic/components/*/test/**/*'], function() {
        runSequence(
          'transpile',
          'bundle.js',
          'examples'
        )
      });

      watch('ionic/components/*/test/**/*', function() {
        gulp.start('examples');
      });

      watch('ionic/components/**/*.scss', function() {
        gulp.start('sass');
      });
    })
});

function doubleCheckDistFiles() {
  if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/css')) {
    gulp.start('sass');
  }

  if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/fonts')) {
    gulp.start('fonts');
  }
}

gulp.task('clean', function(done) {
  del(['dist/'], done);
});

var traceurOptions = {
  annotations: true,
  types: true,
  outputLanguage: 'es6'
}

var babelOptions = {
  optional: ['es7.decorators'],
  /*plugins: [
    './transformers/disable-define',
    'angular2-annotations',
    'type-assertion:after'
  ],*/
  modules: "system",
  moduleIds: true,
  getModuleId: function(name) {
    return "ionic/" + name;
  }
};

gulp.task('transpile', function() {
  return gulp.src(['ionic/**/*.js', '!ionic/components/*/test/**/*'])
             .pipe(cache('transpile', { optimizeMemory: true }))
             .pipe(traceur(traceurOptions))
             .pipe(gulp.dest('dist/js/es6/ionic'))
             .pipe(babel(babelOptions))
             .pipe(gulp.dest('dist/js/es5/ionic'))
});

gulp.task('bundle.js', function() {
  return gulp.src('dist/js/es5/ionic/**/*.js')
             .pipe(concat('ionic.bundle.js'))
             .pipe(gulp.dest('dist/js/'));
});

gulp.task('bundle.deps', function() {
  var Builder = require('systemjs-builder')
  var builder = new Builder();
  return builder.loadConfig('config.js').then(function(){
    // add ionic and angular2 build paths, since config.js is loaded at runtime from
    // tests we don't want to put them there
    builder.config({
      baseURL: 'file:' + process.cwd(),
      paths : {
        "ionic/*": "dist/js/es6/ionic/*.js",
        "angular2/*": "angular2/dist/js/dev/es6/angular2/*.es6",
      }
    });
    return builder.build('dist/js/es6/ionic/**/* - [dist/js/es6/ionic/**/*]', 'dist/js/dependencies.js');
  }, function(error){
    console.log("Error building dependency bundle, have you transpiled Ionic and/or built Angular2 yet?");
    throw new Error(error);
  })
});

gulp.task('examples', function() {
  var buildTest = lazypipe()
             .pipe(traceur, traceurOptions)
             //.pipe(babel, babelOptions) Let SystemJS load index.js at runtime, saves build time

  // Get each test folder with gulp.src
  return gulp.src('ionic/components/*/test/*/**/*')
    .pipe(cache('examples', { optimizeMemory: true }))
    .pipe(gulpif(/.js$/, buildTest()))
    .pipe(gulpif(/index.js$/, createIndexHTML()))
    .pipe(rename(function(file) {
      file.dirname = file.dirname.replace(path.sep + 'test' + path.sep, path.sep)
    }))
    .pipe(gulp.dest('dist/examples/'))

  function createIndexHTML() {
    var indexContents = _.template(
      fs.readFileSync('scripts/e2e/ionic.template.html')
    )({
      buildConfig: buildConfig
    });

    return through2.obj(function(file, enc, next) {
      var self = this;
      self.push(new VinylFile({
        base: file.base,
        contents: new Buffer(indexContents),
        path: path.join(path.dirname(file.path), 'index.html'),
      }));
      next(null, file);
    });
  }
});

gulp.task('sass', function() {
  return gulp.src('ionic/ionic.scss')
    .pipe(sass({
      onError: function(err) {
        console.log(err)
      }
    }))
    .pipe(autoprefixer(buildConfig.autoprefixer))
    .pipe(gulp.dest('dist/css/'));
});

gulp.task('fonts', function() {
  return gulp.src('ionic/components/icon/fonts/**/*')
    .pipe(gulp.dest('dist/fonts'));
});

gulp.task('polyfills', function() {
  return gulp.src('ionic/animations/web-animations*')
    .pipe(gulp.dest('dist/polyfills'));
});

gulp.task('link.angular', function() {
  if (!fs.existsSync('../angular-ionic')) {
    throw new Error("../angular-ionic doesn't exist. Run gulp update.angular first");
  }
  linkAngular();
});

gulp.task('update.angular', function(done) {

  if (!fs.existsSync('../angular-ionic')) {
    console.log('cloning angular master...');
    exec('git clone git@github.com:angular/angular ../angular-ionic', function() {
      linkAngular();
      npmInstall();
    });

  } else {
    console.log('angular master: cleaning modules');
    del(['../angular-ionic/modules'], function() {

      console.log('angular master: reset --hard...');
      exec('git reset --hard origin/master', {cwd: '../angular-ionic'}, function () {

        console.log('angular master: git pull origin master...');
        exec('git pull origin master', function () {
          npmInstall();
        });
      });

    })
  }

  function npmInstall() {
    console.log('angular master: npm install (may take a while, chill out)...');
    exec('npm install', {cwd: '../angular-ionic'}, function () {
      done();
    });
  }

});

function linkAngular() {
 if (!fs.existsSync('angular2')) {
    console.log("Symlinking ../angular-ionic to angular2");
    fs.symlinkSync('../angular-ionic', 'angular2');
  }
}

require('./scripts/snapshot/snapshot.task')(gulp, argv, buildConfig);

// gulp.task('watch', ['default'], function() {
//   gulp.watch(buildConfig.src.scss, ['sass'])
//   gulp.watch([].concat(
//     buildConfig.src.js, buildConfig.src.html,
//     'scripts/e2e/index.template.html'
//   ), ['e2e'])
//   gulp.watch([].concat(
//     buildConfig.src.e2e, buildConfig.src.html,
//     'scripts/e2e/index.template.html'
//   ), ['ionic-js'])
// });

gulp.task('karma', function() {
  return karma.start({ configFile: __dirname + '/scripts/test/karma.conf.js' })
});

gulp.task('karma-watch', function() {
  return karma.start({ configFile: __dirname + '/scripts/test/karma-watch.conf.js' })
});

gulp.task('e2e', ['sass'], function() {
  var indexContents = _.template( fs.readFileSync('scripts/e2e/index.template.html') )({
    buildConfig: buildConfig
  });
  var testTemplate = _.template( fs.readFileSync('scripts/e2e/e2e.template.js') )

  var platforms = [
    'android',
    'core',
    'ios',
  ];

  gulp.src(['ionic/**/*.js'])
           .pipe(gulp.dest('dist/src'));

  // Get each test folder with gulp.src
  return gulp.src(buildConfig.src.e2e)
    .pipe(cached('e2e'))
    .pipe(rename(function(file) {
      file.dirname = file.dirname.replace(path.sep + 'test' + path.sep, path.sep)
    }))
    .pipe(gulpif(/main.js$/, processMain()))
    //.pipe(gulpif(/e2e.js$/, createPlatformTests()))
    .pipe(gulp.dest(buildConfig.dist + '/e2e'));

    function processMain() {
      return through2.obj(function(file, enc, next) {
        var self = this;
        self.push(new VinylFile({
          base: file.base,
          contents: new Buffer(indexContents),
          path: path.join(path.dirname(file.path), 'index.html'),
        }));
        next(null, file);
      })
    }

    function createPlatformTests(file) {
      return through2.obj(function(file, enc, next) {
        var self = this
        var relativePath = path.dirname(file.path.replace(/^.*?ionic(\/|\\)components(\/|\\)/, ''))
        var contents = file.contents.toString()
        platforms.forEach(function(platform) {
          var platformContents = testTemplate({
            contents: contents,
            buildConfig: buildConfig,
            relativePath: relativePath,
            platform: platform
          })
          self.push(new VinylFile({
            base: file.base,
            contents: new Buffer(platformContents),
            path: file.path.replace(/e2e.js$/, platform + '.e2e.js')
          }))
        })
        next()
      })
    }

});
<commit_msg>teach an old gulp new tricks<commit_after>var _ = require('lodash');
var buildConfig = require('./scripts/build/config');
var fs = require('fs');
var gulp = require('gulp');
var karma = require('karma').server;
var path = require('path');
var VinylFile = require('vinyl');
var argv = require('yargs').argv;
var cached = require('gulp-cached');
var concat = require('gulp-concat');
var del = require('del');
var gulpif = require('gulp-if');
var rename = require('gulp-rename');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var through2 = require('through2');
var runSequence = require('run-sequence');
var watch = require('gulp-watch');
var exec = require('child_process').exec;
var babel = require('gulp-babel');
var traceur = require('gulp-traceur');
var webpack = require('gulp-webpack');
var lazypipe = require('lazypipe');
var cache = require('gulp-cached');

gulp.task('clean.build', function() {
  runSequence(
    'clean',
    'transpile',
    'bundle.deps',
    'bundle.js',
    'examples',
    'sass',
    'fonts',
    'polyfills');
})

gulp.task('build', function() {
  runSequence(
    'transpile',
    'bundle.js',
    'examples',
    'sass',
    'fonts',
    'polyfills');
})

gulp.task('watch', function() {

  runSequence(
    'transpile',
    'bundle.js',
    'examples',
    'sass',
    'fonts',
    'polyfills',

    function() {
      watch(['ionic/**/*.js', '!ionic/components/*/test/**/*'], function() {
        runSequence(
          'transpile',
          'bundle.js',
          'examples'
        )
      });

      watch('ionic/components/*/test/**/*', function() {
        gulp.start('examples');
      });

      watch('ionic/components/**/*.scss', function() {
        gulp.start('sass');
      });
    })
});

function doubleCheckDistFiles() {
  if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/css')) {
    gulp.start('sass');
  }

  if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/fonts')) {
    gulp.start('fonts');
  }
}

gulp.task('clean', function(done) {
  del(['dist/'], done);
});

var traceurOptions = {
  annotations: true,
  types: true,
  outputLanguage: 'es6'
}

var babelOptions = {
  optional: ['es7.decorators'],
  /*plugins: [
    './transformers/disable-define',
    'angular2-annotations',
    'type-assertion:after'
  ],*/
  modules: "system",
  moduleIds: true,
  getModuleId: function(name) {
    return "ionic/" + name;
  }
};

gulp.task('transpile', function() {
  return gulp.src(['ionic/**/*.js', '!ionic/components/*/test/**/*'])
             .pipe(cache('transpile', { optimizeMemory: true }))
             .pipe(traceur(traceurOptions))
             .pipe(gulp.dest('dist/js/es6/ionic'))
             .pipe(babel(babelOptions))
             .pipe(gulp.dest('dist/js/es5/ionic'))
});

gulp.task('bundle.js', function() {
  return gulp.src('dist/js/es5/ionic/**/*.js')
             .pipe(concat('ionic.bundle.js'))
             .pipe(gulp.dest('dist/js/'));
});

gulp.task('bundle.deps', function() {
  var Builder = require('systemjs-builder')
  var builder = new Builder();
  return builder.loadConfig('config.js').then(function(){
    // add ionic and angular2 build paths, since config.js is loaded at runtime from
    // tests we don't want to put them there
    builder.config({
      baseURL: 'file:' + process.cwd(),
      paths : {
        "ionic/*": "dist/js/es6/ionic/*.js",
        "angular2/*": "angular2/dist/js/dev/es6/angular2/*.es6",
      }
    });
    return builder.build('dist/js/es6/ionic/**/* - [dist/js/es6/ionic/**/*]', 'dist/js/dependencies.js');
  }, function(error){
    console.log("Error building dependency bundle, have you transpiled Ionic and/or built Angular2 yet?");
    throw new Error(error);
  })
});

gulp.task('examples', function() {
  var buildTest = lazypipe()
             .pipe(traceur, traceurOptions)
             //.pipe(babel, babelOptions) Let SystemJS load index.js at runtime, saves build time

  // Get each test folder with gulp.src
  return gulp.src('ionic/components/*/test/*/**/*')
    .pipe(cache('examples', { optimizeMemory: true }))
    .pipe(gulpif(/.js$/, buildTest()))
    .pipe(gulpif(/index.js$/, createIndexHTML()))
    .pipe(rename(function(file) {
      file.dirname = file.dirname.replace(path.sep + 'test' + path.sep, path.sep)
    }))
    .pipe(gulp.dest('dist/examples/'))

  function createIndexHTML() {
    var indexContents = _.template(
      fs.readFileSync('scripts/e2e/ionic.template.html')
    )({
      buildConfig: buildConfig
    });

    return through2.obj(function(file, enc, next) {
      var self = this;
      self.push(new VinylFile({
        base: file.base,
        contents: new Buffer(indexContents),
        path: path.join(path.dirname(file.path), 'index.html'),
      }));
      next(null, file);
    });
  }
});

gulp.task('sass', function() {
  return gulp.src('ionic/ionic.scss')
    .pipe(sass({
      onError: function(err) {
        console.log(err)
      }
    }))
    .pipe(autoprefixer(buildConfig.autoprefixer))
    .pipe(gulp.dest('dist/css/'));
});

gulp.task('fonts', function() {
  return gulp.src('ionic/components/icon/fonts/**/*')
    .pipe(gulp.dest('dist/fonts'));
});

gulp.task('polyfills', function() {
  return gulp.src('ionic/animations/web-animations*')
    .pipe(gulp.dest('dist/polyfills'));
});

gulp.task('link.angular', function() {
  if (!fs.existsSync('../angular-ionic')) {
    throw new Error("../angular-ionic doesn't exist. Run gulp update.angular first");
  }
  linkAngular();
});

gulp.task('update.angular', function(done) {

  if (!fs.existsSync('../angular-ionic')) {
    console.log('cloning angular master...');
    exec('git clone git@github.com:angular/angular ../angular-ionic', function() {
      linkAngular();
      npmInstall();
    });

  } else {
    console.log('angular master: cleaning modules');
    del(['../angular-ionic/modules'], function() {

      console.log('angular master: reset --hard...');
      exec('git reset --hard origin/master', {cwd: '../angular-ionic'}, function () {

        console.log('angular master: git pull origin master...');
        exec('git pull origin master', function () {
          npmInstall();
        });
      });

    })
  }

  function npmInstall() {
    console.log('angular master: npm install (may take a while, chill out)...');
    exec('npm install', {cwd: '../angular-ionic'}, function () {
      done();
    });
  }

});

function linkAngular() {
 if (!fs.existsSync('angular2')) {
    console.log("Symlinking ../angular-ionic to angular2");
    fs.symlinkSync('../angular-ionic', 'angular2');
  }
}

require('./scripts/snapshot/snapshot.task')(gulp, argv, buildConfig);

// gulp.task('watch', ['default'], function() {
//   gulp.watch(buildConfig.src.scss, ['sass'])
//   gulp.watch([].concat(
//     buildConfig.src.js, buildConfig.src.html,
//     'scripts/e2e/index.template.html'
//   ), ['e2e'])
//   gulp.watch([].concat(
//     buildConfig.src.e2e, buildConfig.src.html,
//     'scripts/e2e/index.template.html'
//   ), ['ionic-js'])
// });

gulp.task('karma', function() {
  return karma.start({ configFile: __dirname + '/scripts/test/karma.conf.js' })
});

gulp.task('karma-watch', function() {
  return karma.start({ configFile: __dirname + '/scripts/test/karma-watch.conf.js' })
});

gulp.task('e2e', ['sass'], function() {
  var indexContents = _.template( fs.readFileSync('scripts/e2e/index.template.html') )({
    buildConfig: buildConfig
  });
  var testTemplate = _.template( fs.readFileSync('scripts/e2e/e2e.template.js') )

  var platforms = [
    'android',
    'core',
    'ios',
  ];

  gulp.src(['ionic/**/*.js'])
           .pipe(gulp.dest('dist/src'));

  // Get each test folder with gulp.src
  return gulp.src(buildConfig.src.e2e)
    .pipe(cached('e2e'))
    .pipe(rename(function(file) {
      file.dirname = file.dirname.replace(path.sep + 'test' + path.sep, path.sep)
    }))
    .pipe(gulpif(/main.js$/, processMain()))
    //.pipe(gulpif(/e2e.js$/, createPlatformTests()))
    .pipe(gulp.dest(buildConfig.dist + '/e2e'));

    function processMain() {
      return through2.obj(function(file, enc, next) {
        var self = this;
        self.push(new VinylFile({
          base: file.base,
          contents: new Buffer(indexContents),
          path: path.join(path.dirname(file.path), 'index.html'),
        }));
        next(null, file);
      })
    }

    function createPlatformTests(file) {
      return through2.obj(function(file, enc, next) {
        var self = this
        var relativePath = path.dirname(file.path.replace(/^.*?ionic(\/|\\)components(\/|\\)/, ''))
        var contents = file.contents.toString()
        platforms.forEach(function(platform) {
          var platformContents = testTemplate({
            contents: contents,
            buildConfig: buildConfig,
            relativePath: relativePath,
            platform: platform
          })
          self.push(new VinylFile({
            base: file.base,
            contents: new Buffer(platformContents),
            path: file.path.replace(/e2e.js$/, platform + '.e2e.js')
          }))
        })
        next()
      })
    }

});

/********************************************************************/

gulp.task('old.build', function() {
  runSequence(
    'old.clean',
    'old.ionic.copy.js',
    'old.ionic.examples',
    'old.sass',
    'old.fonts',
    'old.polyfills');
})

gulp.task('old.watch', function() {

  runSequence(
    'old.clean',
    'old.ionic.copy.js',
    'old.ionic.examples',
    'old.sass',
    'old.fonts',
    'old.polyfills',

    function() {
      watch('ionic/**/*.js', function(file) {
        var splt = file.path.split('/');
        var filename = splt[splt.length - 1];

        var dest = file.path.replace(__dirname, '../angular-ionic/modules');
        dest = dest.replace(filename, '')

        doubleCheckDistFiles();

        return gulp.src(file.path).pipe(gulp.dest(dest));
      });

      watch('ionic/components/*/test/**/*', function() {
        doubleCheckDistFiles();
        gulp.start('ionic.examples');
      });

      watch('ionic/components/**/*.scss', function() {
        gulp.start('sass');
      });
    })

});

function doubleCheckDistFiles() {
  if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/css')) {
    gulp.start('old.sass');
  }

  if (!fs.existsSync('../angular-ionic/dist/js/dev/es5/fonts')) {
    gulp.start('old.fonts');
  }
}

gulp.task('old.clean', function(done) {
  del(['../angular-ionic/modules/ionic, ./angular-ionic/modules/examples/src/ionic'], done);
});

gulp.task('old.ionic.copy.js', function(done) {
  return gulp.src(['ionic/**/*.js', '!ionic/components/*/test/**/*'])
             .pipe(gulp.dest('../angular-ionic/modules/ionic'));
});

gulp.task('old.ionic.examples', function() {
  var indexContents = _.template( fs.readFileSync('scripts/e2e/angular.template.html') )({
    buildConfig: buildConfig
  });

  // Get each test folder with gulp.src
  return gulp.src('ionic/components/*/test/*/**/*')
    .pipe(rename(function(file) {
      file.dirname = file.dirname.replace(path.sep + 'test' + path.sep, path.sep)
    }))
    .pipe(gulpif(/index.js$/, processMain()))
    .pipe(gulp.dest('../angular-ionic/modules/examples/src/ionic'))

    function processMain() {
      return through2.obj(function(file, enc, next) {
        var self = this;
        self.push(new VinylFile({
          base: file.base,
          contents: new Buffer(indexContents),
          path: path.join(path.dirname(file.path), 'index.html'),
        }));
        next(null, file);
      })
    }

});

gulp.task('old.sass', function() {
  return gulp.src('ionic/ionic.scss')
    .pipe(sass({
      onError: function(err) {
        console.log(err)
      }
    }))
    .pipe(autoprefixer(buildConfig.autoprefixer))
    .pipe(gulp.dest('../angular-ionic/dist/js/dev/es5/css'));
});

gulp.task('old.fonts', function() {
  return gulp.src('ionic/components/icon/fonts/**/*')
    .pipe(gulp.dest('../angular-ionic/dist/js/dev/es5/fonts'));
});

gulp.task('old.polyfills', function() {
  return gulp.src('ionic/animations/web-animations*')
    .pipe(gulp.dest('../angular-ionic/dist/js/dev/es5/polyfills'));
});

gulp.task('old.update.angular', function(done) {

  if (!fs.existsSync('../angular-ionic')) {
    fs.mkdirSync('../angular-ionic');

    console.log('cloning angular master...');
    exec('git clone git@github.com:angular/angular ../angular-ionic', function() {
      npmInstall();
    });

  } else {
    console.log('angular master: cleaning modules');
    del(['../angular-ionic/modules'], function() {

      console.log('angular master: reset --hard...');
      exec('git reset --hard origin/master', {cwd: '../angular-ionic'}, function () {

        console.log('angular master: git pull origin master...');
        exec('git pull origin master', function () {
          npmInstall();
        });
      });

    })
  }

  function npmInstall() {
    console.log('angular master: npm install (may take a while, chill out)...');
    exec('npm install', {cwd: '../angular-ionic'}, function () {
      done();
    });
  }

});

// gulp.task('watch', ['default'], function() {
//   gulp.watch(buildConfig.src.scss, ['sass'])
//   gulp.watch([].concat(
//     buildConfig.src.js, buildConfig.src.html,
//     'scripts/e2e/index.template.html'
//   ), ['e2e'])
//   gulp.watch([].concat(
//     buildConfig.src.e2e, buildConfig.src.html,
//     'scripts/e2e/index.template.html'
//   ), ['ionic-js'])
// });

gulp.task('old.karma', function() {
  return karma.start({ configFile: __dirname + '/scripts/test/karma.conf.js' })
});

gulp.task('old.karma-watch', function() {
  return karma.start({ configFile: __dirname + '/scripts/test/karma-watch.conf.js' })
});

gulp.task('old.e2e', ['old.sass'], function() {
  var indexContents = _.template( fs.readFileSync('scripts/e2e/index.template.html') )({
    buildConfig: buildConfig
  });
  var testTemplate = _.template( fs.readFileSync('scripts/e2e/e2e.template.js') )

  var platforms = [
    'android',
    'core',
    'ios',
  ];

  gulp.src(['ionic/**/*.js'])
           .pipe(gulp.dest('dist/src'));

  // Get each test folder with gulp.src
  return gulp.src(buildConfig.src.e2e)
    .pipe(cached('e2e'))
    .pipe(rename(function(file) {
      file.dirname = file.dirname.replace(path.sep + 'test' + path.sep, path.sep)
    }))
    .pipe(gulpif(/main.js$/, processMain()))
    //.pipe(gulpif(/e2e.js$/, createPlatformTests()))
    .pipe(gulp.dest(buildConfig.dist + '/e2e'));

    function processMain() {
      return through2.obj(function(file, enc, next) {
        var self = this;
        self.push(new VinylFile({
          base: file.base,
          contents: new Buffer(indexContents),
          path: path.join(path.dirname(file.path), 'index.html'),
        }));
        next(null, file);
      })
    }

    function createPlatformTests(file) {
      return through2.obj(function(file, enc, next) {
        var self = this
        var relativePath = path.dirname(file.path.replace(/^.*?ionic(\/|\\)components(\/|\\)/, ''))
        var contents = file.contents.toString()
        platforms.forEach(function(platform) {
          var platformContents = testTemplate({
            contents: contents,
            buildConfig: buildConfig,
            relativePath: relativePath,
            platform: platform
          })
          self.push(new VinylFile({
            base: file.base,
            contents: new Buffer(platformContents),
            path: file.path.replace(/e2e.js$/, platform + '.e2e.js')
          }))
        })
        next()
      })
    }

});
<|endoftext|>


<commit_before>var common = require("../common-tap.js")
  , test = require("tap").test
  , rimraf = require("rimraf")
  , npm = require("../../")
  , mr = require("npm-registry-mock")
  , spawn = require('child_process').spawn
  , node = process.execPath
  , npmc = require.resolve('../../')
  , pkg = __dirname + '/outdated-new-versions'
  , args = [ npmc
           , 'outdated'
           , '--json'
           , '--silent'
           , '--registry=' + common.registry
           , '--cache=' + pkg + '/cache'
           ]

var expected = { underscore:
                 { current: '1.3.3'
                 , wanted: '1.3.3'
                 , latest: '1.5.1'
                 , location: 'node_modules/underscore'
                 }
               , request:
                 { current: '0.9.5'
                 , wanted: '0.9.5'
                 , latest: '2.27.0'
                 , location: 'node_modules/request'
                 }
               }

test("it should log json data", function (t) {
  cleanup()
  process.chdir(pkg)

  mr(common.port, function (s) {
    npm.load({
      cache: pkg + "/cache",
      loglevel: 'silent',
      registry: common.registry }
    , function () {
      npm.install(".", function (err) {
        var child = spawn(node, args)
          , out = ''
        child.stdout
          .on('data', function (buf) {
            out += buf.toString()
          })
          .pipe(process.stdout)
        child.on('exit', function () {
          out = JSON.parse(out)
          t.deepEqual(out, expected)
          s.close()
          t.end()
        })
      })
    })
  })
})

test("cleanup", function (t) {
  cleanup()
  t.end()
})

function cleanup () {
  rimraf.sync(pkg + "/node_modules")
  rimraf.sync(pkg + "/cache")
}<commit_msg>Fix outdated-json test on Windows.<commit_after>var common = require("../common-tap.js")
  , test = require("tap").test
  , rimraf = require("rimraf")
  , npm = require("../../")
  , mr = require("npm-registry-mock")
  , path = require("path")
  , spawn = require('child_process').spawn
  , node = process.execPath
  , npmc = require.resolve('../../')
  , pkg = __dirname + '/outdated-new-versions'
  , args = [ npmc
           , 'outdated'
           , '--json'
           , '--silent'
           , '--registry=' + common.registry
           , '--cache=' + pkg + '/cache'
           ]

var expected = { underscore:
                 { current: '1.3.3'
                 , wanted: '1.3.3'
                 , latest: '1.5.1'
                 , location: 'node_modules' + path.sep + 'underscore'
                 }
               , request:
                 { current: '0.9.5'
                 , wanted: '0.9.5'
                 , latest: '2.27.0'
                 , location: 'node_modules' + path.sep + 'request'
                 }
               }

test("it should log json data", function (t) {
  cleanup()
  process.chdir(pkg)

  mr(common.port, function (s) {
    npm.load({
      cache: pkg + "/cache",
      loglevel: 'silent',
      registry: common.registry }
    , function () {
      npm.install(".", function (err) {
        var child = spawn(node, args)
          , out = ''
        child.stdout
          .on('data', function (buf) {
            out += buf.toString()
          })
          .pipe(process.stdout)
        child.on('exit', function () {
          out = JSON.parse(out)
          t.deepEqual(out, expected)
          s.close()
          t.end()
        })
      })
    })
  })
})

test("cleanup", function (t) {
  cleanup()
  t.end()
})

function cleanup () {
  rimraf.sync(pkg + "/node_modules")
  rimraf.sync(pkg + "/cache")
}
<|endoftext|>


<commit_before>"use strict";

const bloggifyPaths = require("bloggify-paths")
    , PluginLoader = require("bloggify-plugin-loader")
    , defaultConfig = require("./default-config")
    , ul = require("ul")
    ;

module.exports = class BloggifyCore {
    /**
     * BloggifyCore
     * The Bloggify core library.
     *
     * @name BloggifyCore
     * @function
     * @param {Object} options An object containing the following fields:
     *
     *  - `fieldOne` (Number): Any number (default: `42`).
     *
     * @return BloggifyCore The `BloggifyCore` instance.
     */
    constructor (root, options) {
        this.options = ul.deepMerge(options, {
            config: {}
          , paths: {}
        });
        this.paths = bloggifyPaths(root, this.options);
        this.pluginLoader = new PluginLoader(this);
    }

    getConfig (cb) {
        let conf = ul.deepMerge(this.options.config, defaultConfig);
        try {
            conf = require(this.paths.config);
        } catch (e) {
            if (e.code !== "MODULE_NOT_FOUND") {
                return cb(e, conf);
            }
            return cb(null, conf, e);
        }
        conf = ul.deepMerge(conf, defaultConfig);
        return cb(null, conf);
    }

    loadPlugins (names, cb) {
        return this.pluginLoader.loadAll(names, cb);
    }
};
<commit_msg>Added the getPlugin method<commit_after>"use strict";

const bloggifyPaths = require("bloggify-paths")
    , PluginLoader = require("bloggify-plugin-loader")
    , defaultConfig = require("./default-config")
    , ul = require("ul")
    ;

module.exports = class BloggifyCore {
    /**
     * BloggifyCore
     * The Bloggify core library.
     *
     * @name BloggifyCore
     * @function
     * @param {Object} options An object containing the following fields:
     *
     *  - `fieldOne` (Number): Any number (default: `42`).
     *
     * @return BloggifyCore The `BloggifyCore` instance.
     */
    constructor (root, options) {
        this.options = ul.deepMerge(options, {
            config: {}
          , paths: {}
        });
        this.paths = bloggifyPaths(root, this.options);
        this.pluginLoader = new PluginLoader(this);
    }

    getConfig (cb) {
        let conf = ul.deepMerge(this.options.config, defaultConfig);
        try {
            conf = require(this.paths.config);
        } catch (e) {
            if (e.code !== "MODULE_NOT_FOUND") {
                return cb(e, conf);
            }
            return cb(null, conf, e);
        }
        conf = ul.deepMerge(conf, defaultConfig);
        return cb(null, conf);
    }

    loadPlugins (names, cb) {
        return this.pluginLoader.loadAll(names, cb);
    }

    getPlugin (name, mod) {
        return this.pluginLoader.get(name, mod);
    }
};
<|endoftext|>


<commit_before>'use strict';

// ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, NotSupported, AuthenticationError } = require ('./base/errors');

// ---------------------------------------------------------------------------

module.exports = class xbtce extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'xbtce',
            'name': 'xBTCe',
            'countries': [ 'RU' ],
            'rateLimit': 2000, // responses are cached every 2 seconds
            'version': 'v1',
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'createMarketOrder': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28059414-e235970c-662c-11e7-8c3a-08e31f78684b.jpg',
                'api': 'https://cryptottlivewebapi.xbtce.net:8443/api',
                'www': 'https://www.xbtce.com',
                'doc': [
                    'https://www.xbtce.com/tradeapi',
                    'https://support.xbtce.info/Knowledgebase/Article/View/52/25/xbtce-exchange-api',
                ],
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
                'uid': true,
            },
            'api': {
                'public': {
                    'get': [
                        'currency',
                        'currency/{filter}',
                        'level2',
                        'level2/{filter}',
                        'quotehistory/{symbol}/{periodicity}/bars/ask',
                        'quotehistory/{symbol}/{periodicity}/bars/bid',
                        'quotehistory/{symbol}/level2',
                        'quotehistory/{symbol}/ticks',
                        'symbol',
                        'symbol/{filter}',
                        'tick',
                        'tick/{filter}',
                        'ticker',
                        'ticker/{filter}',
                        'tradesession',
                    ],
                },
                'private': {
                    'get': [
                        'tradeserverinfo',
                        'tradesession',
                        'currency',
                        'currency/{filter}',
                        'level2',
                        'level2/{filter}',
                        'symbol',
                        'symbol/{filter}',
                        'tick',
                        'tick/{filter}',
                        'account',
                        'asset',
                        'asset/{id}',
                        'position',
                        'position/{id}',
                        'trade',
                        'trade/{id}',
                        'quotehistory/{symbol}/{periodicity}/bars/ask',
                        'quotehistory/{symbol}/{periodicity}/bars/ask/info',
                        'quotehistory/{symbol}/{periodicity}/bars/bid',
                        'quotehistory/{symbol}/{periodicity}/bars/bid/info',
                        'quotehistory/{symbol}/level2',
                        'quotehistory/{symbol}/level2/info',
                        'quotehistory/{symbol}/periodicities',
                        'quotehistory/{symbol}/ticks',
                        'quotehistory/{symbol}/ticks/info',
                        'quotehistory/cache/{symbol}/{periodicity}/bars/ask',
                        'quotehistory/cache/{symbol}/{periodicity}/bars/bid',
                        'quotehistory/cache/{symbol}/level2',
                        'quotehistory/cache/{symbol}/ticks',
                        'quotehistory/symbols',
                        'quotehistory/version',
                    ],
                    'post': [
                        'trade',
                        'tradehistory',
                    ],
                    'put': [
                        'trade',
                    ],
                    'delete': [
                        'trade',
                    ],
                },
            },
        });
    }

    async fetchMarkets (params = {}) {
        let markets = await this.privateGetSymbol ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['Symbol'];
            let base = market['MarginCurrency'];
            let quote = market['ProfitCurrency'];
            if (base === 'DSH')
                base = 'DASH';
            let symbol = base + '/' + quote;
            symbol = market['IsTradeAllowed'] ? symbol : id;
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetAsset ();
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['Currency'];
            let uppercase = currency.toUpperCase ();
            // xbtce names DASH incorrectly as DSH
            if (uppercase === 'DSH')
                uppercase = 'DASH';
            let account = {
                'free': balance['FreeAmount'],
                'used': balance['LockedAmount'],
                'total': balance['Amount'],
            };
            result[uppercase] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let orderbook = await this.privateGetLevel2Filter (this.extend ({
            'filter': market['id'],
        }, params));
        orderbook = orderbook[0];
        let timestamp = orderbook['Timestamp'];
        return this.parseOrderBook (orderbook, timestamp, 'Bids', 'Asks', 'Price', 'Volume');
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = 0;
        let last = undefined;
        if ('LastBuyTimestamp' in ticker)
            if (timestamp < ticker['LastBuyTimestamp']) {
                timestamp = ticker['LastBuyTimestamp'];
                last = ticker['LastBuyPrice'];
            }
        if ('LastSellTimestamp' in ticker)
            if (timestamp < ticker['LastSellTimestamp']) {
                timestamp = ticker['LastSellTimestamp'];
                last = ticker['LastSellPrice'];
            }
        if (!timestamp)
            timestamp = this.milliseconds ();
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': ticker['DailyBestBuyPrice'],
            'low': ticker['DailyBestSellPrice'],
            'bid': ticker['BestBid'],
            'bidVolume': undefined,
            'ask': ticker['BestAsk'],
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': ticker['DailyTradedTotalVolume'],
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetTicker (params);
        tickers = this.indexBy (tickers, 'Symbol');
        let ids = Object.keys (tickers);
        let result = {};
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            let market = undefined;
            let symbol = undefined;
            if (id in this.markets_by_id) {
                market = this.markets_by_id[id];
                symbol = market['symbol'];
            } else {
                let base = id.slice (0, 3);
                let quote = id.slice (3, 6);
                if (base === 'DSH')
                    base = 'DASH';
                if (quote === 'DSH')
                    quote = 'DASH';
                symbol = base + '/' + quote;
            }
            let ticker = tickers[id];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let tickers = await this.publicGetTickerFilter (this.extend ({
            'filter': market['id'],
        }, params));
        let length = tickers.length;
        if (length < 1)
            throw new ExchangeError (this.id + ' fetchTicker returned empty response, xBTCe public API error');
        tickers = this.indexBy (tickers, 'Symbol');
        let ticker = tickers[market['id']];
        return this.parseTicker (ticker, market);
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        // no method for trades?
        return await this.privateGetTrade (params);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
        return [
            ohlcv['Timestamp'],
            ohlcv['Open'],
            ohlcv['High'],
            ohlcv['Low'],
            ohlcv['Close'],
            ohlcv['Volume'],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        //     let minutes = parseInt (timeframe / 60); // 1 minute by default
        //     let periodicity = minutes.toString ();
        //     await this.loadMarkets ();
        //     let market = this.market (symbol);
        //     if (since === undefined)
        //         since = this.seconds () - 86400 * 7; // last day by defulat
        //     if (limit === undefined)
        //         limit = 1000; // default
        //     let response = await this.privateGetQuotehistorySymbolPeriodicityBarsBid (this.extend ({
        //         'symbol': market['id'],
        //         'periodicity': periodicity,
        //         'timestamp': since,
        //         'count': limit,
        //     }, params));
        //     return this.parseOHLCVs (response['Bars'], market, timeframe, since, limit);
        throw new NotSupported (this.id + ' fetchOHLCV is disabled by the exchange');
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        if (type === 'market')
            throw new ExchangeError (this.id + ' allows limit orders only');
        let response = await this.privatePostTrade (this.extend ({
            'pair': this.marketId (symbol),
            'type': side,
            'amount': amount,
            'rate': price,
        }, params));
        return {
            'info': response,
            'id': response['Id'].toString (),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        return await this.privateDeleteTrade (this.extend ({
            'Type': 'Cancel',
            'Id': id,
        }, params));
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        if (!this.apiKey)
            throw new AuthenticationError (this.id + ' requires apiKey for all requests, their public API is always busy');
        if (!this.uid)
            throw new AuthenticationError (this.id + ' requires uid property for authentication and trading, their public API is always busy');
        let url = this.urls['api'] + '/' + this.version;
        if (api === 'public')
            url += '/' + api;
        url += '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else {
            this.checkRequiredCredentials ();
            headers = { 'Accept-Encoding': 'gzip, deflate' };
            let nonce = this.nonce ().toString ();
            if (method === 'POST') {
                if (Object.keys (query).length) {
                    headers['Content-Type'] = 'application/json';
                    body = this.json (query);
                } else {
                    url += '?' + this.urlencode (query);
                }
            }
            let auth = nonce + this.uid + this.apiKey + method + url;
            if (body)
                auth += body;
            let signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha256', 'base64');
            let credentials = this.uid + ':' + this.apiKey + ':' + nonce + ':' + this.decode (signature);
            headers['Authorization'] = 'HMAC ' + credentials;
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<commit_msg>xbtce cleanup for eslint curly<commit_after>'use strict';

// ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, NotSupported, AuthenticationError } = require ('./base/errors');

// ---------------------------------------------------------------------------

module.exports = class xbtce extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'xbtce',
            'name': 'xBTCe',
            'countries': [ 'RU' ],
            'rateLimit': 2000, // responses are cached every 2 seconds
            'version': 'v1',
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'createMarketOrder': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28059414-e235970c-662c-11e7-8c3a-08e31f78684b.jpg',
                'api': 'https://cryptottlivewebapi.xbtce.net:8443/api',
                'www': 'https://www.xbtce.com',
                'doc': [
                    'https://www.xbtce.com/tradeapi',
                    'https://support.xbtce.info/Knowledgebase/Article/View/52/25/xbtce-exchange-api',
                ],
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
                'uid': true,
            },
            'api': {
                'public': {
                    'get': [
                        'currency',
                        'currency/{filter}',
                        'level2',
                        'level2/{filter}',
                        'quotehistory/{symbol}/{periodicity}/bars/ask',
                        'quotehistory/{symbol}/{periodicity}/bars/bid',
                        'quotehistory/{symbol}/level2',
                        'quotehistory/{symbol}/ticks',
                        'symbol',
                        'symbol/{filter}',
                        'tick',
                        'tick/{filter}',
                        'ticker',
                        'ticker/{filter}',
                        'tradesession',
                    ],
                },
                'private': {
                    'get': [
                        'tradeserverinfo',
                        'tradesession',
                        'currency',
                        'currency/{filter}',
                        'level2',
                        'level2/{filter}',
                        'symbol',
                        'symbol/{filter}',
                        'tick',
                        'tick/{filter}',
                        'account',
                        'asset',
                        'asset/{id}',
                        'position',
                        'position/{id}',
                        'trade',
                        'trade/{id}',
                        'quotehistory/{symbol}/{periodicity}/bars/ask',
                        'quotehistory/{symbol}/{periodicity}/bars/ask/info',
                        'quotehistory/{symbol}/{periodicity}/bars/bid',
                        'quotehistory/{symbol}/{periodicity}/bars/bid/info',
                        'quotehistory/{symbol}/level2',
                        'quotehistory/{symbol}/level2/info',
                        'quotehistory/{symbol}/periodicities',
                        'quotehistory/{symbol}/ticks',
                        'quotehistory/{symbol}/ticks/info',
                        'quotehistory/cache/{symbol}/{periodicity}/bars/ask',
                        'quotehistory/cache/{symbol}/{periodicity}/bars/bid',
                        'quotehistory/cache/{symbol}/level2',
                        'quotehistory/cache/{symbol}/ticks',
                        'quotehistory/symbols',
                        'quotehistory/version',
                    ],
                    'post': [
                        'trade',
                        'tradehistory',
                    ],
                    'put': [
                        'trade',
                    ],
                    'delete': [
                        'trade',
                    ],
                },
            },
            'commonCurrencies': {
                'DSH': 'DASH',
            },
        });
    }

    async fetchMarkets (params = {}) {
        const response = await this.privateGetSymbol (params);
        const result = [];
        for (let i = 0; i < response.length; i++) {
            const market = response[i];
            const id = this.safeString (market, 'Symbol');
            const baseId = this.safeString (market, 'MarginCurrency');
            const quoteId = this.safeString (market, 'ProfitCurrency');
            const base = this.commonCurrencyCode (baseId);
            const quote = this.commonCurrencyCode (quoteId);
            let symbol = base + '/' + quote;
            symbol = market['IsTradeAllowed'] ? symbol : id;
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        const balances = await this.privateGetAsset (params);
        const result = { 'info': balances };
        for (let i = 0; i < balances.length; i++) {
            const balance = balances[i];
            const currencyId = this.safeString (balance, 'Currency');
            const uppercase = currencyId.toUpperCase ();
            const code = this.commonCurrencyCode (uppercase);
            const account = {
                'free': balance['FreeAmount'],
                'used': balance['LockedAmount'],
                'total': balance['Amount'],
            };
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'filter': market['id'],
        };
        const response = await this.privateGetLevel2Filter (this.extend (request, params));
        const orderbook = response[0];
        let timestamp = this.safeInteger (orderbook, 'Timestamp');
        return this.parseOrderBook (orderbook, timestamp, 'Bids', 'Asks', 'Price', 'Volume');
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = 0;
        let last = undefined;
        if ('LastBuyTimestamp' in ticker) {
            if (timestamp < ticker['LastBuyTimestamp']) {
                timestamp = ticker['LastBuyTimestamp'];
                last = ticker['LastBuyPrice'];
            }
        }
        if ('LastSellTimestamp' in ticker) {
            if (timestamp < ticker['LastSellTimestamp']) {
                timestamp = ticker['LastSellTimestamp'];
                last = ticker['LastSellPrice'];
            }
        }
        if (!timestamp) {
            timestamp = this.milliseconds ();
        }
        let symbol = undefined;
        if (market) {
            symbol = market['symbol'];
        }
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': ticker['DailyBestBuyPrice'],
            'low': ticker['DailyBestSellPrice'],
            'bid': ticker['BestBid'],
            'bidVolume': undefined,
            'ask': ticker['BestAsk'],
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': ticker['DailyTradedTotalVolume'],
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        const response = await this.publicGetTicker (params);
        const tickers = this.indexBy (response, 'Symbol');
        const ids = Object.keys (tickers);
        const result = {};
        for (let i = 0; i < ids.length; i++) {
            const id = ids[i];
            let market = undefined;
            let symbol = undefined;
            if (id in this.markets_by_id) {
                market = this.markets_by_id[id];
                symbol = market['symbol'];
            } else {
                const baseId = id.slice (0, 3);
                const quoteId = id.slice (3, 6);
                const base = this.commonCurrencyCode (baseId);
                const quote = this.commonCurrencyCode (quoteId);
                symbol = base + '/' + quote;
            }
            const ticker = tickers[id];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'filter': market['id'],
        };
        const response = await this.publicGetTickerFilter (this.extend (request, params));
        const length = response.length;
        if (length < 1) {
            throw new ExchangeError (this.id + ' fetchTicker returned empty response, xBTCe public API error');
        }
        const tickers = this.indexBy (response, 'Symbol');
        const ticker = tickers[market['id']];
        return this.parseTicker (ticker, market);
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        // no method for trades?
        return await this.privateGetTrade (params);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
        return [
            ohlcv['Timestamp'],
            ohlcv['Open'],
            ohlcv['High'],
            ohlcv['Low'],
            ohlcv['Close'],
            ohlcv['Volume'],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        //     let minutes = parseInt (timeframe / 60); // 1 minute by default
        //     let periodicity = minutes.toString ();
        //     await this.loadMarkets ();
        //     let market = this.market (symbol);
        //     if (since === undefined)
        //         since = this.seconds () - 86400 * 7; // last day by defulat
        //     if (limit === undefined)
        //         limit = 1000; // default
        //     let response = await this.privateGetQuotehistorySymbolPeriodicityBarsBid (this.extend ({
        //         'symbol': market['id'],
        //         'periodicity': periodicity,
        //         'timestamp': since,
        //         'count': limit,
        //     }, params));
        //     return this.parseOHLCVs (response['Bars'], market, timeframe, since, limit);
        throw new NotSupported (this.id + ' fetchOHLCV is disabled by the exchange');
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        if (type === 'market') {
            throw new ExchangeError (this.id + ' allows limit orders only');
        }
        const request = {
            'pair': this.marketId (symbol),
            'type': side,
            'amount': amount,
            'rate': price,
        };
        const response = await this.privatePostTrade (this.extend (request, params));
        return {
            'info': response,
            'id': response['Id'].toString (),
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        const request = {
            'Type': 'Cancel',
            'Id': id,
        };
        return await this.privateDeleteTrade (this.extend (request, params));
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        if (!this.apiKey) {
            throw new AuthenticationError (this.id + ' requires apiKey for all requests, their public API is always busy');
        }
        if (!this.uid) {
            throw new AuthenticationError (this.id + ' requires uid property for authentication and trading, their public API is always busy');
        }
        let url = this.urls['api'] + '/' + this.version;
        if (api === 'public') {
            url += '/' + api;
        }
        url += '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        } else {
            this.checkRequiredCredentials ();
            headers = { 'Accept-Encoding': 'gzip, deflate' };
            let nonce = this.nonce ().toString ();
            if (method === 'POST') {
                if (Object.keys (query).length) {
                    headers['Content-Type'] = 'application/json';
                    body = this.json (query);
                } else {
                    url += '?' + this.urlencode (query);
                }
            }
            let auth = nonce + this.uid + this.apiKey + method + url;
            if (body) {
                auth += body;
            }
            let signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha256', 'base64');
            let credentials = this.uid + ':' + this.apiKey + ':' + nonce + ':' + this.decode (signature);
            headers['Authorization'] = 'HMAC ' + credentials;
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>


<commit_before>/*!
 * Bootstrap Markdown Editor v1.2.1 (https://github.com/inacho/bootstrap-markdown-editor)
 * Copyright 2016 Ignacio de Tomás <nacho@inacho.es>
 * Licensed under MIT (https://github.com/inacho/bootstrap-markdown-editor/blob/master/LICENSE)
 */

!function(a){"use strict";function b(b,c,d,e,f){f.show();var g=new FormData,h=0;for(h=0;h<c.length;h++)g.append("file"+h,c[h]);a.ajax({url:b,type:"POST",contentType:!1,data:g,processData:!1,cache:!1,dataType:"json"}).done(function(a){var b="";a.length>1&&(b="\n");for(var c=0;ce&&(c=d-e,b.css("height",c+"px"))}function d(a,b){a.commands.addCommand({name:"bold",bindKey:{win:"Ctrl-B",mac:"Command-B"},exec:function(a){var c=a.session.getTextRange(a.getSelectionRange());""===c?b.insertSnippet(a,"**${1:text}**"):b.insertSnippet(a,"**"+c+"**")},readOnly:!1}),a.commands.addCommand({name:"italic",bindKey:{win:"Ctrl-I",mac:"Command-I"},exec:function(a){var c=a.session.getTextRange(a.getSelectionRange());""===c?b.insertSnippet(a,"*${1:text}*"):b.insertSnippet(a,"*"+c+"*")},readOnly:!1}),a.commands.addCommand({name:"link",bindKey:{win:"Ctrl-K",mac:"Command-K"},exec:function(a){var c=a.session.getTextRange(a.getSelectionRange());""===c?b.insertSnippet(a,"[${1:text}](http://$2)"):b.insertSnippet(a,"["+c+"](http://$1)")},readOnly:!1})}function e(a,b){0===a.getCursorPosition().column?(a.navigateLineStart(),a.insert(b+" ")):(a.navigateLineStart(),a.insert(b+" "),a.navigateLineEnd())}function f(b,c){var d="";return d+='

',d+='
',d+='
',d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnHeader1+'" class="md-btn btn btn-sm btn-default" data-btn="h1">H1</button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnHeader2+'" class="md-btn btn btn-sm btn-default" data-btn="h2">H2</button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnHeader3+'" class="md-btn btn btn-sm btn-default" data-btn="h3">H3</button>',d+="
",d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnBold+'" class="md-btn btn btn-sm btn-default" data-btn="bold"></button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnItalic+'" class="md-btn btn btn-sm btn-default" data-btn="italic"></button>',d+="
",d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnList+'" class="md-btn btn btn-sm btn-default" data-btn="ul"></button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnOrderedList+'" class="md-btn btn btn-sm btn-default" data-btn="ol"></button>',d+="
",d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnLink+'" class="md-btn btn btn-sm btn-default" data-btn="link"></button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnImage+'" class="md-btn btn btn-sm btn-default" data-btn="image"></button>',c.imageUpload===!0&&(d+='
<input class="md-input-upload" type="file" multiple accept=".jpg,.jpeg,.png,.gif">
'),d+="
",c.fullscreen===!0&&(d+='
',d+='<button type="button" class="md-btn btn btn-sm btn-default" data-btn="fullscreen"> '+c.label.btnFullscreen+"</button>",d+="
"),c.preview===!0&&(d+='
',d+='<button type="button" class="md-btn btn btn-sm btn-default btn-edit active" data-btn="edit"> '+c.label.btnEdit+"</button>",d+='<button type="button" class="md-btn btn btn-sm btn-default btn-preview" data-btn="preview"> '+c.label.btnPreview+"</button>",d+="
"),d+="
",d+="
",d+='
'+a("
").text(b).html()+"
",d+='

'}var g={init:function(g){var h=a.extend(!0,{},a.fn.markdownEditor.defaults,g),i=this,j=!1,k=!1;i.addClass("md-container").html(f(this.text(),h)),"function"==typeof a().tooltip&&i.find('[data-mdtooltip="tooltip"]').tooltip({container:"body"});var l=i.find(".md-editor"),m=i.find(".md-preview"),n=i.find(".md-loading");i.css({width:h.width}),l.css({width:h.width,height:h.height,fontSize:h.fontSize}),m.css({width:h.width,height:h.height});var o,p=ace.edit(l[0]);return p.setTheme("ace/theme/"+h.theme),p.getSession().setMode("ace/mode/markdown"),p.getSession().setUseWrapMode(!0),p.getSession().setUseSoftTabs(h.softTabs),p.setHighlightActiveLine(!1),p.setShowPrintMargin(!1),p.renderer.setShowGutter(!1),ace.config.loadModule("ace/ext/language_tools",function(){o=ace.require("ace/snippets").snippetManager,d(p,o)}),h.imageUpload&&(i.find(".md-input-upload").on("change",function(){var c=a(this).get(0).files;c.length&&b(h.uploadPath,a(this).get(0).files,p,o,n)}),i.on("dragenter",function(a){a.stopPropagation(),a.preventDefault()}),i.on("dragover",function(a){a.stopPropagation(),a.preventDefault()}),i.on("drop",function(a){a.preventDefault();var c=a.originalEvent.dataTransfer.files;b(h.uploadPath,c,p,o,n)})),h.fullscreen===!0&&a(window).resize(function(){k===!0&&c(j===!1?l:m)}),i.find(".md-btn").click(function(){var b=a(this).data("btn"),d=p.session.getTextRange(p.getSelectionRange());"h1"===b?e(p,"#"):"h2"===b?e(p,"##"):"h3"===b?e(p,"###"):"ul"===b?e(p,"*"):"ol"===b?e(p,"1."):"bold"===b?p.execCommand("bold"):"italic"===b?p.execCommand("italic"):"link"===b?p.execCommand("link"):"image"===b?""===d?o.insertSnippet(p,"![${1:text}](http://$2)"):o.insertSnippet(p,"!["+d+"](http://$1)"):"edit"===b?(j=!1,m.hide(),l.show(),i.find(".btn-edit").addClass("active"),i.find(".btn-preview").removeClass("active"),k===!0&&c(l)):"preview"===b?(j=!0,m.html('
'+h.label.loading+"...
"),h.onPreview(p.getSession().getValue(),function(a){m.html(a)}),l.hide(),m.show(),i.find(".btn-preview").addClass("active"),i.find(".btn-edit").removeClass("active"),k===!0&&c(m)):"fullscreen"===b&&(k===!0?(k=!1,a("body, html").removeClass("md-body-fullscreen"),i.removeClass("md-fullscreen"),l.css("height",h.height),m.css("height",h.height)):(k=!0,a("body, html").addClass("md-body-fullscreen"),i.addClass("md-fullscreen"),c(j===!1?l:m)),p.resize()),p.focus()}),this},content:function(){var a=ace.edit(this.find(".md-editor")[0]);return a.getSession().getValue()},setContent:function(a){var b=ace.edit(this.find(".md-editor")[0]);b.setValue(a,1)}};a.fn.markdownEditor=function(b){return g[b]?g[b].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof b&&b?void a.error("Method "+b+" does not exist on jQuery.markdownEditor"):g.init.apply(this,arguments)},a.fn.markdownEditor.defaults={width:"100%",height:"400px",fontSize:"14px",theme:"tomorrow",softTabs:!0,fullscreen:!0,imageUpload:!1,uploadPath:"",preview:!1,onPreview:function(a,b){b(a)},label:{btnHeader1:"Header 1",btnHeader2:"Header 2",btnHeader3:"Header 3",btnBold:"Bold",btnItalic:"Italic",btnList:"Unordered list",btnOrderedList:"Ordered list",btnLink:"Link",btnImage:"Insert image",btnUpload:"Upload image",btnEdit:"Edit",btnPreview:"Preview",btnFullscreen:"Fullscreen",loading:"Loading"}}}(jQuery);<commit_msg>Compiled JS<commit_after>/*!
 * Bootstrap Markdown Editor v1.2.1 (https://github.com/inacho/bootstrap-markdown-editor)
 * Copyright 2016 Ignacio de Tomás <nacho@inacho.es>
 * Licensed under MIT (https://github.com/inacho/bootstrap-markdown-editor/blob/master/LICENSE)
 */

!function(a){"use strict";function b(b,c,d,e,f){if(c.length){f.show();var g=new FormData,h=0;for(h=0;h<c.length;h++)g.append("file"+h,c[h]);a.ajax({url:b,type:"POST",contentType:!1,data:g,processData:!1,cache:!1,dataType:"json"}).done(function(a){var b="";a.length>1&&(b="\n");for(var c=0;ce&&(c=d-e,b.css("height",c+"px"))}function d(a,b){a.commands.addCommand({name:"bold",bindKey:{win:"Ctrl-B",mac:"Command-B"},exec:function(a){var c=a.session.getTextRange(a.getSelectionRange());""===c?b.insertSnippet(a,"**${1:text}**"):b.insertSnippet(a,"**"+c+"**")},readOnly:!1}),a.commands.addCommand({name:"italic",bindKey:{win:"Ctrl-I",mac:"Command-I"},exec:function(a){var c=a.session.getTextRange(a.getSelectionRange());""===c?b.insertSnippet(a,"*${1:text}*"):b.insertSnippet(a,"*"+c+"*")},readOnly:!1}),a.commands.addCommand({name:"link",bindKey:{win:"Ctrl-K",mac:"Command-K"},exec:function(a){var c=a.session.getTextRange(a.getSelectionRange());""===c?b.insertSnippet(a,"[${1:text}](http://$2)"):b.insertSnippet(a,"["+c+"](http://$1)")},readOnly:!1})}function e(a,b){0===a.getCursorPosition().column?(a.navigateLineStart(),a.insert(b+" ")):(a.navigateLineStart(),a.insert(b+" "),a.navigateLineEnd())}function f(b,c){var d="";return d+='

',d+='
',d+='
',d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnHeader1+'" class="md-btn btn btn-sm btn-default" data-btn="h1">H1</button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnHeader2+'" class="md-btn btn btn-sm btn-default" data-btn="h2">H2</button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnHeader3+'" class="md-btn btn btn-sm btn-default" data-btn="h3">H3</button>',d+="
",d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnBold+'" class="md-btn btn btn-sm btn-default" data-btn="bold"></button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnItalic+'" class="md-btn btn btn-sm btn-default" data-btn="italic"></button>',d+="
",d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnList+'" class="md-btn btn btn-sm btn-default" data-btn="ul"></button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnOrderedList+'" class="md-btn btn btn-sm btn-default" data-btn="ol"></button>',d+="
",d+='
',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnLink+'" class="md-btn btn btn-sm btn-default" data-btn="link"></button>',d+='<button type="button" data-mdtooltip="tooltip" title="'+c.label.btnImage+'" class="md-btn btn btn-sm btn-default" data-btn="image"></button>',c.imageUpload===!0&&(d+='
<input class="md-input-upload" type="file" multiple accept=".jpg,.jpeg,.png,.gif">
'),d+="
",c.fullscreen===!0&&(d+='
',d+='<button type="button" class="md-btn btn btn-sm btn-default" data-btn="fullscreen"> '+c.label.btnFullscreen+"</button>",d+="
"),c.preview===!0&&(d+='
',d+='<button type="button" class="md-btn btn btn-sm btn-default btn-edit active" data-btn="edit"> '+c.label.btnEdit+"</button>",d+='<button type="button" class="md-btn btn btn-sm btn-default btn-preview" data-btn="preview"> '+c.label.btnPreview+"</button>",d+="
"),d+="
",d+="
",d+='
'+a("
").text(b).html()+"
",d+='

'}var g={init:function(g){var h=a.extend(!0,{},a.fn.markdownEditor.defaults,g),i=this,j=!1,k=!1;i.addClass("md-container").html(f(this.text(),h)),"function"==typeof a().tooltip&&i.find('[data-mdtooltip="tooltip"]').tooltip({container:"body"});var l=i.find(".md-editor"),m=i.find(".md-preview"),n=i.find(".md-loading");i.css({width:h.width}),l.css({width:h.width,height:h.height,fontSize:h.fontSize}),m.css({width:h.width,height:h.height});var o,p=ace.edit(l[0]);return p.setTheme("ace/theme/"+h.theme),p.getSession().setMode("ace/mode/markdown"),p.getSession().setUseWrapMode(!0),p.getSession().setUseSoftTabs(h.softTabs),p.setHighlightActiveLine(!1),p.setShowPrintMargin(!1),p.renderer.setShowGutter(!1),ace.config.loadModule("ace/ext/language_tools",function(){o=ace.require("ace/snippets").snippetManager,d(p,o)}),h.imageUpload&&(i.find(".md-input-upload").on("change",function(){a(this).get(0).files;b(h.uploadPath,a(this).get(0).files,p,o,n)}),i.on("dragenter",function(a){a.stopPropagation(),a.preventDefault()}),i.on("dragover",function(a){a.stopPropagation(),a.preventDefault()}),i.on("drop",function(a){a.preventDefault();var c=a.originalEvent.dataTransfer.files;b(h.uploadPath,c,p,o,n)})),h.fullscreen===!0&&a(window).resize(function(){k===!0&&c(j===!1?l:m)}),i.find(".md-btn").click(function(){var b=a(this).data("btn"),d=p.session.getTextRange(p.getSelectionRange());"h1"===b?e(p,"#"):"h2"===b?e(p,"##"):"h3"===b?e(p,"###"):"ul"===b?e(p,"*"):"ol"===b?e(p,"1."):"bold"===b?p.execCommand("bold"):"italic"===b?p.execCommand("italic"):"link"===b?p.execCommand("link"):"image"===b?""===d?o.insertSnippet(p,"![${1:text}](http://$2)"):o.insertSnippet(p,"!["+d+"](http://$1)"):"edit"===b?(j=!1,m.hide(),l.show(),i.find(".btn-edit").addClass("active"),i.find(".btn-preview").removeClass("active"),k===!0&&c(l)):"preview"===b?(j=!0,m.html('
'+h.label.loading+"...
"),h.onPreview(p.getSession().getValue(),function(a){m.html(a)}),l.hide(),m.show(),i.find(".btn-preview").addClass("active"),i.find(".btn-edit").removeClass("active"),k===!0&&c(m)):"fullscreen"===b&&(k===!0?(k=!1,a("body, html").removeClass("md-body-fullscreen"),i.removeClass("md-fullscreen"),l.css("height",h.height),m.css("height",h.height)):(k=!0,a("body, html").addClass("md-body-fullscreen"),i.addClass("md-fullscreen"),c(j===!1?l:m)),p.resize()),p.focus()}),this},content:function(){var a=ace.edit(this.find(".md-editor")[0]);return a.getSession().getValue()},setContent:function(a){var b=ace.edit(this.find(".md-editor")[0]);b.setValue(a,1)}};a.fn.markdownEditor=function(b){return g[b]?g[b].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof b&&b?void a.error("Method "+b+" does not exist on jQuery.markdownEditor"):g.init.apply(this,arguments)},a.fn.markdownEditor.defaults={width:"100%",height:"400px",fontSize:"14px",theme:"tomorrow",softTabs:!0,fullscreen:!0,imageUpload:!1,uploadPath:"",preview:!1,onPreview:function(a,b){b(a)},label:{btnHeader1:"Header 1",btnHeader2:"Header 2",btnHeader3:"Header 3",btnBold:"Bold",btnItalic:"Italic",btnList:"Unordered list",btnOrderedList:"Ordered list",btnLink:"Link",btnImage:"Insert image",btnUpload:"Upload image",btnEdit:"Edit",btnPreview:"Preview",btnFullscreen:"Fullscreen",loading:"Loading"}}}(jQuery);<|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, da<commit_msg>Fixed memory parsing error #1337<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, dat<|endoftext|>