<commit_before>QUnit.config.reorder = false;

var totalTests, moduleContext, moduleDoneContext, testContext, testDoneContext, logContext,
	testAutorun, beginModules,
	module1Test1, module1Test2, module2Test1, module2Test2,
	module2Test3, module2Test4, module2Test5, module2Test6,
	begin = 0,
	moduleStart = 0,
	moduleDone = 0,
	testStart = 0,
	testDone = 0,
	log = 0,
	module1Context = {
		name: "logs1",
		tests: [
			( module1Test1 = {
				"name": "test1",
				"testId": "646e9e25",
				"skip": false
			} ),
			( module1Test2 = {
				"name": "test2",
				"testId": "646e9e26",
				"skip": false
			} )
		]
	},
	module2Context = {
		name: "logs2",
		tests: [
			( module2Test1 = {
				"name": "test1",
				"testId": "9954d966",
				"skip": false
			} ),
			( module2Test2 = {
				"name": "test2",
				"testId": "9954d967",
				"skip": false
			} ),
			( module2Test3 = {
				"name": "a skipped test",
				"testId": "3e797d3a",
				"skip": true
			} ),
			( module2Test4 = {
				"name": "test the log for the skipped test",
				"testId": "d3266148",
				"skip": false
			} ),
			( module2Test5 = {
				"name": "a todo test",
				"testId": "77a47174",
				"skip": false
			} ),
			( module2Test6 = {
				"name": "test the log for the todo test",
				"testId": "5f5ab826",
				"skip": false
			} )
		]
	};

QUnit.begin( function( args ) {
	totalTests = args.totalTests;
	beginModules = args.modules;
	begin++;
} );

QUnit.moduleStart( function( context ) {
	moduleStart++;
	moduleContext = context;
} );

QUnit.moduleDone( function( context ) {
	moduleDone++;
	moduleDoneContext = context;
} );

QUnit.testStart( function( context ) {
	testStart++;
	testContext = context;
} );

QUnit.testDone( function( context ) {
	testDone++;
	testDoneContext = context;
} );

QUnit.log( function( context ) {
	log++;
	logContext = context;
} );

QUnit.module( module1Context.name );

QUnit.test( module1Test1.name, function( assert ) {
	assert.expect( 18 );

	assert.equal(
		typeof totalTests,
		"number",
		"QUnit.begin should pass total amount of tests to callback"
	);

	while ( beginModules.length > 2 ) {
		beginModules.pop();
	}

	assert.deepEqual(
		beginModules,
		[ module1Context, module2Context ],
		"QUnit.begin details registered modules and their respective tests"
	);

	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 1, "QUnit.moduleStart calls" );
	assert.equal( testStart, 1, "QUnit.testStart calls" );
	assert.equal( testDone, 0, "QUnit.testDone calls" );
	assert.equal( moduleDone, 0, "QUnit.moduleDone calls" );

	assert.equal(
		logContext.runtime >= 0 && logContext.runtime < 50,
		true,
		"log runtime was a reasonable number"
	);

	delete logContext.runtime;
	assert.deepEqual( logContext, {
		name: module1Test1.name,
		module: module1Context.name,
		result: true,
		message: "log runtime was a reasonable number",
		actual: true,
		expected: true,
		negative: false,
		testId: module1Test1.testId,
		todo: false
	}, "log context after equal(actual, expected, message)" );

	assert.equal( "foo", "foo" );

	delete logContext.runtime;
	assert.deepEqual( logContext, {
		name: module1Test1.name,
		module: module1Context.name,
		result: true,
		message: undefined,
		actual: "foo",
		expected: "foo",
		negative: false,
		testId: module1Test1.testId,
		todo: false
	}, "log context after equal(actual, expected)" );

	assert.ok( true, "ok(true, message)" );

	delete logContext.runtime;
	assert.deepEqual( logContext, {
		module: module1Context.name,
		name: module1Test1.name,
		result: true,
		message: "ok(true, message)",
		actual: true,
		expected: true,
		negative: false,
		testId: module1Test1.testId,
		todo: false
	}, "log context after ok(true, message)" );

	assert.strictEqual( testDoneContext, undefined, "testDone context" );
	assert.deepEqual( testContext, {
		module: module1Context.name,
		name: module1Test1.name,
		testId: module1Test1.testId,
		previousFailure: false
	}, "test context" );

	assert.strictEqual( moduleDoneContext, undefined, "moduleDone context" );
	assert.deepEqual( moduleContext, module1Context, "module context" );

	assert.equal( log, 17, "QUnit.log calls" );
} );

QUnit.test( module1Test2.name, function( assert ) {
	assert.expect( 12 );
	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 1, "QUnit.moduleStart calls" );
	assert.equal( testStart, 2, "QUnit.testStart calls" );
	assert.equal( testDone, 1, "QUnit.testDone calls" );
	assert.equal( moduleDone, 0, "QUnit.moduleDone calls" );

	assert.equal(
		testDoneContext.runtime >= 0 && testDoneContext.runtime < 1000,
		true,
		"test runtime was a reasonable number"
	);

	assert.true( testDoneContext.assertions instanceof Array, "testDone context: assertions" );

	// TODO: more tests for testDoneContext.assertions

	delete testDoneContext.runtime;

	// Delete testDoneContext.assertions so we can easily jump to next assertion
	delete testDoneContext.assertions;

	// Delete testDoneContext.source
	delete testDoneContext.source;

	assert.deepEqual( testDoneContext, {
		module: module1Context.name,
		name: module1Test1.name,
		failed: 0,
		passed: 18,
		total: 18,
		testId: module1Test1.testId,
		skipped: false,
		todo: false
	}, "testDone context" );
	assert.deepEqual( testContext, {
		module: module1Context.name,
		name: module1Test2.name,
		testId: module1Test2.testId,
		previousFailure: false
	}, "test context" );

	assert.strictEqual( moduleDoneContext, undefined, "moduleDone context" );
	assert.deepEqual( moduleContext, module1Context, "module context" );
	assert.equal( log, 29, "QUnit.log calls" );
} );

QUnit.module( module2Context.name );

QUnit.test( module2Test1.name, function( assert ) {
	assert.expect( 10 );
	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 2, "QUnit.moduleStart calls" );
	assert.equal( testStart, 3, "QUnit.testStart calls" );
	assert.equal( testDone, 2, "QUnit.testDone calls" );
	assert.equal( moduleDone, 1, "QUnit.moduleDone calls" );

	assert.deepEqual( testContext, {
		module: module2Context.name,
		name: module2Test1.name,
		testId: module2Test1.testId,
		previousFailure: false
	}, "test context" );

	assert.equal(
		moduleDoneContext.runtime >= 0 && moduleDoneContext.runtime < 5000,
		true,
		"module runtime was a reasonable number"
	);
	delete moduleDoneContext.runtime;

	assert.deepEqual( moduleDoneContext, {
		name: module1Context.name,
		tests: module1Context.tests,
		failed: 0,
		passed: 30,
		total: 30
	}, "moduleDone context" );
	assert.deepEqual( moduleContext, module2Context, "module context" );

	assert.equal( log, 39, "QUnit.log calls" );
} );

QUnit.test( module2Test2.name, function( assert ) {
	assert.expect( 8 );
	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 2, "QUnit.moduleStart calls" );
	assert.equal( testStart, 4, "QUnit.testStart calls" );
	assert.equal( testDone, 3, "QUnit.testDone calls" );
	assert.equal( moduleDone, 1, "QUnit.moduleDone calls" );

	assert.deepEqual( testContext, {
		module: module2Context.name,
		name: module2Test2.name,
		testId: module2Test2.testId,
		previousFailure: false
	}, "test context" );
	assert.deepEqual( moduleContext, module2Context, "module context" );

	assert.equal( log, 47, "QUnit.log calls" );
} );

QUnit.skip( module2Test3.name );

QUnit.test( module2Test4.name, function( assert ) {
	assert.expect( 1 );

	delete testDoneContext.source;

	assert.deepEqual( testDoneContext, {
		assertions: [],
		module: module2Context.name,
		name: module2Test3.name,
		failed: 0,
		passed: 0,
		total: 0,
		skipped: true,
		todo: false,
		testId: module2Test3.testId,
		runtime: 0
	}, "testDone context" );
} );

QUnit.todo( module2Test5.name, function( assert ) {
	assert.true( false );
	assert.true( true );
} );

QUnit.test( module2Test6.name, function( assert ) {
	assert.expect( 1 );

	delete testDoneContext.runtime;
	delete testDoneContext.duration;
	delete testDoneContext.source;
	delete testDoneContext.assertions;

	assert.deepEqual( testDoneContext, {
		module: module2Context.name,
		name: module2Test5.name,
		failed: 1,
		passed: 1,
		total: 2,
		skipped: false,
		todo: true,
		testId: module2Test5.testId
	}, "testDone context" );
} );

testAutorun = true;

QUnit.done( function() {

	if ( !testAutorun ) {
		return;
	}

	testAutorun = false;

	moduleStart = moduleDone = 0;

	// Since these tests run *after* done, and as such
	// QUnit is not able to know whether more tests are coming
	// the module starts/ends after each test.
	QUnit.module( "autorun" );

	setTimeout( function() {
		QUnit.test( "first", function( assert ) {
			assert.equal( moduleStart, 1, "test started" );
			assert.equal( moduleDone, 0, "test in progress" );
		} );

		QUnit.test( "second", function( assert ) {
			assert.equal( moduleStart, 2, "test started" );
			assert.equal( moduleDone, 1, "test in progress" );
		} );
	}, 5000 );
} );
<commit_msg>Tests: Remove broken tests for removed "autorun" feature<commit_after>QUnit.config.reorder = false;

var totalTests, moduleContext, moduleDoneContext, testContext, testDoneContext, logContext,
	beginModules,
	module1Test1, module1Test2, module2Test1, module2Test2,
	module2Test3, module2Test4, module2Test5, module2Test6,
	begin = 0,
	moduleStart = 0,
	moduleDone = 0,
	testStart = 0,
	testDone = 0,
	log = 0,
	module1Context = {
		name: "logs1",
		tests: [
			( module1Test1 = {
				"name": "test1",
				"testId": "646e9e25",
				"skip": false
			} ),
			( module1Test2 = {
				"name": "test2",
				"testId": "646e9e26",
				"skip": false
			} )
		]
	},
	module2Context = {
		name: "logs2",
		tests: [
			( module2Test1 = {
				"name": "test1",
				"testId": "9954d966",
				"skip": false
			} ),
			( module2Test2 = {
				"name": "test2",
				"testId": "9954d967",
				"skip": false
			} ),
			( module2Test3 = {
				"name": "a skipped test",
				"testId": "3e797d3a",
				"skip": true
			} ),
			( module2Test4 = {
				"name": "test the log for the skipped test",
				"testId": "d3266148",
				"skip": false
			} ),
			( module2Test5 = {
				"name": "a todo test",
				"testId": "77a47174",
				"skip": false
			} ),
			( module2Test6 = {
				"name": "test the log for the todo test",
				"testId": "5f5ab826",
				"skip": false
			} )
		]
	};

QUnit.begin( function( args ) {
	totalTests = args.totalTests;
	beginModules = args.modules;
	begin++;
} );

QUnit.moduleStart( function( context ) {
	moduleStart++;
	moduleContext = context;
} );

QUnit.moduleDone( function( context ) {
	moduleDone++;
	moduleDoneContext = context;
} );

QUnit.testStart( function( context ) {
	testStart++;
	testContext = context;
} );

QUnit.testDone( function( context ) {
	testDone++;
	testDoneContext = context;
} );

QUnit.log( function( context ) {
	log++;
	logContext = context;
} );

QUnit.module( module1Context.name );

QUnit.test( module1Test1.name, function( assert ) {
	assert.expect( 18 );

	assert.equal(
		typeof totalTests,
		"number",
		"QUnit.begin should pass total amount of tests to callback"
	);

	while ( beginModules.length > 2 ) {
		beginModules.pop();
	}

	assert.deepEqual(
		beginModules,
		[ module1Context, module2Context ],
		"QUnit.begin details registered modules and their respective tests"
	);

	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 1, "QUnit.moduleStart calls" );
	assert.equal( testStart, 1, "QUnit.testStart calls" );
	assert.equal( testDone, 0, "QUnit.testDone calls" );
	assert.equal( moduleDone, 0, "QUnit.moduleDone calls" );

	assert.equal(
		logContext.runtime >= 0 && logContext.runtime < 50,
		true,
		"log runtime was a reasonable number"
	);

	delete logContext.runtime;
	assert.deepEqual( logContext, {
		name: module1Test1.name,
		module: module1Context.name,
		result: true,
		message: "log runtime was a reasonable number",
		actual: true,
		expected: true,
		negative: false,
		testId: module1Test1.testId,
		todo: false
	}, "log context after equal(actual, expected, message)" );

	assert.equal( "foo", "foo" );

	delete logContext.runtime;
	assert.deepEqual( logContext, {
		name: module1Test1.name,
		module: module1Context.name,
		result: true,
		message: undefined,
		actual: "foo",
		expected: "foo",
		negative: false,
		testId: module1Test1.testId,
		todo: false
	}, "log context after equal(actual, expected)" );

	assert.ok( true, "ok(true, message)" );

	delete logContext.runtime;
	assert.deepEqual( logContext, {
		module: module1Context.name,
		name: module1Test1.name,
		result: true,
		message: "ok(true, message)",
		actual: true,
		expected: true,
		negative: false,
		testId: module1Test1.testId,
		todo: false
	}, "log context after ok(true, message)" );

	assert.strictEqual( testDoneContext, undefined, "testDone context" );
	assert.deepEqual( testContext, {
		module: module1Context.name,
		name: module1Test1.name,
		testId: module1Test1.testId,
		previousFailure: false
	}, "test context" );

	assert.strictEqual( moduleDoneContext, undefined, "moduleDone context" );
	assert.deepEqual( moduleContext, module1Context, "module context" );

	assert.equal( log, 17, "QUnit.log calls" );
} );

QUnit.test( module1Test2.name, function( assert ) {
	assert.expect( 12 );
	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 1, "QUnit.moduleStart calls" );
	assert.equal( testStart, 2, "QUnit.testStart calls" );
	assert.equal( testDone, 1, "QUnit.testDone calls" );
	assert.equal( moduleDone, 0, "QUnit.moduleDone calls" );

	assert.equal(
		testDoneContext.runtime >= 0 && testDoneContext.runtime < 1000,
		true,
		"test runtime was a reasonable number"
	);

	assert.true( testDoneContext.assertions instanceof Array, "testDone context: assertions" );

	// TODO: more tests for testDoneContext.assertions

	delete testDoneContext.runtime;

	// Delete testDoneContext.assertions so we can easily jump to next assertion
	delete testDoneContext.assertions;

	// Delete testDoneContext.source
	delete testDoneContext.source;

	assert.deepEqual( testDoneContext, {
		module: module1Context.name,
		name: module1Test1.name,
		failed: 0,
		passed: 18,
		total: 18,
		testId: module1Test1.testId,
		skipped: false,
		todo: false
	}, "testDone context" );
	assert.deepEqual( testContext, {
		module: module1Context.name,
		name: module1Test2.name,
		testId: module1Test2.testId,
		previousFailure: false
	}, "test context" );

	assert.strictEqual( moduleDoneContext, undefined, "moduleDone context" );
	assert.deepEqual( moduleContext, module1Context, "module context" );
	assert.equal( log, 29, "QUnit.log calls" );
} );

QUnit.module( module2Context.name );

QUnit.test( module2Test1.name, function( assert ) {
	assert.expect( 10 );
	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 2, "QUnit.moduleStart calls" );
	assert.equal( testStart, 3, "QUnit.testStart calls" );
	assert.equal( testDone, 2, "QUnit.testDone calls" );
	assert.equal( moduleDone, 1, "QUnit.moduleDone calls" );

	assert.deepEqual( testContext, {
		module: module2Context.name,
		name: module2Test1.name,
		testId: module2Test1.testId,
		previousFailure: false
	}, "test context" );

	assert.equal(
		moduleDoneContext.runtime >= 0 && moduleDoneContext.runtime < 5000,
		true,
		"module runtime was a reasonable number"
	);
	delete moduleDoneContext.runtime;

	assert.deepEqual( moduleDoneContext, {
		name: module1Context.name,
		tests: module1Context.tests,
		failed: 0,
		passed: 30,
		total: 30
	}, "moduleDone context" );
	assert.deepEqual( moduleContext, module2Context, "module context" );

	assert.equal( log, 39, "QUnit.log calls" );
} );

QUnit.test( module2Test2.name, function( assert ) {
	assert.expect( 8 );
	assert.equal( begin, 1, "QUnit.begin calls" );
	assert.equal( moduleStart, 2, "QUnit.moduleStart calls" );
	assert.equal( testStart, 4, "QUnit.testStart calls" );
	assert.equal( testDone, 3, "QUnit.testDone calls" );
	assert.equal( moduleDone, 1, "QUnit.moduleDone calls" );

	assert.deepEqual( testContext, {
		module: module2Context.name,
		name: module2Test2.name,
		testId: module2Test2.testId,
		previousFailure: false
	}, "test context" );
	assert.deepEqual( moduleContext, module2Context, "module context" );

	assert.equal( log, 47, "QUnit.log calls" );
} );

QUnit.skip( module2Test3.name );

QUnit.test( module2Test4.name, function( assert ) {
	assert.expect( 1 );

	delete testDoneContext.source;

	assert.deepEqual( testDoneContext, {
		assertions: [],
		module: module2Context.name,
		name: module2Test3.name,
		failed: 0,
		passed: 0,
		total: 0,
		skipped: true,
		todo: false,
		testId: module2Test3.testId,
		runtime: 0
	}, "testDone context" );
} );

QUnit.todo( module2Test5.name, function( assert ) {
	assert.true( false );
	assert.true( true );
} );

QUnit.test( module2Test6.name, function( assert ) {
	assert.expect( 1 );

	delete testDoneContext.runtime;
	delete testDoneContext.duration;
	delete testDoneContext.source;
	delete testDoneContext.assertions;

	assert.deepEqual( testDoneContext, {
		module: module2Context.name,
		name: module2Test5.name,
		failed: 1,
		passed: 1,
		total: 2,
		skipped: false,
		todo: true,
		testId: module2Test5.testId
	}, "testDone context" );
} );
<|endoftext|>


<commit_before>/* Holds all global constant objects. */
var GLOBAL = {

	EVENT: {
		menuShow:       'menuShow',
		menuHide:       'menuHide',
		numberPress:    'numberPress',    // [number, representations]
		textPress:      'textPress',      // [text]
		subgameStarted: 'subgameStarted', // [game type]
		modeChange:     'modeChange',     // [newMode]
		tryNumber:      'tryNumber',      // [guess, correct number]
		agentGuess:     'agentGuess',     // [guess, correct number]
		waterAdded:     'waterAdded',     // [total amount, added amount]
		plantPress:     'plantPress',     // [garden plant]
		waterPlant:     'waterPlant',     // [garden plant]
		skippable:      'skippable'       // [TimelineMax object]
	},

	AGENT: {
		0: Panda,
		1: Panda,
		2: Panda,
		3: Panda
	},

	STATE: {
		entry:          'Entry',
		playerSetup:    'PlayerSetup',
		chooseScenario: 'chooseScenario',
		garden:         'Garden',
		0:              'Lizard',
		lizardGame:     'Lizard',
		1:              'Mountain',
		mountainGame:   'Mountain',
		2:              'Birdhero',
		birdheroGame:   'Birdhero',
		3:              'Balloon',
		balloonGame:    'Balloon',
		4:              'BeeFlight',
		beeGame:        'BeeFlight'
	},

	MODE: {
		playerDo:   0,
		playerShow: 1,
		agentTry:   2,
		agentDo:    3,
		intro:      4,
		outro:      5,
	},

	NUMBER_REPRESENTATION: {
		none:    0,
		dots:    1,
		fingers: 2,
		strikes: 3,
		objects: 4,
		numbers: 5,
		dice:    6,
		yesno:   15, // Special for yes/no: odd values = yes, even values = no
	},

	METHOD: {
		count: 0,
		basicMath: 1
	},

	FONT: 'The Girl Next Door'
};<commit_msg>Remove unnecessary comma<commit_after>/* Holds all global constant objects. */
var GLOBAL = {

	EVENT: {
		menuShow:       'menuShow',
		menuHide:       'menuHide',
		numberPress:    'numberPress',    // [number, representations]
		textPress:      'textPress',      // [text]
		subgameStarted: 'subgameStarted', // [game type]
		modeChange:     'modeChange',     // [newMode]
		tryNumber:      'tryNumber',      // [guess, correct number]
		agentGuess:     'agentGuess',     // [guess, correct number]
		waterAdded:     'waterAdded',     // [total amount, added amount]
		plantPress:     'plantPress',     // [garden plant]
		waterPlant:     'waterPlant',     // [garden plant]
		skippable:      'skippable'       // [TimelineMax object]
	},

	AGENT: {
		0: Panda,
		1: Panda,
		2: Panda,
		3: Panda
	},

	STATE: {
		entry:          'Entry',
		playerSetup:    'PlayerSetup',
		chooseScenario: 'chooseScenario',
		garden:         'Garden',
		0:              'Lizard',
		lizardGame:     'Lizard',
		1:              'Mountain',
		mountainGame:   'Mountain',
		2:              'Birdhero',
		birdheroGame:   'Birdhero',
		3:              'Balloon',
		balloonGame:    'Balloon',
		4:              'BeeFlight',
		beeGame:        'BeeFlight'
	},

	MODE: {
		playerDo:   0,
		playerShow: 1,
		agentTry:   2,
		agentDo:    3,
		intro:      4,
		outro:      5,
	},

	NUMBER_REPRESENTATION: {
		none:    0,
		dots:    1,
		fingers: 2,
		strikes: 3,
		objects: 4,
		numbers: 5,
		dice:    6,
		yesno:   15 // Special for yes/no: odd values = yes, even values = no
	},

	METHOD: {
		count: 0,
		basicMath: 1
	},

	FONT: 'The Girl Next Door'
};<|endoftext|>


<commit_before>'use strict';

let Promise = require('bluebird'),
  urlParser = require('url'),
  log = require('intel'),
  BmpRunner = require('./bmp_runner'),
  harBuilder = require('../support/har_builder'),
  trafficShapeParser = require('../support/traffic_shape_parser');

class ProxyRunDelegate {
  constructor(options) {
    this.trafficShapeConfig = trafficShapeParser.parseTrafficShapeConfig(options);
    this.createHar = !options.skipHar;

    if (this.trafficShapeConfig || options.basicAuth || this.createHar === true) {
      this.bmpRunner = new BmpRunner();
    }
  }

  __runIfProxy(block) {
    if (this.bmpRunner) {
      return block();
    } else {
      return Promise.resolve()
    }
  }

  onStart() {
    return this.__runIfProxy(() => this.bmpRunner.start());
  }

  onStartRun(url, options) {
    return this.__runIfProxy(() => {
      this.isFirstPage = true;
      let promise = this.bmpRunner.startProxy()
        .tap(() => {
          let proxyConfigTasks = [];
          if (this.trafficShapeConfig) {
            proxyConfigTasks.push(this.bmpRunner.setLimit(this.trafficShapeConfig));
          }
          const auth = options.basicAuth;
          if (auth) {
            if (!auth.domain) {
              auth.domain = urlParser.parse(url).host;
              log.verbose('Extracting domain %s for basic authentication from url', auth.domain);
            }
            proxyConfigTasks.push(this.bmpRunner.addBasicAuth(auth.domain, auth.username, auth.password));
          }
          return Promise.all(proxyConfigTasks);
        })
        .tap((proxyPort) => {
          options.proxyPort = proxyPort;
        });

      if (this.createHar) {
        promise = promise.then(() => this.bmpRunner.createHAR());
      }

      return promise;

    });
  }

  onStartPage() {
    return this.__runIfProxy(() => {
      let promise = Promise.resolve();

      if (this.createHar && !this.isFirstPage) {
        promise = this.bmpRunner.startNewPage();
      }

      this.isFirstPage = false;

      return promise;
    });
  }

  onStopRun(result) {
    return this.__runIfProxy(() => {
      let promise = Promise.resolve();

      if (this.createHar) {
        promise = promise.then(() => {
          this.bmpRunner.getHAR()
            .then(JSON.parse)
            .then((har) => {
              harBuilder.addCreator(har);
              result.har = har;
              return result;
            });
        });
      }

      return promise.tap(() => this.bmpRunner.stopProxy());
    });
  }

  onStop() {
    return this.__runIfProxy(() => {
      log.debug('Stopping proxy process');
      return this.bmpRunner.stop()
        .tap(() => {
          log.debug('Stopped proxy process');
        });
    });
  }

}

module.exports = ProxyRunDelegate;<commit_msg>Proxy was being closed before getHAR had finished.<commit_after>'use strict';

let Promise = require('bluebird'),
  urlParser = require('url'),
  log = require('intel'),
  BmpRunner = require('./bmp_runner'),
  harBuilder = require('../support/har_builder'),
  trafficShapeParser = require('../support/traffic_shape_parser');

class ProxyRunDelegate {
  constructor(options) {
    this.trafficShapeConfig = trafficShapeParser.parseTrafficShapeConfig(options);
    this.createHar = !options.skipHar;

    if (this.trafficShapeConfig || options.basicAuth || this.createHar === true) {
      this.bmpRunner = new BmpRunner();
    }
  }

  __runIfProxy(block) {
    if (this.bmpRunner) {
      return block();
    } else {
      return Promise.resolve()
    }
  }

  onStart() {
    return this.__runIfProxy(() => this.bmpRunner.start());
  }

  onStartRun(url, options) {
    return this.__runIfProxy(() => {
      this.isFirstPage = true;
      let promise = this.bmpRunner.startProxy()
        .tap(() => {
          let proxyConfigTasks = [];
          if (this.trafficShapeConfig) {
            proxyConfigTasks.push(this.bmpRunner.setLimit(this.trafficShapeConfig));
          }
          const auth = options.basicAuth;
          if (auth) {
            if (!auth.domain) {
              auth.domain = urlParser.parse(url).host;
              log.verbose('Extracting domain %s for basic authentication from url', auth.domain);
            }
            proxyConfigTasks.push(this.bmpRunner.addBasicAuth(auth.domain, auth.username, auth.password));
          }
          return Promise.all(proxyConfigTasks);
        })
        .tap((proxyPort) => {
          options.proxyPort = proxyPort;
        });

      if (this.createHar) {
        promise = promise.then(() => this.bmpRunner.createHAR());
      }

      return promise;

    });
  }

  onStartPage() {
    return this.__runIfProxy(() => {
      let promise = Promise.resolve();

      if (this.createHar && !this.isFirstPage) {
        promise = this.bmpRunner.startNewPage();
      }

      this.isFirstPage = false;

      return promise;
    });
  }

  onStopRun(result) {
    return this.__runIfProxy(() => {
      let promise = Promise.resolve();

      if (this.createHar) {
        promise = promise.then(() => {
          return this.bmpRunner.getHAR()
            .then(JSON.parse)
            .then((har) => {
              harBuilder.addCreator(har);
              result.har = har;
              return result;
            });
        });
      }

      return promise.tap(() => this.bmpRunner.stopProxy());
    });
  }

  onStop() {
    return this.__runIfProxy(() => {
      log.debug('Stopping proxy process');
      return this.bmpRunner.stop()
        .tap(() => {
          log.debug('Stopped proxy process');
        });
    });
  }

}

module.exports = ProxyRunDelegate;<|endoftext|>


<commit_before>this.mmooc=this.mmooc||{};

this.mmooc.api = function() {
    var _urlToTypeMapping = [];

    _urlToTypeMapping['quizzes'] = 'Quiz';
    _urlToTypeMapping['assignments'] = 'Assignment';
    _urlToTypeMapping['discussion_topics'] = 'Discussion';

    return {
        _ajax: typeof $   !== "undefined" ? $   : {},

        _env:  typeof ENV !== "undefined" ? ENV : {},

        _location: typeof document !== "undefined" ? document.location : {search:"", href:""},

        _uriPrefix: "/api/v1",

        _defaultError: function (event, jqxhr, settings, thrownError) {
            console.log(event, jqxhr, settings, thrownError);
        },

        _get: function(options) {
            var error    = options.error || this._defaultError;
            var uri      = this._uriPrefix + options.uri;
            var params   = options.params || {};
            var callback = options.callback;
            this._ajax.get(uri, params, callback).fail(error);
        },

        getCurrentModuleItemId : function() {
            var paramName = "module_item_id";
            var q = "" + this._location.search;
            if (typeof q === "undefined" || q.indexOf(paramName) == -1) {
                return null;
            }

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentContentId : function() {
            var q = "" + this._location.pathname;

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentTypeAndContentId: function() {
            var regexp = /\/courses\/\d\/\w+\/\d/;

            if (regexp.test("" + this._location.pathname)) {
                var tmp = this._location.pathname.split("/");
                if (tmp.length >= 5) {
                    var type = _urlToTypeMapping[tmp[3]];
                    var contentId = parseInt(tmp[4], 10);
                    return { contentId: contentId, type: type};
                }
            }
            return null;
        },

        getEnrolledCourses: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses",
                "params":   { "include": ["syllabus_body" , "course_progress"] }
            });
        },

        /* FIXME Regarding include items: This parameter suggests that
         * Canvas return module items directly in the Module object
         * JSON, to avoid having to make separate API requests for
         * each module when enumerating modules and items. Canvas is
         * free to omit 'items' for any particular module if it deems
         * them too numerous to return inline. Callers must be
         * prepared to use the List Module Items API if items are not
         * returned.
         */
        getModulesForCurrentCourse: function(callback, error) {
            var courseId = this.getCurrentCourseId();
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId + "/modules",
                "params":   { "include": ["items"] }
            });
        },

        getCurrentCourseId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/courses\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            } else if (this._env.group) {
                // Group pages does not contain course id in URL, but is available via JavaScript variable
                return this._env.group.context_id;
            } else if ($("#section-tabs-header-subtitle").size() > 0) {
                // Group subpages contains course id only in a link
                var tmp = $("#section-tabs-header-subtitle").attr("href").split("/");
                if (tmp.length == 3) {
                    return parseInt(tmp[2], 10);
                }
            }

            return null;
        },

        getCourse: function(courseId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId,
                "params":   {  }
            });
        },

        getCurrentGroupId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/groups\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            }
            return null;
        },

        getGroup: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId,
                "params":   {}
            });
        },

        getGroupMembers: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId + "/users",
                "params":   {"include": ["avatar_url"] }
            });
        },

        getCurrentModule: function(callback, error) {
            var currentModuleItemId = this.getCurrentModuleItemId();
            var currentTypeAndContentId = null;
            if (currentModuleItemId == null) {
                currentTypeAndContentId = this.getCurrentTypeAndContentId();
                if (currentTypeAndContentId == null) {
                    return;
                }
            }

            this.getModulesForCurrentCourse(function(modules) {
                for (var i = 0; i < modules.length; i++) {
                    var module = modules[i];
                    var items = module.items;
                    for (var j = 0; j < items.length; j++) {
                        var item = items[j];
                        if (item.id == currentModuleItemId || (currentTypeAndContentId != null && currentTypeAndContentId.contentId == item.content_id && currentTypeAndContentId.type == item.type)) {
                            item.isCurrent = true;
                            callback(module);
                            return;
                        }
                    }
                }

            }, error);
        },

        getRoles : function() {
            return this._env.current_user_roles;
        },

        getUser : function() {
            return this._env.current_user;
        },

        getActivityStreamForUser: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/users/self/activity_stream",
                "params":   { }
            });
        },

        currentPageIsAnnouncement: function() {
            return ($("#section-tabs").find("a.announcements.active").size() == 1);
        },

        currentPageIsModuleItem: function() {
            if (this.getCurrentModuleItemId() != null || this.getCurrentTypeAndContentId() != null) {
                return true;
            } else {
                return false;
            }
        },
        getUnreadMessageSize: function() {
          return parseInt(document.getElementsByClassName('unread-messages-count')[0].innerHTML);
        }
    };
}();

if (typeof module !== "undefined" && module !== null) {
    module.exports = this.mmooc.api;
}
<commit_msg>MAT-194: show left menu during quiz as well<commit_after>this.mmooc=this.mmooc||{};

this.mmooc.api = function() {
    var _urlToTypeMapping = [];

    _urlToTypeMapping['quizzes'] = 'Quiz';
    _urlToTypeMapping['assignments'] = 'Assignment';
    _urlToTypeMapping['discussion_topics'] = 'Discussion';

    return {
        _ajax: typeof $   !== "undefined" ? $   : {},

        _env:  typeof ENV !== "undefined" ? ENV : {},

        _location: typeof document !== "undefined" ? document.location : {search:"", href:""},

        _uriPrefix: "/api/v1",

        _defaultError: function (event, jqxhr, settings, thrownError) {
            console.log(event, jqxhr, settings, thrownError);
        },

        _get: function(options) {
            var error    = options.error || this._defaultError;
            var uri      = this._uriPrefix + options.uri;
            var params   = options.params || {};
            var callback = options.callback;
            this._ajax.get(uri, params, callback).fail(error);
        },

        getCurrentModuleItemId : function() {
            var paramName = "module_item_id";
            var q = "" + this._location.search;
            if (typeof q === "undefined" || q.indexOf(paramName) == -1) {
                return null;
            }

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentContentId : function() {
            var q = "" + this._location.pathname;

            var moduleId = q.substring(q.indexOf(paramName) + paramName.length + 1, q.length);
            if (moduleId.indexOf("&") != -1) {
                moduleId = moduleId.substring(0, moduleId.indexOf("&"));
            }

            return parseInt(moduleId, 10);
        },

        getCurrentTypeAndContentId: function() {
            var regexp = /\/courses\/\d+\/\w+\/\d+/;

            if (regexp.test("" + this._location.pathname)) {
                var tmp = this._location.pathname.split("/");
                if (tmp.length >= 5) {
                    var type = _urlToTypeMapping[tmp[3]];
                    var contentId = parseInt(tmp[4], 10);
                    return { contentId: contentId, type: type};
                }
            }
            return null;
        },

        getEnrolledCourses: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses",
                "params":   { "include": ["syllabus_body" , "course_progress"] }
            });
        },

        /* FIXME Regarding include items: This parameter suggests that
         * Canvas return module items directly in the Module object
         * JSON, to avoid having to make separate API requests for
         * each module when enumerating modules and items. Canvas is
         * free to omit 'items' for any particular module if it deems
         * them too numerous to return inline. Callers must be
         * prepared to use the List Module Items API if items are not
         * returned.
         */
        getModulesForCurrentCourse: function(callback, error) {
            var courseId = this.getCurrentCourseId();
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId + "/modules",
                "params":   { "include": ["items"] }
            });
        },

        getCurrentCourseId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/courses\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            } else if (this._env.group) {
                // Group pages does not contain course id in URL, but is available via JavaScript variable
                return this._env.group.context_id;
            } else if ($("#section-tabs-header-subtitle").size() > 0) {
                // Group subpages contains course id only in a link
                var tmp = $("#section-tabs-header-subtitle").attr("href").split("/");
                if (tmp.length == 3) {
                    return parseInt(tmp[2], 10);
                }
            }

            return null;
        },

        getCourse: function(courseId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/courses/" + courseId,
                "params":   {  }
            });
        },

        getCurrentGroupId: function() {
            var currentUrl = "" + this._location.pathname;
            var matches = currentUrl.match(/\/groups\/(\d+)/);
            if (matches != null) {
                return parseInt(matches[1], 10);
            }
            return null;
        },

        getGroup: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId,
                "params":   {}
            });
        },

        getGroupMembers: function(groupId, callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/groups/" + groupId + "/users",
                "params":   {"include": ["avatar_url"] }
            });
        },

        getCurrentModule: function(callback, error) {
            var currentModuleItemId = this.getCurrentModuleItemId();
            var currentTypeAndContentId = null;
            if (currentModuleItemId == null) {
                currentTypeAndContentId = this.getCurrentTypeAndContentId();
                if (currentTypeAndContentId == null) {
                    return;
                }
            }

            this.getModulesForCurrentCourse(function(modules) {
                for (var i = 0; i < modules.length; i++) {
                    var module = modules[i];
                    var items = module.items;
                    for (var j = 0; j < items.length; j++) {
                        var item = items[j];
                        if (item.id == currentModuleItemId || (currentTypeAndContentId != null && currentTypeAndContentId.contentId == item.content_id && currentTypeAndContentId.type == item.type)) {
                            item.isCurrent = true;
                            callback(module);
                            return;
                        }
                    }
                }

            }, error);
        },

        getRoles : function() {
            return this._env.current_user_roles;
        },

        getUser : function() {
            return this._env.current_user;
        },

        getActivityStreamForUser: function(callback, error) {
            this._get({
                "callback": callback,
                "error":    error,
                "uri":      "/users/self/activity_stream",
                "params":   { }
            });
        },

        currentPageIsAnnouncement: function() {
            return ($("#section-tabs").find("a.announcements.active").size() == 1);
        },

        currentPageIsModuleItem: function() {
            if (this.getCurrentModuleItemId() != null || this.getCurrentTypeAndContentId() != null) {
                return true;
            } else {
                return false;
            }
        },
        getUnreadMessageSize: function() {
          return parseInt(document.getElementsByClassName('unread-messages-count')[0].innerHTML);
        }
    };
}();

if (typeof module !== "undefined" && module !== null) {
    module.exports = this.mmooc.api;
}
<|endoftext|>


<commit_before>"use strict";

var PluginError = require("gulp-util").PluginError;
var gulp = require("gulp");
var es = require("event-stream");
var through = require("through2");
var _ = require("lodash");

var assignPrefix = require("./assignPrefix");
var createArray = require("./createArray");
var mergeChunks = require("./mergeChunks");

var defaults = {
    assetsDir: "./",
    pipelines: {}
};

module.exports = function (findBuilds, insertFile) {
    return function (options) {
        options = _.extend({}, defaults, options);

        var getStreamForPipeline = function (name) {
            return options.pipelines[name]();
        };

        var pushStreamToPipeline = function (stream, name) {
            if ( options.pipelines[name] ) {
                return stream.pipe(getStreamForPipeline(name));
            }

            return stream;
        };

        var process = function (file, encoding, callback) {
            var self = this;

            if ( file.isNull() ) {
                callback();
                return;
            }

            if ( file.isStream() ) {
                throw new PluginError("gulp-spa", "Streaming not supported");
            }

            var processed = findBuilds(String(file.contents));
            processed.builds.forEach(assignPrefix);

            var mainPipeline = through.obj();

            var finishMain = function () {
                var contents = mergeChunks({
                    chunks: processed.chunks,
                    files: files,
                    insertFile: insertFile,
                    itemSeparators: _.pluck(processed.builds, "itemSeparator"),
                    urlPrefixes: _.pluck(processed.builds, "urlPrefix")
                });

                file.contents = new Buffer(contents);
                mainPipeline.push(file);
            };

            if ( _.isEmpty(processed.builds) ) {
                finishMain();
            } else {
                var streams = processed.builds.map(function (build) {
                    if ( build.files.length === 0 ) {
                        return getStreamForPipeline(build.id);
                    }

                    var stream = gulp.src(build.files, { cwd: options.assetsDir, base: options.assetsDir });
                    return pushStreamToPipeline(stream, build.id);
                });

                var files = streams.map(createArray);

                streams.forEach(function (stream, index) {
                    var fileList = files[index];
                    stream.on("data", fileList.push.bind(fileList));
                    stream.on("data", self.push.bind(self));
                });

                var all = es.merge.apply(es, streams);

                all.on("end", finishMain);
            }

            pushStreamToPipeline(mainPipeline, "main").on("data", function (file) {
                self.push(file);
                callback();
            });
        };

        return through.obj(process);
    };
};
<commit_msg>Changed pipeline handling to fix #4.<commit_after>"use strict";

var PluginError = require("gulp-util").PluginError;
var gulp = require("gulp");
var es = require("event-stream");
var through = require("through2");
var _ = require("lodash");

var assignPrefix = require("./assignPrefix");
var createArray = require("./createArray");
var mergeChunks = require("./mergeChunks");

var defaults = {
    assetsDir: "./",
    pipelines: {}
};

module.exports = function (findBuilds, insertFile) {
    return function (options) {
        options = _.extend({}, defaults, options);

        var getCallbackForPipeline = function (name) {
            return options.pipelines[name];
        };

        var pushStreamToPipeline = function (stream, name) {
            if ( options.pipelines[name] ) {
                return getCallbackForPipeline(name)(stream);
            }

            return stream;
        };

        var process = function (file, encoding, callback) {
            var self = this;

            if ( file.isNull() ) {
                callback();
                return;
            }

            if ( file.isStream() ) {
                throw new PluginError("gulp-spa", "Streaming not supported");
            }

            var processed = findBuilds(String(file.contents));
            processed.builds.forEach(assignPrefix);

            var mainPipeline = through.obj();

            var finishMain = function () {
                var contents = mergeChunks({
                    chunks: processed.chunks,
                    files: files,
                    insertFile: insertFile,
                    itemSeparators: _.pluck(processed.builds, "itemSeparator"),
                    urlPrefixes: _.pluck(processed.builds, "urlPrefix")
                });

                file.contents = new Buffer(contents);
                mainPipeline.push(file);
            };

            if ( _.isEmpty(processed.builds) ) {
                finishMain();
            } else {
                var streams = processed.builds.map(function (build) {
                    if ( build.files.length === 0 ) {
                        return getCallbackForPipeline(build.id)();
                    }

                    var stream = gulp.src(build.files, { cwd: options.assetsDir, base: options.assetsDir });
                    return pushStreamToPipeline(stream, build.id);
                });

                var files = streams.map(createArray);

                streams.forEach(function (stream, index) {
                    var fileList = files[index];
                    stream.on("data", fileList.push.bind(fileList));
                    stream.on("data", self.push.bind(self));
                });

                var all = es.merge.apply(es, streams);

                all.on("end", finishMain);
            }

            pushStreamToPipeline(mainPipeline, "main").on("data", function (file) {
                self.push(file);
                callback();
            });
        };

        return through.obj(process);
    };
};
<|endoftext|>


<commit_before>var events = require('events'),
    querystring = require('querystring'),
    Args = require('vargs').Constructor,
    follow = require('follow'),
    cradle = require('../../cradle'),
    Database = require('./index').Database;

Database.prototype.changes = function (options, callback) {
    if (typeof(options) === 'function') {
        callback = options;
        options = {};
    }

    options = options || {};

    if (callback) {
        return this.query({
            method: 'GET',
            path: '_changes',
            query: options
        }, callback);
    }

    var response = new events.EventEmitter(),
        responded = false,
        auth = '',
        feed;

    if (!options.db) {
        if (this.connection.auth && this.connection.auth.username
            && this.connection.auth.password) {
            auth = this.connection.auth.username + ':' + this.connection.auth.password + '@';
        }

        options.db = 'http://' + auth + this.connection.host + ':' + this.connection.port + '/' + this.name;
    }

    feed = new follow.Feed(options);
    feed.on('change', function () {
        //
        // Remark: Support the legacy `data` events.
        //
        if (!responded) {
            responded = true;
            feed.emit('response', response);
        }

        response.emit.apply(response, ['data'].concat(Array.prototype.slice.call(arguments)));
    });

    if (options.follow !== false) {
      feed.follow();
    }

    return feed;
};
<commit_msg>Use protocol from connection<commit_after>var events = require('events'),
    querystring = require('querystring'),
    Args = require('vargs').Constructor,
    follow = require('follow'),
    cradle = require('../../cradle'),
    Database = require('./index').Database;

Database.prototype.changes = function (options, callback) {
    if (typeof(options) === 'function') {
        callback = options;
        options = {};
    }

    options = options || {};

    if (callback) {
        return this.query({
            method: 'GET',
            path: '_changes',
            query: options
        }, callback);
    }

    var response = new events.EventEmitter(),
        responded = false,
        protocol,
        auth = '',
        feed;

    if (!options.db) {
        protocol = this.connection.protocol || 'http';

        if (this.connection.auth && this.connection.auth.username
            && this.connection.auth.password) {
            auth = this.connection.auth.username + ':' + this.connection.auth.password + '@';
        }

        options.db = protocol + '://' + auth + this.connection.host + ':' + this.connection.port + '/' + this.name;
    }

    feed = new follow.Feed(options);
    feed.on('change', function () {
        //
        // Remark: Support the legacy `data` events.
        //
        if (!responded) {
            responded = true;
            feed.emit('response', response);
        }

        response.emit.apply(response, ['data'].concat(Array.prototype.slice.call(arguments)));
    });

    if (options.follow !== false) {
      feed.follow();
    }

    return feed;
};
<|endoftext|>


<commit_before>
module.exports = errorHandler

var cbCalled = false
  , log = require("./log")
  , npm = require("../../npm")
  , rm = require("./rm-rf")
  , constants = require("constants")
  , itWorked = false
  , path = require("path")

process.on("exit", function (code) {
  if (code) itWorked = false
  if (itWorked) log("ok")
  else {
    log.error([""
              ,"Additional logging details can be found in:"
              ,"    " + path.resolve("npm-debug.log")
              ].join("\n"))
    log.win("not ok")
  }
  itWorked = false // ready for next exit
})

function errorHandler (er) {
  if (cbCalled) throw new Error("Callback called more than once.")
  cbCalled = true
  if (!er) return exit(0)
  if (!(er instanceof Error)) {
    log.error(er)
    return exit(1)
  }
  if (!er.errno) {
    var m = er.message.match(/^(?:Error: )?(E[A-Z]+)/)
    if (m) {
      m = m[1]
      if (!constants[m] && !npm[m]) constants[m] = {}
      er.errno = npm[m] || constants[m]
    }
  }

  switch (er.errno) {
  case constants.ECONNREFUSED:
    log.error(er)
    log.error(["If you are using Cygwin, please set up your /etc/resolv.conf"
              ,"See step 4 in this wiki page:"
              ,"    http://github.com/ry/node/wiki/Building-node.js-on-Cygwin-%28Windows%29"
              ,"If you are not using Cygwin, please report this"
              ,"at <http://github.com/isaacs/npm/issues>"
              ,"or email it to <npm-@googlegroups.com>"
              ].join("\n"))
    break

  case constants.EACCES:
  case constants.EPERM:
    log.error(er)
    log.error(["",
              "Please use 'sudo' or log in as root to run this command."
              ,""
              ,"    sudo npm "
                +npm.config.get("argv").original.map(JSON.stringify).join(" ")
              ,""
              ,"or set the 'unsafe-perm' config var to true."
              ,""
              ,"    npm config set unsafe-perm true"
              ].join("\n"))
    break

  case npm.ELIFECYCLE:
    log.error(er.message)
    log.error(["","Failed at the "+er.pkgid+" "+er.stage+" script."
              ,"This is most likely a problem with the "+er.pkgname+" package,"
              ,"not with npm itself."
              ,"Tell the author that this fails on your system:"
              ,"    "+er.script
              ,"You can get their info via:"
              ,"    npm owner ls "+er.pkgname
              ,"There is likely additional logging output above."
              ].join("\n"))
    break

  case npm.EJSONPARSE:
    log.error(er.message)
    log.error("File: "+er.file)
    log.error(["Failed to parse package.json data."
              ,"package.json must be actual JSON, not just JavaScript."
              ,"","This is not a bug in npm."
              ,"Tell the package author to fix their package.json file."
              ].join("\n"), "JSON.parse")
    break

  case npm.E404:
    log.error(["'"+er.pkgid+"' is not in the npm registry."
              ,"You should bug the author to publish it."
              ,"Note that you can also install from a tarball or folder."
              ].join("\n"), "404")
    break

  case npm.EPUBLISHCONFLICT:
    log.error(["Cannot publish over existing version."
              ,"Bump the 'version' field, set the --force flag, or"
              ,"    npm unpublish '"+er.pkgid+"'"
              ,"and try again"
              ].join("\n"), "publish fail" )
    break

  case npm.EISGIT:
    log.error([er.message
              ,"    "+er.path
              ,"Refusing to remove it. Update manually,"
              ,"or move it out of the way first."
              ].join("\n"), "git" )
    break

  case npm.ECYCLE:
    log.error([er.message
              ,"While installing: "+er.pkgid
              ,"Found a pathological dependency case that npm cannot solve."
              ,"Please report this to the package author."
              ].join("\n"))
    break

  case npm.EENGINE:
    log.error([er.message
              ,"Not compatible with your version of node/npm: "+er.pkgid
              ,"Required: "+JSON.stringify(er.required)
              ,"Actual:   "+JSON.stringify({npm:npm.version
                                           ,node:process.version})
              ].join("\n"))
    break

  case constants.EEXIST:
    log.error([er.message
              ,"File exists: "+er.path
              ,"Move it away, and try again."].join("\n"))
    break

  default:
    log.error(er)
    log.error(["Report this *entire* log at:"
              ,"    <http://github.com/isaacs/npm/issues>"
              ,"or email it to:"
              ,"    <npm-@googlegroups.com>"
              ].join("\n"))
    break
  }

  var os = require("os")
  log.error("")
  log.error(os.type() + " " + os.release(), "System")
  log.error(process.argv
            .map(JSON.stringify).join(" "), "command")
  exit(typeof er.errno === "number" ? er.errno : 1)
}

function exit (code) {
  var doExit = npm.config.get("_exit")
  log.verbose([code, doExit], "exit")
  if (code) writeLogFile(reallyExit)
  else {
    rm("npm-debug.log", function () { rm(npm.tmp, reallyExit) })
  }
  function reallyExit() {
    itWorked = !code
    if (doExit) process.exit(code || 0)
    else process.emit("exit", code || 0)
  }
}

function writeLogFile (cb) {
  var fs = require("./graceful-fs")
    , fstr = fs.createWriteStream("npm-debug.log")
    , sys = require("util")

  log.history.forEach(function (m) {
    var lvl = log.LEVEL[m.level]
      , pref = m.pref ? " " + m.pref : ""
      , b = lvl + pref + " "
      , msg = typeof m.msg === "string" ? m.msg
            : msg instanceof Error ? msg.stack || msg.message
            : sys.inspect(m.msg, 0, 4)
    fstr.write(new Buffer(b
                         +(msg.split(/\n+/).join("\n"+b))
                         + "\n"))
  })
  fstr.on("close", cb)
}
<commit_msg>report case when cb() never called.<commit_after>
module.exports = errorHandler

var cbCalled = false
  , log = require("./log")
  , npm = require("../../npm")
  , rm = require("./rm-rf")
  , constants = require("constants")
  , itWorked = false
  , path = require("path")

process.on("exit", function (code) {
  if (code) itWorked = false
  if (itWorked) log("ok")
  else {
    if (!cbCalled) {
      log.error("cb() never called!\n ")
    }
    log.error([""
              ,"Additional logging details can be found in:"
              ,"    " + path.resolve("npm-debug.log")
              ].join("\n"))
    log.win("not ok")
  }
  itWorked = false // ready for next exit
})

function errorHandler (er) {
  if (cbCalled) throw new Error("Callback called more than once.")
  cbCalled = true
  if (!er) return exit(0)
  if (!(er instanceof Error)) {
    log.error(er)
    return exit(1)
  }
  if (!er.errno) {
    var m = er.message.match(/^(?:Error: )?(E[A-Z]+)/)
    if (m) {
      m = m[1]
      if (!constants[m] && !npm[m]) constants[m] = {}
      er.errno = npm[m] || constants[m]
    }
  }

  switch (er.errno) {
  case constants.ECONNREFUSED:
    log.error(er)
    log.error(["If you are using Cygwin, please set up your /etc/resolv.conf"
              ,"See step 4 in this wiki page:"
              ,"    http://github.com/ry/node/wiki/Building-node.js-on-Cygwin-%28Windows%29"
              ,"If you are not using Cygwin, please report this"
              ,"at <http://github.com/isaacs/npm/issues>"
              ,"or email it to <npm-@googlegroups.com>"
              ].join("\n"))
    break

  case constants.EACCES:
  case constants.EPERM:
    log.error(er)
    log.error(["",
              "Please use 'sudo' or log in as root to run this command."
              ,""
              ,"    sudo npm "
                +npm.config.get("argv").original.map(JSON.stringify).join(" ")
              ,""
              ,"or set the 'unsafe-perm' config var to true."
              ,""
              ,"    npm config set unsafe-perm true"
              ].join("\n"))
    break

  case npm.ELIFECYCLE:
    log.error(er.message)
    log.error(["","Failed at the "+er.pkgid+" "+er.stage+" script."
              ,"This is most likely a problem with the "+er.pkgname+" package,"
              ,"not with npm itself."
              ,"Tell the author that this fails on your system:"
              ,"    "+er.script
              ,"You can get their info via:"
              ,"    npm owner ls "+er.pkgname
              ,"There is likely additional logging output above."
              ].join("\n"))
    break

  case npm.EJSONPARSE:
    log.error(er.message)
    log.error("File: "+er.file)
    log.error(["Failed to parse package.json data."
              ,"package.json must be actual JSON, not just JavaScript."
              ,"","This is not a bug in npm."
              ,"Tell the package author to fix their package.json file."
              ].join("\n"), "JSON.parse")
    break

  case npm.E404:
    log.error(["'"+er.pkgid+"' is not in the npm registry."
              ,"You should bug the author to publish it."
              ,"Note that you can also install from a tarball or folder."
              ].join("\n"), "404")
    break

  case npm.EPUBLISHCONFLICT:
    log.error(["Cannot publish over existing version."
              ,"Bump the 'version' field, set the --force flag, or"
              ,"    npm unpublish '"+er.pkgid+"'"
              ,"and try again"
              ].join("\n"), "publish fail" )
    break

  case npm.EISGIT:
    log.error([er.message
              ,"    "+er.path
              ,"Refusing to remove it. Update manually,"
              ,"or move it out of the way first."
              ].join("\n"), "git" )
    break

  case npm.ECYCLE:
    log.error([er.message
              ,"While installing: "+er.pkgid
              ,"Found a pathological dependency case that npm cannot solve."
              ,"Please report this to the package author."
              ].join("\n"))
    break

  case npm.EENGINE:
    log.error([er.message
              ,"Not compatible with your version of node/npm: "+er.pkgid
              ,"Required: "+JSON.stringify(er.required)
              ,"Actual:   "+JSON.stringify({npm:npm.version
                                           ,node:process.version})
              ].join("\n"))
    break

  case constants.EEXIST:
    log.error([er.message
              ,"File exists: "+er.path
              ,"Move it away, and try again."].join("\n"))
    break

  default:
    log.error(er)
    log.error(["Report this *entire* log at:"
              ,"    <http://github.com/isaacs/npm/issues>"
              ,"or email it to:"
              ,"    <npm-@googlegroups.com>"
              ].join("\n"))
    break
  }

  var os = require("os")
  log.error("")
  log.error(os.type() + " " + os.release(), "System")
  log.error(process.argv
            .map(JSON.stringify).join(" "), "command")
  exit(typeof er.errno === "number" ? er.errno : 1)
}

function exit (code) {
  var doExit = npm.config.get("_exit")
  log.verbose([code, doExit], "exit")
  if (code) writeLogFile(reallyExit)
  else {
    rm("npm-debug.log", function () { rm(npm.tmp, reallyExit) })
  }
  function reallyExit() {
    itWorked = !code
    if (doExit) process.exit(code || 0)
    else process.emit("exit", code || 0)
  }
}

function writeLogFile (cb) {
  var fs = require("./graceful-fs")
    , fstr = fs.createWriteStream("npm-debug.log")
    , sys = require("util")

  log.history.forEach(function (m) {
    var lvl = log.LEVEL[m.level]
      , pref = m.pref ? " " + m.pref : ""
      , b = lvl + pref + " "
      , msg = typeof m.msg === "string" ? m.msg
            : msg instanceof Error ? msg.stack || msg.message
            : sys.inspect(m.msg, 0, 4)
    fstr.write(new Buffer(b
                         +(msg.split(/\n+/).join("\n"+b))
                         + "\n"))
  })
  fstr.on("close", cb)
}
<|endoftext|>


<commit_before>const googlemaps = {
	provider_name: "maps.google.com",
	endpoints: [{
		schemes: [/.*google\.[^/]+\/maps\/place\/.+/],
		builder: function(urlObj, obj) {
			var match = /.*google\.[^/]+\/maps\/place\/([\w+]*)\/.*/.exec(urlObj.href);
			if (!match || match.length != 2) return;
			var place = encodeURIComponent(match[1]);
			obj.type = "embed";
			obj.html = `<iframe src="//maps.google.com/maps?t=m&q=${place}&output=embed"></iframe>`;
		}
	}]
};

const youtube = {
	provider_name: "youtube.com",
	endpoints: [{
		schemes: [
			'https://*.youtube.com/v/*',
			'https://*.youtube.com/embed/*',
			'https://youtu.be/*'
		],
		url: 'https://www.youtube.com/oembed',
		redirect: function(obj) {
			if (obj.pathname == "/watch") return;
			var videoId;
			if (obj.pathname.startsWith("/embed/")) {
				videoId = obj.pathname.split('/').pop();
			} else if (obj.hostname == "youtu.be") {
				videoId = obj.pathname.substring(1);
			}
			if (!videoId) return;
			delete obj.href;
			delete obj.pathname;
			delete obj.search;
			delete obj.query;
			obj.path = "/watch?v=" + encodeURIComponent(videoId);
			obj.hostname = "www.youtube.com";
			return true;
		}
	}]
};

const twitter = {
	provider_name: "youtube.com",
	endpoints: [{
		schemes: [
			'https://twitter.com/*/status/*'
		],
		redirect: function(obj) {
			return true;
		}
	}]
};

const instagram = {
	provider_name: "instagram.com",
	endpoints: [{
		schemes: [
			'https://www.instagram.com/*/*/'
		],
		redirect: function (obj) {
			obj.headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15";
			return true;
		}
	}]
};

module.exports = [googlemaps, youtube, twitter, instagram];

<commit_msg>Small notes<commit_after>const googlemaps = {
	provider_name: "maps.google.com",
	endpoints: [{
		schemes: [/.*google\.[^/]+\/maps\/place\/.+/],
		builder: function(urlObj, obj) {
			var match = /.*google\.[^/]+\/maps\/place\/([\w+]*)\/.*/.exec(urlObj.href);
			if (!match || match.length != 2) return;
			var place = encodeURIComponent(match[1]);
			obj.type = "embed";
			obj.html = `<iframe src="//maps.google.com/maps?t=m&q=${place}&output=embed"></iframe>`;
		}
	}]
};

const youtube = {
	provider_name: "youtube.com",
	endpoints: [{
		schemes: [
			'https://*.youtube.com/v/*',
			'https://*.youtube.com/embed/*',
			'https://youtu.be/*'
		],
		url: 'https://www.youtube.com/oembed', // TODO ?maxwidth=1024&maxheight=1024
		redirect: function(obj) {
			if (obj.pathname == "/watch") return;
			var videoId;
			if (obj.pathname.startsWith("/embed/")) {
				videoId = obj.pathname.split('/').pop();
			} else if (obj.hostname == "youtu.be") {
				videoId = obj.pathname.substring(1);
			}
			if (!videoId) return;
			delete obj.href;
			delete obj.pathname;
			delete obj.search;
			delete obj.query;
			obj.path = "/watch?v=" + encodeURIComponent(videoId);
			obj.hostname = "www.youtube.com";
			return true;
		}
	}]
};

const twitter = {
	provider_name: "twitter.com",
	endpoints: [{
		schemes: [
			'https://twitter.com/*/status/*'
		],
		redirect: function(obj) {
			return true;
		}
	}]
};

const instagram = {
	provider_name: "instagram.com",
	endpoints: [{
		schemes: [
			'https://www.instagram.com/*/*/'
		],
		redirect: function (obj) {
			obj.headers["User-Agent"] = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15";
			return true;
		}
	}]
};

module.exports = [googlemaps, youtube, twitter, instagram];

<|endoftext|>


<commit_before>"use strict";

const clc = require("cli-color");
const fs = require("fs");
const path = require("path");
const request = require("request");
const size = require("lodash/size");
const zlib = require("zlib");
const crypto = require("crypto");

const hashcache = require("./hashcache");
const detectProjectRoot = require("../../detectProjectRoot");
const api = require("../../api");
const logger = require("../../logger");
const Queue = require("../../queue");

function _progressMessage(message, current, total) {
  current = Math.min(current, total);
  return (
    message +
    " [" +
    current +
    "/" +
    total +
    "] (" +
    clc.bold.green(Math.floor(current * 1.0 / total * 100).toString() + "%") +
    ")"
  );
}

class Uploader {
  constructor(options) {
    this.version = options.version;
    this.cwd = options.cwd || process.cwd();

    this.projectRoot = detectProjectRoot(this.cwd);

    this.gzipLevel = options.gzipLevel || 9;
    this.hashQueue = new Queue({
      name: "hashQueue",
      concurrency: options.hashConcurrency || 50,
      handler: this.hashHandler.bind(this),
    });
    this.populateBatchSize = options.populateBatchSize || 1000;
    this.populateBatch = {};
    this.populateQueue = new Queue({
      name: "populateQueue",
      concurrency: options.populateConcurrency || 10,
      handler: this.populateHandler.bind(this),
      retries: 3,
    });
    this.uploadQueue = new Queue({
      name: "uploadQueue",
      concurrency: options.uploadConcurrency || 200,
      handler: this.uploadHandler.bind(this),
      retries: 5,
    });
    this.public = options.public || this.cwd;
    this.files = options.files;
    this.fileCount = this.files.length;

    this.cache = hashcache.load(this.projectRoot, this.hashcacheName());
    this.cacheNew = {};

    this.hashMap = {};
    this.pathMap = {};
  }

  hashcacheName() {
    return Buffer.from(path.relative(this.projectRoot, this.public))
      .toString("base64")
      .replace(/=+$/, "");
  }

  start() {
    const self = this;
    // short-circuit when there's zero files
    if (this.files.length === 0) {
      return Promise.resolve();
    }

    this.files.forEach(function(f) {
      self.hashQueue.add(f);
    });
    self.hashQueue.close();
    self.hashQueue.process();
    self.hashQueue
      .wait()
      .then(self.queuePopulate.bind(self))
      .then(function() {
        hashcache.dump(self.projectRoot, self.hashcacheName(), self.cacheNew);
        logger.debug("[hosting][hash queue][FINAL]", self.hashQueue.stats());
        self.populateQueue.close();
        return self.populateQueue.wait();
      })
      .then(function() {
        logger.debug("[hosting][populate queue][FINAL]", self.populateQueue.stats());
        logger.debug("[hosting] uploads queued:", self.uploadQueue.tasks.length);
        self.uploadQueue.close();
      });

    const fin = function(err) {
      logger.debug("[hosting][upload queue][FINAL]", self.uploadQueue.stats());
      if (err) throw err;
    };

    return this.wait()
      .then(fin)
      .catch(fin);
  }

  wait() {
    return Promise.all([
      this.hashQueue.wait(),
      this.populateQueue.wait(),
      this.uploadQueue.wait(),
    ]).then(function() {
      return; // don't return an array of three `undefined`
    });
  }

  statusMessage() {
    if (!this.hashQueue.finished) {
      return _progressMessage("hashing files", this.hashQueue.complete, this.fileCount);
    } else if (!this.populateQueue.finished) {
      return _progressMessage(
        "adding files to version",
        this.populateQueue.complete * 1000,
        this.fileCount
      );
    } else if (!this.uploadQueue.finished) {
      return _progressMessage(
        "uploading new files",
        this.uploadQueue.complete,
        this.uploadQueue.tasks.length
      );
    } else {
      return "upload complete";
    }
  }

  hashHandler(filePath) {
    const stats = fs.statSync(path.resolve(this.public, filePath));
    const mtime = stats.mtime.getTime();
    const cached = this.cache[filePath];
    if (cached && cached.mtime === mtime) {
      this.cacheNew[filePath] = cached;
      this.addHash(filePath, cached.hash);
      return Promise.resolve();
    }

    const fstream = this._zipStream(filePath);
    const hash = crypto.createHash("sha256");

    fstream.pipe(hash);

    const self = this;
    return new Promise(function(resolve, reject) {
      fstream.on("end", function() {
        const hashVal = hash.read().toString("hex");
        self.cacheNew[filePath] = { mtime: mtime, hash: hashVal };
        self.addHash(filePath, hashVal);
        resolve();
      });

      fstream.on("error", reject);
    });
  }

  addHash(filePath, hash) {
    this.hashMap[hash] = filePath;
    this.pathMap[filePath] = hash;

    this.populateBatch["/" + filePath] = hash;
    this.populateCount++;

    const curBatchSize = size(this.populateBatch);
    if (curBatchSize > 0 && curBatchSize % this.populateBatchSize === 0) {
      this.queuePopulate();
    }
  }

  queuePopulate() {
    const pop = this.populateBatch;
    this.populateQueue.add(pop, "batch" + (this.populateQueue.tasks.length + 1));
    this.populateBatch = {};
    this.populateQueue.process();
  }

  populateHandler(batch) {
    const self = this;
    // wait for any existing populate calls to finish before proceeding
    return api
      .request("POST", "/v1beta1/" + self.version + ":populateFiles", {
        origin: api.hostingApiOrigin,
        auth: true,
        data: { files: batch },
        logOptions: { skipRequestBody: true },
      })
      .then(function(result) {
        self.uploadUrl = result.body.uploadUrl;
        self.addUploads(result.body.uploadRequiredHashes || []);
      });
  }

  addUploads(hashes) {
    const self = this;
    hashes.forEach(function(hash) {
      self.uploadQueue.add(hash);
    });
    self.uploadQueue.process();
  }

  uploadHandler(toUpload) {
    const self = this;

    return api
      .addRequestHeaders({
        url: this.uploadUrl + "/" + toUpload,
      })
      .then(function(reqOpts) {
        return new Promise(function(resolve, reject) {
          self._zipStream(self.hashMap[toUpload]).pipe(
            request.post(reqOpts, function(err, res) {
              if (self.uploadQueue.cursor % 100 === 0) {
                logger.debug("[hosting][upload]", self.uploadQueue.stats());
              }
              if (err) {
                return reject(err);
              } else if (res.statusCode !== 200) {
                logger.debug(
                  "[hosting][upload]",
                  self.hashMap[toUpload],
                  "(" + toUpload + ")",
                  "HTTP ERROR",
                  res.statusCode,
                  ":",
                  res.headers,
                  res.body
                );
                return reject(new Error("Unexpected error while uploading file."));
              }

              resolve();
            })
          );
        });
      });
  }

  _zipStream(filePath) {
    const gzip = zlib.createGzip({ level: this.gzipLevel });
    return fs.createReadStream(path.resolve(this.public, filePath)).pipe(gzip);
  }
}

module.exports = Uploader;
<commit_msg>Adaptive timeouts for Hosting uploads. (#954)<commit_after>"use strict";

const clc = require("cli-color");
const fs = require("fs");
const path = require("path");
const request = require("request");
const size = require("lodash/size");
const zlib = require("zlib");
const crypto = require("crypto");

const hashcache = require("./hashcache");
const detectProjectRoot = require("../../detectProjectRoot");
const api = require("../../api");
const logger = require("../../logger");
const Queue = require("../../queue");

const MIN_UPLOAD_TIMEOUT = 30000; // 30s
const MAX_UPLOAD_TIMEOUT = 7200000; // 2h

function _progressMessage(message, current, total) {
  current = Math.min(current, total);
  return (
    message +
    " [" +
    current +
    "/" +
    total +
    "] (" +
    clc.bold.green(Math.floor(current * 1.0 / total * 100).toString() + "%") +
    ")"
  );
}

class Uploader {
  constructor(options) {
    this.version = options.version;
    this.cwd = options.cwd || process.cwd();

    this.projectRoot = detectProjectRoot(this.cwd);

    this.gzipLevel = options.gzipLevel || 9;
    this.hashQueue = new Queue({
      name: "hashQueue",
      concurrency: options.hashConcurrency || 50,
      handler: this.hashHandler.bind(this),
    });
    this.populateBatchSize = options.populateBatchSize || 1000;
    this.populateBatch = {};
    this.populateQueue = new Queue({
      name: "populateQueue",
      concurrency: options.populateConcurrency || 10,
      handler: this.populateHandler.bind(this),
      retries: 3,
    });
    this.uploadQueue = new Queue({
      name: "uploadQueue",
      concurrency: options.uploadConcurrency || 200,
      handler: this.uploadHandler.bind(this),
      retries: 5,
    });
    this.public = options.public || this.cwd;
    this.files = options.files;
    this.fileCount = this.files.length;

    this.cache = hashcache.load(this.projectRoot, this.hashcacheName());
    this.cacheNew = {};

    this.sizeMap = {};
    this.hashMap = {};
    this.pathMap = {};
  }

  hashcacheName() {
    return Buffer.from(path.relative(this.projectRoot, this.public))
      .toString("base64")
      .replace(/=+$/, "");
  }

  start() {
    const self = this;
    // short-circuit when there's zero files
    if (this.files.length === 0) {
      return Promise.resolve();
    }

    this.files.forEach(function(f) {
      self.hashQueue.add(f);
    });
    self.hashQueue.close();
    self.hashQueue.process();
    self.hashQueue
      .wait()
      .then(self.queuePopulate.bind(self))
      .then(function() {
        hashcache.dump(self.projectRoot, self.hashcacheName(), self.cacheNew);
        logger.debug("[hosting][hash queue][FINAL]", self.hashQueue.stats());
        self.populateQueue.close();
        return self.populateQueue.wait();
      })
      .then(function() {
        logger.debug("[hosting][populate queue][FINAL]", self.populateQueue.stats());
        logger.debug("[hosting] uploads queued:", self.uploadQueue.tasks.length);
        self.uploadQueue.close();
      });

    const fin = function(err) {
      logger.debug("[hosting][upload queue][FINAL]", self.uploadQueue.stats());
      if (err) throw err;
    };

    return this.wait()
      .then(fin)
      .catch(fin);
  }

  wait() {
    return Promise.all([
      this.hashQueue.wait(),
      this.populateQueue.wait(),
      this.uploadQueue.wait(),
    ]).then(function() {
      return; // don't return an array of three `undefined`
    });
  }

  statusMessage() {
    if (!this.hashQueue.finished) {
      return _progressMessage("hashing files", this.hashQueue.complete, this.fileCount);
    } else if (!this.populateQueue.finished) {
      return _progressMessage(
        "adding files to version",
        this.populateQueue.complete * 1000,
        this.fileCount
      );
    } else if (!this.uploadQueue.finished) {
      return _progressMessage(
        "uploading new files",
        this.uploadQueue.complete,
        this.uploadQueue.tasks.length
      );
    } else {
      return "upload complete";
    }
  }

  hashHandler(filePath) {
    const stats = fs.statSync(path.resolve(this.public, filePath));
    const mtime = stats.mtime.getTime();
    this.sizeMap[filePath] = stats.size;
    const cached = this.cache[filePath];
    if (cached && cached.mtime === mtime) {
      this.cacheNew[filePath] = cached;
      this.addHash(filePath, cached.hash);
      return Promise.resolve();
    }

    const fstream = this._zipStream(filePath);
    const hash = crypto.createHash("sha256");

    fstream.pipe(hash);

    const self = this;
    return new Promise(function(resolve, reject) {
      fstream.on("end", function() {
        const hashVal = hash.read().toString("hex");
        self.cacheNew[filePath] = { mtime: mtime, hash: hashVal };
        self.addHash(filePath, hashVal);
        resolve();
      });

      fstream.on("error", reject);
    });
  }

  addHash(filePath, hash) {
    this.hashMap[hash] = filePath;
    this.pathMap[filePath] = hash;

    this.populateBatch["/" + filePath] = hash;
    this.populateCount++;

    const curBatchSize = size(this.populateBatch);
    if (curBatchSize > 0 && curBatchSize % this.populateBatchSize === 0) {
      this.queuePopulate();
    }
  }

  queuePopulate() {
    const pop = this.populateBatch;
    this.populateQueue.add(pop, "batch" + (this.populateQueue.tasks.length + 1));
    this.populateBatch = {};
    this.populateQueue.process();
  }

  populateHandler(batch) {
    const self = this;
    // wait for any existing populate calls to finish before proceeding
    return api
      .request("POST", "/v1beta1/" + self.version + ":populateFiles", {
        origin: api.hostingApiOrigin,
        auth: true,
        data: { files: batch },
        logOptions: { skipRequestBody: true },
      })
      .then(function(result) {
        self.uploadUrl = result.body.uploadUrl;
        self.addUploads(result.body.uploadRequiredHashes || []);
      });
  }

  addUploads(hashes) {
    const self = this;
    hashes.forEach(function(hash) {
      self.uploadQueue.add(hash);
    });
    self.uploadQueue.process();
  }

  uploadHandler(toUpload) {
    const self = this;

    return api
      .addRequestHeaders({
        url: this.uploadUrl + "/" + toUpload,
      })
      .then(function(reqOpts) {
        return new Promise(function(resolve, reject) {
          self._zipStream(self.hashMap[toUpload]).pipe(
            request.post(
              Object.assign(reqOpts, {
                timeout: self._uploadTimeout(self.hashMap[toUpload]),
              }),
              function(err, res) {
                if (self.uploadQueue.cursor % 100 === 0) {
                  logger.debug("[hosting][upload]", self.uploadQueue.stats());
                }
                if (err) {
                  return reject(err);
                } else if (res.statusCode !== 200) {
                  logger.debug(
                    "[hosting][upload]",
                    self.hashMap[toUpload],
                    "(" + toUpload + ")",
                    "HTTP ERROR",
                    res.statusCode,
                    ":",
                    res.headers,
                    res.body
                  );
                  return reject(new Error("Unexpected error while uploading file."));
                }

                resolve();
              }
            )
          );
        });
      });
  }

  _zipStream(filePath) {
    const gzip = zlib.createGzip({ level: this.gzipLevel });
    return fs.createReadStream(path.resolve(this.public, filePath)).pipe(gzip);
  }

  _uploadTimeout(filePath) {
    const size = this.sizeMap[filePath] || 0;
    // 20s per MB bounded to min/max timeouts
    return Math.min(Math.max(Math.round(size / 1000) * 20, MIN_UPLOAD_TIMEOUT), MAX_UPLOAD_TIMEOUT);
  }
}

module.exports = Uploader;
<|endoftext|>


<commit_before>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

var React = require('react-native');
var MOCKED_MOVIES_DATA = [
  {title: 'Title', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}},
];
var {
  AppRegistry,
  Image,
  StyleSheet,
  Text,
  View,
} = React;

var Movies = React.createClass({
   render: function() {
    var movie = MOCKED_MOVIES_DATA[0];
    return (
      <View style={styles.container}>
        <Text>{movie.title}</Text>
        <Text>{movie.year}</Text>
        <Image source={{uri: movie.posters.thumbnail}} />
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
  },
});

AppRegistry.registerComponent('Movies', () => Movies);
<commit_msg>Adding styles to the image<commit_after>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

var React = require('react-native');
var MOCKED_MOVIES_DATA = [
  {title: 'Title', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}},
];
var {
  AppRegistry,
  Image,
  StyleSheet,
  Text,
  View,
} = React;

var Movies = React.createClass({
   render: function() {
    var movie = MOCKED_MOVIES_DATA[0];
    return (
      <View style={styles.container}>
        <Text>{movie.title}</Text>
        <Text>{movie.year}</Text>
        <Image style={styles.thumbnail} source={{uri: movie.posters.thumbnail}} />
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  thumbnail:{
    width: 53,
    height: 81
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
  },
});

AppRegistry.registerComponent('Movies', () => Movies);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Pavol Rusnak
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * Javascript port from python by Ian Coleman
 *
 * Requires code from sjcl
 * https://github.com/bitwiseshiftleft/sjcl
 */

var Mnemonic = function(language) {

    var PBKDF2_ROUNDS = 2048;
    var RADIX = 2048;

    var self = this;
    var wordlist = [];

    var hmacSHA512 = function(key) {
        var hasher = new sjcl.misc.hmac(key, sjcl.hash.sha512);
        this.encrypt = function() {
            return hasher.encrypt.apply(hasher, arguments);
        };
    };

    function init() {
        wordlist = WORDLISTS[language];
        if (wordlist.length != RADIX) {
            err = 'Wordlist should contain ' + RADIX + ' words, but it contains ' + wordlist.length + ' words.';
            throw err;
        }
    }

    self.generate = function(strength) {
        strength = strength || 128;
        var r = strength % 32;
        if (r > 0) {
            throw 'Strength should be divisible by 32, but it is not (' + r + ').';
        }
        var hasStrongCrypto = 'crypto' in window && window['crypto'] !== null;
        if (!hasStrongCrypto) {
            throw 'Mnemonic should be generated with strong randomness, but crypto.getRandomValues is unavailable';
        }
        var buffer = new Uint8Array(strength / 8);
        var data = crypto.getRandomValues(buffer);
        return self.toMnemonic(data);
    }

    self.toMnemonic = function(byteArray) {
        if (byteArray.length % 4 > 0) {
            throw 'Data length in bits should be divisible by 32, but it is not (' + byteArray.length + ' bytes = ' + byteArray.length*8 + ' bits).'
        }

        //h = hashlib.sha256(data).hexdigest()
        var data = byteArrayToWordArray(byteArray);
        var hash = sjcl.hash.sha256.hash(data);
        var h = sjcl.codec.hex.fromBits(hash);

        // b is a binary string, eg '00111010101100...'
        //b = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) + \
        //    bin(int(h, 16))[2:].zfill(256)[:len(data) * 8 / 32]
        //
        // a = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8)
        // c = bin(int(h, 16))[2:].zfill(256)
        // d = c[:len(data) * 8 / 32]
        var a = byteArrayToBinaryString(byteArray);
        var c = zfill(hexStringToBinaryString(h), 256);
        var d = c.substring(0, byteArray.length * 8 / 32);
        // b = line1 + line2
        var b = a + d;

        var result = [];
        var blen = b.length / 11;
        for (var i=0; i<blen; i++) {
            var idx = parseInt(b.substring(i * 11, (i + 1) * 11), 2);
            result.push(wordlist[idx]);
        }
        return self.joinWords(result);
    }

    self.check = function(mnemonic) {
        var mnemonic = self.splitWords(mnemonic);
        if (mnemonic.length % 3 > 0) {
            return false
        }
        // idx = map(lambda x: bin(self.wordlist.index(x))[2:].zfill(11), mnemonic)
        var idx = [];
        for (var i=0; i<mnemonic.length; i++) {
            var word = mnemonic[i];
            var wordIndex = wordlist.indexOf(word);
            if (wordIndex == -1) {
                return false;
            }
            var binaryIndex = zfill(wordIndex.toString(2), 11);
            idx.push(binaryIndex);
        }
        var b = idx.join('');
        var l = b.length;
        //d = b[:l / 33 * 32]
        //h = b[-l / 33:]
        var d = b.substring(0, l / 33 * 32);
        var h = b.substring(l - l / 33, l);
        //nd = binascii.unhexlify(hex(int(d, 2))[2:].rstrip('L').zfill(l / 33 * 8))
        var nd = binaryStringToWordArray(d);
        //nh = bin(int(hashlib.sha256(nd).hexdigest(), 16))[2:].zfill(256)[:l / 33]
        var ndHash = sjcl.hash.sha256.hash(nd);
        var ndHex = sjcl.codec.hex.fromBits(ndHash);
        var ndBstr = zfill(hexStringToBinaryString(ndHex), 256);
        var nh = ndBstr.substring(0,l/33);
        return h == nh;
    }

    self.toSeed = function(mnemonic, passphrase) {
        passphrase = passphrase || '';
        mnemonic = self.joinWords(self.splitWords(self.normalizeString(mnemonic))); // removes blanks
        passphrase = self.normalizeString(passphrase)
        passphrase = "mnemonic" + passphrase;
        var mnemonicBits = sjcl.codec.utf8String.toBits(mnemonic);
        var passphraseBits = sjcl.codec.utf8String.toBits(passphrase);
        var result = sjcl.misc.pbkdf2(mnemonicBits, passphraseBits, PBKDF2_ROUNDS, 512, hmacSHA512);
        var hashHex = sjcl.codec.hex.fromBits(result);
        return hashHex;
    }

    self.splitWords = function(mnemonic) {
        return mnemonic.split(/\s/g).filter(function(x) { return x.length; });
    }

    self.joinWords = function(words) {
        // Set space correctly depending on the language
        // see https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md#japanese
        var space = " ";
        if (language == "japanese") {
            space = "\u3000"; // ideographic space
        }
        return words.join(space);
    }

    self.normalizeString = function(str) {
        if (typeof str.normalize == "function") {
            return str.normalize("NFKD");
        }
        else {
            // TODO decide how to handle this in the future.
            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
            return str;
        }
    }

    function byteArrayToWordArray(data) {
        var a = [];
        for (var i=0; i<data.length/4; i++) {
            v = 0;
            v += data[i*4 + 0] << 8 * 3;
            v += data[i*4 + 1] << 8 * 2;
            v += data[i*4 + 2] << 8 * 1;
            v += data[i*4 + 3] << 8 * 0;
            a.push(v);
        }
        return a;
    }

    function byteArrayToBinaryString(data) {
        var bin = "";
        for (var i=0; i<data.length; i++) {
            bin += zfill(data[i].toString(2), 8);
        }
        return bin;
    }

    function hexStringToBinaryString(hexString) {
        binaryString = "";
        for (var i=0; i<hexString.length; i++) {
            binaryString += zfill(parseInt(hexString[i], 16).toString(2),4);
        }
        return binaryString;
    }

    function binaryStringToWordArray(binary) {
        var aLen = binary.length / 32;
        var a = [];
        for (var i=0; i<aLen; i++) {
            var valueStr = binary.substring(0,32);
            var value = parseInt(valueStr, 2);
            a.push(value);
            binary = binary.slice(32);
        }
        return a;
    }

    // Pad a numeric string on the left with zero digits until the given width
    // is reached.
    // Note this differs to the python implementation because it does not
    // handle numbers starting with a sign.
    function zfill(source, length) {
        source = source.toString();
        while (source.length < length) {
            source = '0' + source;
        }
        return source;
    }

    init();

}
<commit_msg>jsbip39 updated to latest version<commit_after>/*
 * Copyright (c) 2013 Pavol Rusnak
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * Javascript port from python by Ian Coleman
 *
 * Requires code from sjcl
 * https://github.com/bitwiseshiftleft/sjcl
 */

var Mnemonic = function(language) {

    var PBKDF2_ROUNDS = 2048;
    var RADIX = 2048;

    var self = this;
    var wordlist = [];

    var hmacSHA512 = function(key) {
        var hasher = new sjcl.misc.hmac(key, sjcl.hash.sha512);
        this.encrypt = function() {
            return hasher.encrypt.apply(hasher, arguments);
        };
    };

    function init() {
        wordlist = WORDLISTS[language];
        if (wordlist.length != RADIX) {
            err = 'Wordlist should contain ' + RADIX + ' words, but it contains ' + wordlist.length + ' words.';
            throw err;
        }
    }

    self.generate = function(strength) {
        strength = strength || 128;
        var r = strength % 32;
        if (r > 0) {
            throw 'Strength should be divisible by 32, but it is not (' + r + ').';
        }
        var hasStrongCrypto = 'crypto' in window && window['crypto'] !== null;
        if (!hasStrongCrypto) {
            throw 'Mnemonic should be generated with strong randomness, but crypto.getRandomValues is unavailable';
        }
        var buffer = new Uint8Array(strength / 8);
        var data = crypto.getRandomValues(buffer);
        return self.toMnemonic(data);
    }

    self.toMnemonic = function(byteArray) {
        if (byteArray.length % 4 > 0) {
            throw 'Data length in bits should be divisible by 32, but it is not (' + byteArray.length + ' bytes = ' + byteArray.length*8 + ' bits).'
        }

        //h = hashlib.sha256(data).hexdigest()
        var data = byteArrayToWordArray(byteArray);
        var hash = sjcl.hash.sha256.hash(data);
        var h = sjcl.codec.hex.fromBits(hash);

        // b is a binary string, eg '00111010101100...'
        //b = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) + \
        //    bin(int(h, 16))[2:].zfill(256)[:len(data) * 8 / 32]
        //
        // a = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8)
        // c = bin(int(h, 16))[2:].zfill(256)
        // d = c[:len(data) * 8 / 32]
        var a = byteArrayToBinaryString(byteArray);
        var c = zfill(hexStringToBinaryString(h), 256);
        var d = c.substring(0, byteArray.length * 8 / 32);
        // b = line1 + line2
        var b = a + d;

        var result = [];
        var blen = b.length / 11;
        for (var i=0; i<blen; i++) {
            var idx = parseInt(b.substring(i * 11, (i + 1) * 11), 2);
            result.push(wordlist[idx]);
        }
        return self.joinWords(result);
    }

    self.check = function(mnemonic) {
        var mnemonic = self.splitWords(mnemonic);
        if (mnemonic.length == 0 || mnemonic.length % 3 > 0) {
            return false
        }
        // idx = map(lambda x: bin(self.wordlist.index(x))[2:].zfill(11), mnemonic)
        var idx = [];
        for (var i=0; i<mnemonic.length; i++) {
            var word = mnemonic[i];
            var wordIndex = wordlist.indexOf(word);
            if (wordIndex == -1) {
                return false;
            }
            var binaryIndex = zfill(wordIndex.toString(2), 11);
            idx.push(binaryIndex);
        }
        var b = idx.join('');
        var l = b.length;
        //d = b[:l / 33 * 32]
        //h = b[-l / 33:]
        var d = b.substring(0, l / 33 * 32);
        var h = b.substring(l - l / 33, l);
        //nd = binascii.unhexlify(hex(int(d, 2))[2:].rstrip('L').zfill(l / 33 * 8))
        var nd = binaryStringToWordArray(d);
        //nh = bin(int(hashlib.sha256(nd).hexdigest(), 16))[2:].zfill(256)[:l / 33]
        var ndHash = sjcl.hash.sha256.hash(nd);
        var ndHex = sjcl.codec.hex.fromBits(ndHash);
        var ndBstr = zfill(hexStringToBinaryString(ndHex), 256);
        var nh = ndBstr.substring(0,l/33);
        return h == nh;
    }

    self.toSeed = function(mnemonic, passphrase) {
        passphrase = passphrase || '';
        mnemonic = self.joinWords(self.splitWords(self.normalizeString(mnemonic))); // removes blanks
        passphrase = self.normalizeString(passphrase)
        passphrase = "mnemonic" + passphrase;
        var mnemonicBits = sjcl.codec.utf8String.toBits(mnemonic);
        var passphraseBits = sjcl.codec.utf8String.toBits(passphrase);
        var result = sjcl.misc.pbkdf2(mnemonicBits, passphraseBits, PBKDF2_ROUNDS, 512, hmacSHA512);
        var hashHex = sjcl.codec.hex.fromBits(result);
        return hashHex;
    }

    self.splitWords = function(mnemonic) {
        return mnemonic.split(/\s/g).filter(function(x) { return x.length; });
    }

    self.joinWords = function(words) {
        // Set space correctly depending on the language
        // see https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md#japanese
        var space = " ";
        if (language == "japanese") {
            space = "\u3000"; // ideographic space
        }
        return words.join(space);
    }

    self.normalizeString = function(str) {
        if (typeof str.normalize == "function") {
            return str.normalize("NFKD");
        }
        else {
            // TODO decide how to handle this in the future.
            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
            return str;
        }
    }

    function byteArrayToWordArray(data) {
        var a = [];
        for (var i=0; i<data.length/4; i++) {
            v = 0;
            v += data[i*4 + 0] << 8 * 3;
            v += data[i*4 + 1] << 8 * 2;
            v += data[i*4 + 2] << 8 * 1;
            v += data[i*4 + 3] << 8 * 0;
            a.push(v);
        }
        return a;
    }

    function byteArrayToBinaryString(data) {
        var bin = "";
        for (var i=0; i<data.length; i++) {
            bin += zfill(data[i].toString(2), 8);
        }
        return bin;
    }

    function hexStringToBinaryString(hexString) {
        binaryString = "";
        for (var i=0; i<hexString.length; i++) {
            binaryString += zfill(parseInt(hexString[i], 16).toString(2),4);
        }
        return binaryString;
    }

    function binaryStringToWordArray(binary) {
        var aLen = binary.length / 32;
        var a = [];
        for (var i=0; i<aLen; i++) {
            var valueStr = binary.substring(0,32);
            var value = parseInt(valueStr, 2);
            a.push(value);
            binary = binary.slice(32);
        }
        return a;
    }

    // Pad a numeric string on the left with zero digits until the given width
    // is reached.
    // Note this differs to the python implementation because it does not
    // handle numbers starting with a sign.
    function zfill(source, length) {
        source = source.toString();
        while (source.length < length) {
            source = '0' + source;
        }
        return source;
    }

    init();

}
<|endoftext|>