<commit_before>/*

TODO test proxy for memory leaks

*/
require('./api');
var M = process.mono;
var net = require('net');
var startApp = require('./spawner').start;

function pipe (app, socket, buffer) {

    // the host of an application is the ip address where the application runs
    var projectSocket = net.connect(app.port, app.host);
    projectSocket.setKeepAlive(true);
    projectSocket.on('error', function (err) {

        M.cache.rm(app.host);
        send(socket, 500, M.error.APP_SOCKET_RELOAD_MESSAGE);
    });

    // down stream
    projectSocket.pipe(socket);
    // up stream
    socket.pipe(projectSocket);

    projectSocket.write(buffer);

    socket.resume();
}

// handle socket
function server (socket) {

    // set up piping on first data event
    socket.once('data', function (buffer) {

        socket.pause();

        // Info: read more from buffer, if there are a lot of 414 errors
        var host = buffer.toString('ascii', 0, 1000);

        // is the URL to long?
        if (host.indexOf('\n') > 2048) {
            return send(socket, 414, 'Request-URL Too Long.');
        }

        // get host
        if (!(host = host.match(/host\: *([a-z0-9\-_\.]+)(:[0-9]{2,5})?/i))) {
            return send(socket, 400, 'No Host found in headers.');
        }
        host = host[1];

        // get application from cache
        var app = M.cache.get(host);
        if (app === null) {
            return send(socket, 503, 'Application is starting...');
        }

        // proxy request
        if (app) {
            return pipe(app, socket, buffer);
        }

        // mark application as "starting"
        M.cache.save(host, null);

        // start app
        startApp(host, function (err, application) {

            // handle error
            if (err) {

                // remove app from cache
                M.cache.rm(host);

                // end socket connection
                if (err === 503) {
                    return send(socket, 503, '503 Application ' + application + ' unavailable');
                }

                // set appropriate status code
                var statusCode = 500;
                if (err.code === M.error.APP_NOT_FOUND) {
                    statusCode = 404;
                }

                // send error
                return send(socket, statusCode, err.message);
            }

            // save app in cache
            M.cache.save(host, application);

            // pipe socket to application
            pipe(application, socket, buffer);
        });
    });

    // handle socket errors
    socket.on('error', function (err) {
        console.log(err.message);
    });
}

function send (socket, status, msg) {

    socket.resume();
    socket.end(
        'HTTP/1.1 ' + status + '\r\n' +
        'Date: ' + new Date().toString() + '\r\n' +
        'Server: Mono Web Server\r\n' +
        'Content-Length: ' + msg.length + '\r\n' +
        'Connection: close\r\n' +
        'Content-Type: text/plain; charset=utf-8\r\n' +
        '\r\n' + msg
    );
}

function killApps (err) {

    var apps = M.cache.getAll();
    for (var host in apps) {

        if (apps[host] && apps[host].pid) {
            process.kill(apps[host].pid);
        }
    }

    if (err) {
        console.error(err.message);
        console.error(err.stack);
        return process.exit(1);
    }

    process.exit();
}

// on user term/int or exception, kill all application processes and exit
process.on('SIGTERM', killApps);
process.on('SIGINT', killApps);
process.on('uncaughtException', killApps);

// handle api errors
M.on('error', function (err) {
    throw new Error(err);
});

// start proxy server
M.on('ready', function () {
    net.createServer(server).listen(M.config.port, M.config.host);
});
<commit_msg>prevent proxy crash when send message is undefined<commit_after>/*

TODO test proxy for memory leaks

*/
require('./api');
var M = process.mono;
var net = require('net');
var startApp = require('./spawner').start;

function pipe (app, socket, buffer) {

    // the host of an application is the ip address where the application runs
    var projectSocket = net.connect(app.port, app.host);
    projectSocket.setKeepAlive(true);
    projectSocket.on('error', function (err) {

        M.cache.rm(app.host);
        send(socket, 500, M.error.APP_SOCKET_RELOAD_MESSAGE);
    });

    // down stream
    projectSocket.pipe(socket);
    // up stream
    socket.pipe(projectSocket);

    projectSocket.write(buffer);

    socket.resume();
}

// handle socket
function server (socket) {

    // set up piping on first data event
    socket.once('data', function (buffer) {

        socket.pause();

        // Info: read more from buffer, if there are a lot of 414 errors
        var host = buffer.toString('ascii', 0, 1000);

        // is the URL to long?
        if (host.indexOf('\n') > 2048) {
            return send(socket, 414, 'Request-URL Too Long.');
        }

        // get host
        if (!(host = host.match(/host\: *([a-z0-9\-_\.]+)(:[0-9]{2,5})?/i))) {
            return send(socket, 400, 'No Host found in headers.');
        }
        host = host[1];

        // get application from cache
        var app = M.cache.get(host);
        if (app === null) {
            return send(socket, 503, 'Application is starting...');
        }

        // proxy request
        if (app) {
            return pipe(app, socket, buffer);
        }

        // mark application as "starting"
        M.cache.save(host, null);

        // start app
        startApp(host, function (err, application) {

            // handle error
            if (err) {

                // remove app from cache
                M.cache.rm(host);

                // end socket connection
                if (err === 503) {
                    return send(socket, 503, '503 Application ' + application + ' unavailable');
                }

                // set appropriate status code
                var statusCode = 500;
                if (err.code === M.error.APP_NOT_FOUND) {
                    statusCode = 404;
                }

                // send error
                return send(socket, statusCode, err.toString());
            }

            // save app in cache
            M.cache.save(host, application);

            // pipe socket to application
            pipe(application, socket, buffer);
        });
    });

    // handle socket errors
    socket.on('error', function (err) {
        console.log(err.message);
    });
}

function send (socket, status, msg) {

    socket.resume();
    socket.end(
        'HTTP/1.1 ' + status + '\r\n' +
        'Date: ' + new Date().toString() + '\r\n' +
        'Server: Mono Web Server\r\n' +
        'Content-Length: ' + (msg ? msg.length : '0') + '\r\n' +
        'Connection: close\r\n' +
        'Content-Type: text/plain; charset=utf-8\r\n' +
        '\r\n' + msg
    );
}

function killApps (err) {

    var apps = M.cache.getAll();
    for (var host in apps) {

        if (apps[host] && apps[host].pid) {
            process.kill(apps[host].pid);
        }
    }

    if (err) {
        console.error(err.message);
        console.error(err.stack);
        return process.exit(1);
    }

    process.exit();
}

// on user term/int or exception, kill all application processes and exit
process.on('SIGTERM', killApps);
process.on('SIGINT', killApps);
process.on('uncaughtException', killApps);

// handle api errors
M.on('error', function (err) {
    throw new Error(err);
});

// start proxy server
M.on('ready', function () {
    net.createServer(server).listen(M.config.port, M.config.host);
});
<|endoftext|>


<commit_before>const Boom = require( 'boom' ),
    Log = require( '../methods/log.js' ),
    DB = require( '../../models.js' );

const ObjectID = DB.ObjectID,
    UserGroups = DB.UserGroups;

module.exports = function checkRole( request, reply ) {

    let auth = request.route.settings.plugins.poetryAuth;

    process.nextTick( () => {

        // Avoid unknown property issue
        request.session.role = {};

        // No auth check needed
        if ( !auth )
            return reply.continue();

        // Not logged on
        if ( !request.session.isAuthenticated || !request.session.user )
            return reply( Boom.unauthorized() );

        // SUPER case
        if ( request.session.user.role == 'SUPER' )
            return reply.continue();

        // ADMIN case
        if ( request.session.user.role == '*' )
            return roles( {
                name: "ADMIN",
                permissions: request.session.team.permissions
            } );

        // USER case
        let id;
        try {
            id = ObjectID( request.session.user.role );
        } catch ( err ) {
            Log.error( 'Wrong role for ', JSON.stringify( request.session.user ) );
            return reply( Boom.forbidden() );
        }
        UserGroups.findOne( {
                _id: id,
                team: request.session.team._id
            } )
            .then( roles, roles );

    } );

    function roles( role ) {

        if ( !role ) {
            Log.warn( 'Unknown role !', request.route.method, request.route.path );
            return reply( Boom.forbidden() );
        }

        request.session.role = role;

        // Special handwritten auths
        if ( Array.isArray( auth ) ) {
            if ( auth.some( tag => check(
                    `API.${tag}.${ request.route.settings.description }`,
                    role
                ) ) ) return Log.silly( 'Custom role found' );
        }

        if ( request.route.settings.tags ) {

            // For descripted routes
            if ( request.route.settings.description ) {

                // Check for each tag
                if ( request.route.settings.tags.some( tag => check(
                        `API.${tag}.${ request.route.settings.description }`,
                        role.permissions
                    ) ) ) return Log.silly( 'Precise role found' );

            }

            // For tagged routes
            if ( request.route.settings.tags.some( tag => check(
                    `API.${tag}`,
                    role.permissions
                ) ) ) return Log.silly( 'Tagged role found' );

        }

        // FORBIDDEN
        Log.silly( 'No permission found', request.route.method, request.route.path );
        return reply( Boom.forbidden( 'No permission found' ) );

    }

    // Get nested value with dot notation
    function check( path, object ) {

        // Separate string
        path = path.split( '.' );

        // Catch undefined
        if ( !object ) return false;
        if ( !object[ path[ 0 ] ] ) return false;

        // It's the targeted value
        if ( path.length == 1 ) {

            // If it's true, continue
            if ( object[ path[ 0 ] ] === true )
                reply.continue();

            // If it's false, block user
            else if ( object[ path[ 0 ] ] === false )
                reply( Boom.forbidden() );

            // If it's a boolean value, stop seeking.
            if ( object[ path[ 0 ] ] === true || object[ path[ 0 ] ] === false )
                return true;

            // Continues deeper
            return false;

        }

        // Deep inspect sub object
        return check( path.slice( 1 )
            .join( '.' ), object[ path[ 0 ] ] );

    }

};
<commit_msg>dbg role users me<commit_after>const Boom = require( 'boom' ),
    Log = require( '../methods/log.js' ),
    DB = require( '../../models.js' );

const ObjectID = DB.ObjectID,
    UserGroups = DB.UserGroups;

module.exports = function checkRole( request, reply ) {

    let auth = request.route.settings.plugins.poetryAuth;

    process.nextTick( () => {

        // Avoid unknown property issue
        request.session.role = {};

        // No auth check needed
        if ( !auth )
            return reply.continue();

        // Not logged on
        if ( !request.session.isAuthenticated || !request.session.user )
            return reply( Boom.unauthorized() );

        // SUPER case
        if ( request.session.user.role == 'SUPER' )
            return reply.continue();

        // ADMIN case
        if ( request.session.user.role == '*' )
            return roles( {
                name: "ADMIN",
                permissions: request.session.team.permissions
            } );

        // USER case
        let id;
        try {
            id = ObjectID( request.session.user.role );
        } catch ( err ) {
            Log.error( 'Wrong role for ', JSON.stringify( request.session.user ) );
            return reply( Boom.forbidden() );
        }
        UserGroups.findOne( {
                _id: id,
                team: request.session.team._id
            } )
            .then( roles, roles );

    } );

    function roles( role ) {

        if ( !role ) {
            Log.warn( 'Unknown role !', request.route.method, request.route.path );
            return reply( Boom.forbidden() );
        }

        request.session.role = role;

        // Special handwritten auths
        if ( Array.isArray( auth ) ) {
            if ( auth.some( tag => check(
                    `API.${tag}.${ request.route.settings.description }`,
                    role
                ) ) ) return Log.silly( 'Custom role found' );
        }

        if ( request.route.settings.tags ) {

            // For descripted routes
            if ( request.route.settings.description ) {

                // Check for each tag
                if ( request.route.settings.tags.some( tag => check(
                        `API.${tag}.${ request.route.settings.description }`,
                        role.permissions
                    ) ) ) return Log.silly( 'Precise role found' );

            }

            // For tagged routes
            if ( request.route.settings.tags.some( tag => check(
                    `API.${tag}`,
                    role.permissions
                ) ) ) return Log.silly( 'Tagged role found' );

        }

        // FORBIDDEN
        Log.silly( 'No permission found', request.route.method, request.route.path );
        return reply( Boom.forbidden( 'No permission found' ) );

    }

    // Get nested value with dot notation
    function check( path, object ) {

        // Always allow /users/me
        if ( ~[
                'API.Users.Me',
                'API.Users.Edit Me',
                'API.Users.Change password'
            ].indexOf( path ) ) return true;

        // Separate string
        path = path.split( '.' );

        // Catch undefined
        if ( !object ) return false;
        if ( !object[ path[ 0 ] ] ) return false;

        // It's the targeted value
        if ( path.length == 1 ) {

            // If it's true, continue
            if ( object[ path[ 0 ] ] === true )
                reply.continue();

            // If it's false, block user
            else if ( object[ path[ 0 ] ] === false )
                reply( Boom.forbidden() );

            // If it's a boolean value, stop seeking.
            if ( object[ path[ 0 ] ] === true || object[ path[ 0 ] ] === false )
                return true;

            // Continues deeper
            return false;

        }

        // Deep inspect sub object
        return check( path.slice( 1 )
            .join( '.' ), object[ path[ 0 ] ] );

    }

};
<|endoftext|>


<commit_before>'use strict'

const tap = require('tap')
const handlers = require('../../handlers')

tap.equal(Object.keys(handlers).length, 7, 'There are 7 standard handlers')

tap.ok(handlers.getFrontpage, 'Handler has method getFrontpage')

tap.ok(handlers.getLogspage, 'Handler has method getLogspage')

tap.ok(handlers.showLogin, 'Handler has method showLogin')

tap.ok(handlers.doLogin, 'Handler has method doLogin')

tap.ok(handlers.doLogout, 'Handler has method doLogout')
<commit_msg>Update handlers-test.js<commit_after>'use strict'

const tap = require('tap')
const handlers = require('../../handlers')

tap.equal(Object.keys(handlers).length, 8, 'There are 8 standard handlers')

tap.ok(handlers.getFrontpage, 'Handler has method getFrontpage')

tap.ok(handlers.getLogspage, 'Handler has method getLogspage')

tap.ok(handlers.showLogin, 'Handler has method showLogin')

tap.ok(handlers.doLogin, 'Handler has method doLogin')

tap.ok(handlers.doLogout, 'Handler has method doLogout')
<|endoftext|>


<commit_before>'use strict'

exports.shader   = getShaderReference
exports.program  = createProgram

var weakMap = typeof WeakMap === 'undefined' ? require('weakmap-shim') : WeakMap
var CACHE = new weakMap()

var SHADER_COUNTER = 0

function ShaderReference(id, src, type, shader, programs, count, cache) {
  this.id       = id
  this.src      = src
  this.type     = type
  this.shader   = shader
  this.count    = count
  this.programs = []
  this.cache    = cache
}

ShaderReference.prototype.dispose = function() {
  if(--this.count === 0) {
    var cache    = this.cache
    var gl       = cache.gl

    //Remove program references
    var programs = this.programs
    for(var i=0, n=programs.length; i<n; ++i) {
      var p = cache.programs[programs[i]]
      if(p) {
        delete cache.programs[i]
        gl.deleteProgram(p)
      }
    }

    //Remove shader reference
    gl.deleteShader(this.shader)
    delete cache.shaders[(this.type === gl.FRAGMENT_SHADER)|0][this.src]
  }
}

function ContextCache(gl) {
  this.gl       = gl
  this.shaders  = [{}, {}]
  this.programs = {}
}

var proto = ContextCache.prototype

function compileShader(gl, type, src) {
  var shader = gl.createShader(type)
  gl.shaderSource(shader, src)
  gl.compileShader(shader)
  if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    var errLog = gl.getShaderInfoLog(shader)
    console.error('gl-shader: Error compiling shader:', errLog)
    throw new Error('gl-shader: Error compiling shader:' + errLog)
  }
  return shader
}

proto.getShaderReference = function(type, src) {
  var gl      = this.gl
  var shaders = this.shaders[(type === gl.FRAGMENT_SHADER)|0]
  var shader  = shaders[src]
  if(!shader) {
    var shaderObj = compileShader(gl, type, src)
    shader = shaders[src] = new ShaderReference(
      SHADER_COUNTER++,
      src,
      type,
      shaderObj,
      [],
      1,
      this)
  } else {
    shader.count += 1
  }
  return shader
}

function linkProgram(gl, vshader, fshader, attribs, locations) {
  var program = gl.createProgram()
  gl.attachShader(program, vshader)
  gl.attachShader(program, fshader)
  for(var i=0; i<attribs.length; ++i) {
    gl.bindAttribLocation(program, locations[i], attribs[i])
  }
  gl.linkProgram(program)
  if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    var errLog = gl.getProgramInfoLog(program)
    console.error('gl-shader: Error linking program:', errLog)
    throw new Error('gl-shader: Error linking program:' + errLog)
  }
  return program
}

proto.getProgram = function(vref, fref, attribs, locations) {
  var token = [vref.id, fref.id, attribs.join(':'), locations.join(':')].join('@')
  var prog  = this.programs[token]
  if(!prog) {
    this.programs[token] = prog = linkProgram(
      this.gl,
      vref.shader,
      fref.shader,
      attribs,
      locations)
    vref.programs.push(token)
    fref.programs.push(token)
  }
  return prog
}

function getCache(gl) {
  var ctxCache = CACHE.get(gl)
  if(!ctxCache) {
    ctxCache = new ContextCache(gl)
    CACHE.set(gl, ctxCache)
  }
  return ctxCache
}

function getShaderReference(gl, type, src) {
  return getCache(gl).getShaderReference(type, src)
}

function createProgram(gl, vref, fref, attribs, locations) {
  return getCache(gl).getProgram(vref, fref, attribs, locations)
}<commit_msg>invalidate shaders across context loss<commit_after>'use strict'

exports.shader   = getShaderReference
exports.program  = createProgram

var weakMap = typeof WeakMap === 'undefined' ? require('weakmap-shim') : WeakMap
var CACHE = new weakMap()

var SHADER_COUNTER = 0

function ShaderReference(id, src, type, shader, programs, count, cache) {
  this.id       = id
  this.src      = src
  this.type     = type
  this.shader   = shader
  this.count    = count
  this.programs = []
  this.cache    = cache
}

ShaderReference.prototype.dispose = function() {
  if(--this.count === 0) {
    var cache    = this.cache
    var gl       = cache.gl

    //Remove program references
    var programs = this.programs
    for(var i=0, n=programs.length; i<n; ++i) {
      var p = cache.programs[programs[i]]
      if(p) {
        delete cache.programs[i]
        gl.deleteProgram(p)
      }
    }

    //Remove shader reference
    gl.deleteShader(this.shader)
    delete cache.shaders[(this.type === gl.FRAGMENT_SHADER)|0][this.src]
  }
}

function ContextCache(gl) {
  this.gl       = gl
  this.shaders  = [{}, {}]
  this.programs = {}
}

var proto = ContextCache.prototype

function compileShader(gl, type, src) {
  var shader = gl.createShader(type)
  gl.shaderSource(shader, src)
  gl.compileShader(shader)
  if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    var errLog = gl.getShaderInfoLog(shader)
    console.error('gl-shader: Error compiling shader:', errLog)
    throw new Error('gl-shader: Error compiling shader:' + errLog)
  }
  return shader
}

proto.getShaderReference = function(type, src) {
  var gl      = this.gl
  var shaders = this.shaders[(type === gl.FRAGMENT_SHADER)|0]
  var shader  = shaders[src]
  if(!shader || !gl.isShader(shader)) {
    var shaderObj = compileShader(gl, type, src)
    shader = shaders[src] = new ShaderReference(
      SHADER_COUNTER++,
      src,
      type,
      shaderObj,
      [],
      1,
      this)
  } else {
    shader.count += 1
  }
  return shader
}

function linkProgram(gl, vshader, fshader, attribs, locations) {
  var program = gl.createProgram()
  gl.attachShader(program, vshader)
  gl.attachShader(program, fshader)
  for(var i=0; i<attribs.length; ++i) {
    gl.bindAttribLocation(program, locations[i], attribs[i])
  }
  gl.linkProgram(program)
  if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    var errLog = gl.getProgramInfoLog(program)
    console.error('gl-shader: Error linking program:', errLog)
    throw new Error('gl-shader: Error linking program:' + errLog)
  }
  return program
}

proto.getProgram = function(vref, fref, attribs, locations) {
  var token = [vref.id, fref.id, attribs.join(':'), locations.join(':')].join('@')
  var prog  = this.programs[token]
  if(!prog || !gl.isProgram(prog)) {
    this.programs[token] = prog = linkProgram(
      this.gl,
      vref.shader,
      fref.shader,
      attribs,
      locations)
    vref.programs.push(token)
    fref.programs.push(token)
  }
  return prog
}

function getCache(gl) {
  var ctxCache = CACHE.get(gl)
  if(!ctxCache) {
    ctxCache = new ContextCache(gl)
    CACHE.set(gl, ctxCache)
  }
  return ctxCache
}

function getShaderReference(gl, type, src) {
  return getCache(gl).getShaderReference(type, src)
}

function createProgram(gl, vref, fref, attribs, locations) {
  return getCache(gl).getProgram(vref, fref, attribs, locations)
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const { expect } = require('chai');
const sinon = require('sinon');
const {
  processExit,
  fixtureCompare: _fixtureCompare
} = require('git-fixtures');
const isGitClean = require('git-diff-apply').isGitClean;
const emberCliUpdate = require('../../src');
const utils = require('../../src/utils');
const buildTmp = require('../helpers/build-tmp');
const {
  assertNoUnstaged,
  assertNoStaged
} = require('../helpers/assertions');

const commitMessage = 'add files';

describe('Integration - index', function() {
  this.timeout(30 * 1000);

  let cwd;
  let sandbox;
  let tmpPath;

  before(function() {
    cwd = process.cwd();
  });

  beforeEach(function() {
    sandbox = sinon.createSandbox();
  });

  afterEach(function() {
    sandbox.restore();

    process.chdir(cwd);
  });

  function merge({
    fixturesPath,
    dirty,
    from,
    to = '3.2.0-beta.1',
    reset,
    compareOnly,
    statsOnly,
    runCodemods,
    listCodemods,
    createCustomDiff
  }) {
    tmpPath = buildTmp({
      fixturesPath,
      commitMessage,
      dirty,
      npmInstall: createCustomDiff
    });

    process.chdir(tmpPath);

    let promise = emberCliUpdate({
      from,
      to,
      reset,
      compareOnly,
      statsOnly,
      runCodemods,
      listCodemods,
      createCustomDiff
    });

    return processExit({
      promise,
      cwd: tmpPath,
      commitMessage,
      expect
    });
  }

  function fixtureCompare({
    mergeFixtures
  }) {
    let actual = tmpPath;
    let expected = path.join(cwd, mergeFixtures);

    _fixtureCompare({
      expect,
      actual,
      expected
    });
  }

  it('handles dirty', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      dirty: true
    }).then(({
      status,
      stderr
    }) => {
      expect(status).to.equal(`?? a-random-new-file
`);

      expect(stderr).to.contain('You must start with a clean working directory');
      expect(stderr).to.not.contain('UnhandledPromiseRejectionWarning');
    });
  });

  it('handles non-ember-cli app', function() {
    return merge({
      fixturesPath: 'test/fixtures/package-json/non-ember-cli'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('Ember CLI project type could not be determined');
    });
  });

  it('handles non-npm dir', function() {
    return merge({
      fixturesPath: 'test/fixtures/package-json/missing'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('No package.json was found in this directory');
    });
  });

  it('handles malformed package.json', function() {
    return merge({
      fixturesPath: 'test/fixtures/package-json/malformed'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('The package.json is malformed');
    });
  });

  it('updates glimmer app', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/glimmer-app',
      from: '0.5.0',
      to: '0.6.1'
    }).then(({
      status
    }) => {
      fixtureCompare({
        mergeFixtures: 'test/fixtures/merge/glimmer-app'
      });

      expect(status).to.match(/^M {2}src\/index\.ts$/m);

      assertNoUnstaged(status);
    });
  });

  it('needs --from if glimmer app before 0.6.3', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/glimmer-app',
      to: '0.6.1'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('version cannot be determined');
    });
  });

  it('resets app', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      reset: true
    }).then(({
      status
    }) => {
      fixtureCompare({
        mergeFixtures: 'test/fixtures/reset/my-app'
      });

      expect(status).to.match(/^ D app\/controllers\/application\.js$/m);

      assertNoStaged(status);
    });
  });

  it('opens compare url', function() {
    let opn = sandbox.stub(utils, 'opn');

    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      compareOnly: true
    }).then(({
      result,
      status
    }) => {
      assertNoUnstaged(status);

      expect(result, 'don\'t accidentally print anything to the console').to.be.undefined;

      expect(opn.calledOnce).to.be.ok;
      expect(opn.args[0][0]).to.equal('https://github.com/ember-cli/ember-new-output/compare/v2.11.1...v3.2.0-beta.1');
    });
  });

  it('resolves semver ranges', function() {
    let opn = sandbox.stub(utils, 'opn');

    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      from: '2.11',
      to: '^2',
      compareOnly: true
    }).then(() => {
      expect(opn.args[0][0]).to.equal('https://github.com/ember-cli/ember-new-output/compare/v2.11.1...v2.18.2');
    });
  });

  it('shows stats only', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      statsOnly: true
    }).then(({
      result,
      status
    }) => {
      assertNoStaged(status);

      expect(result).to.equal(`project type: app
from version: 2.11.1
to version: 3.2.0-beta.1
output repo: https://github.com/ember-cli/ember-new-output
applicable codemods: `);
    });
  });

  // this one can be removed once the above starts returning codemods
  it('shows stats only - codemods', function() {
    return merge({
      fixturesPath: 'test/fixtures/codemod/min-node/my-app',
      statsOnly: true
    }).then(({
      result,
      status
    }) => {
      assertNoStaged(status);

      expect(result).to.equal(`project type: app
from version: 3.2.0-beta.1
to version: 3.2.0-beta.1
output repo: https://github.com/ember-cli/ember-new-output
applicable codemods: ember-modules-codemod, ember-qunit-codemod, ember-test-helpers-codemod, es5-getter-ember-codemod, qunit-dom-codemod`);
    });
  });

  it('lists codemods', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      listCodemods: true
    }).then(({
      result,
      status
    }) => {
      assertNoStaged(status);

      expect(JSON.parse(result)).to.have.own.property('ember-modules-codemod');
    });
  });

  it('can create a personal diff instead of using an output repo', function() {
    this.timeout(2 * 60 * 1000);

    return merge({
      fixturesPath: 'test/fixtures/local/my-custom-app',
      createCustomDiff: true
    }).then(({
      status
    }) => {
      fixtureCompare({
        mergeFixtures: 'test/fixtures/merge/my-custom-app'
      });

      assertNoUnstaged(status);
    });
  });
});
<commit_msg>destructure<commit_after>'use strict';

const path = require('path');
const { expect } = require('chai');
const sinon = require('sinon');
const {
  processExit,
  fixtureCompare: _fixtureCompare
} = require('git-fixtures');
const { isGitClean } = require('git-diff-apply');
const emberCliUpdate = require('../../src');
const utils = require('../../src/utils');
const buildTmp = require('../helpers/build-tmp');
const {
  assertNoUnstaged,
  assertNoStaged
} = require('../helpers/assertions');

const commitMessage = 'add files';

describe('Integration - index', function() {
  this.timeout(30 * 1000);

  let cwd;
  let sandbox;
  let tmpPath;

  before(function() {
    cwd = process.cwd();
  });

  beforeEach(function() {
    sandbox = sinon.createSandbox();
  });

  afterEach(function() {
    sandbox.restore();

    process.chdir(cwd);
  });

  function merge({
    fixturesPath,
    dirty,
    from,
    to = '3.2.0-beta.1',
    reset,
    compareOnly,
    statsOnly,
    runCodemods,
    listCodemods,
    createCustomDiff
  }) {
    tmpPath = buildTmp({
      fixturesPath,
      commitMessage,
      dirty,
      npmInstall: createCustomDiff
    });

    process.chdir(tmpPath);

    let promise = emberCliUpdate({
      from,
      to,
      reset,
      compareOnly,
      statsOnly,
      runCodemods,
      listCodemods,
      createCustomDiff
    });

    return processExit({
      promise,
      cwd: tmpPath,
      commitMessage,
      expect
    });
  }

  function fixtureCompare({
    mergeFixtures
  }) {
    let actual = tmpPath;
    let expected = path.join(cwd, mergeFixtures);

    _fixtureCompare({
      expect,
      actual,
      expected
    });
  }

  it('handles dirty', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      dirty: true
    }).then(({
      status,
      stderr
    }) => {
      expect(status).to.equal(`?? a-random-new-file
`);

      expect(stderr).to.contain('You must start with a clean working directory');
      expect(stderr).to.not.contain('UnhandledPromiseRejectionWarning');
    });
  });

  it('handles non-ember-cli app', function() {
    return merge({
      fixturesPath: 'test/fixtures/package-json/non-ember-cli'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('Ember CLI project type could not be determined');
    });
  });

  it('handles non-npm dir', function() {
    return merge({
      fixturesPath: 'test/fixtures/package-json/missing'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('No package.json was found in this directory');
    });
  });

  it('handles malformed package.json', function() {
    return merge({
      fixturesPath: 'test/fixtures/package-json/malformed'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('The package.json is malformed');
    });
  });

  it('updates glimmer app', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/glimmer-app',
      from: '0.5.0',
      to: '0.6.1'
    }).then(({
      status
    }) => {
      fixtureCompare({
        mergeFixtures: 'test/fixtures/merge/glimmer-app'
      });

      expect(status).to.match(/^M {2}src\/index\.ts$/m);

      assertNoUnstaged(status);
    });
  });

  it('needs --from if glimmer app before 0.6.3', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/glimmer-app',
      to: '0.6.1'
    }).then(({
      stderr
    }) => {
      expect(isGitClean({ cwd: tmpPath })).to.be.ok;

      expect(stderr).to.contain('version cannot be determined');
    });
  });

  it('resets app', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      reset: true
    }).then(({
      status
    }) => {
      fixtureCompare({
        mergeFixtures: 'test/fixtures/reset/my-app'
      });

      expect(status).to.match(/^ D app\/controllers\/application\.js$/m);

      assertNoStaged(status);
    });
  });

  it('opens compare url', function() {
    let opn = sandbox.stub(utils, 'opn');

    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      compareOnly: true
    }).then(({
      result,
      status
    }) => {
      assertNoUnstaged(status);

      expect(result, 'don\'t accidentally print anything to the console').to.be.undefined;

      expect(opn.calledOnce).to.be.ok;
      expect(opn.args[0][0]).to.equal('https://github.com/ember-cli/ember-new-output/compare/v2.11.1...v3.2.0-beta.1');
    });
  });

  it('resolves semver ranges', function() {
    let opn = sandbox.stub(utils, 'opn');

    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      from: '2.11',
      to: '^2',
      compareOnly: true
    }).then(() => {
      expect(opn.args[0][0]).to.equal('https://github.com/ember-cli/ember-new-output/compare/v2.11.1...v2.18.2');
    });
  });

  it('shows stats only', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      statsOnly: true
    }).then(({
      result,
      status
    }) => {
      assertNoStaged(status);

      expect(result).to.equal(`project type: app
from version: 2.11.1
to version: 3.2.0-beta.1
output repo: https://github.com/ember-cli/ember-new-output
applicable codemods: `);
    });
  });

  // this one can be removed once the above starts returning codemods
  it('shows stats only - codemods', function() {
    return merge({
      fixturesPath: 'test/fixtures/codemod/min-node/my-app',
      statsOnly: true
    }).then(({
      result,
      status
    }) => {
      assertNoStaged(status);

      expect(result).to.equal(`project type: app
from version: 3.2.0-beta.1
to version: 3.2.0-beta.1
output repo: https://github.com/ember-cli/ember-new-output
applicable codemods: ember-modules-codemod, ember-qunit-codemod, ember-test-helpers-codemod, es5-getter-ember-codemod, qunit-dom-codemod`);
    });
  });

  it('lists codemods', function() {
    return merge({
      fixturesPath: 'test/fixtures/local/my-app',
      listCodemods: true
    }).then(({
      result,
      status
    }) => {
      assertNoStaged(status);

      expect(JSON.parse(result)).to.have.own.property('ember-modules-codemod');
    });
  });

  it('can create a personal diff instead of using an output repo', function() {
    this.timeout(2 * 60 * 1000);

    return merge({
      fixturesPath: 'test/fixtures/local/my-custom-app',
      createCustomDiff: true
    }).then(({
      status
    }) => {
      fixtureCompare({
        mergeFixtures: 'test/fixtures/merge/my-custom-app'
      });

      assertNoUnstaged(status);
    });
  });
});
<|endoftext|>


<commit_before>(function(){

function getElementOffsetTop(element){
	var actualTop = element.offsetTop
		,offsetParentElement = element.offsetParent;
	if( offsetParentElement == null && element.parentNode ){
		/* when style display is none */
		var parentNode = element.parentNode;
		while( offsetParentElement == null ){
			offsetParentElement = parentNode.offsetParent;
			parentNode = parentNode.parentNode;
			if( !parentNode ){
				break;
			}
		}
	}
	while ( offsetParentElement !== null /* document.body */ ){
		actualTop += (offsetParentElement.offsetTop+offsetParentElement.clientTop);
		offsetParentElement = offsetParentElement.offsetParent;
	}
	return actualTop;
}

function getEleStyle(ele, cssName){
	var style = window.getComputedStyle ?
		window.getComputedStyle(ele, "") :
		ele.currentStyle;
	return style[cssName];
}

function getPageScrollOffset() {
	var doc = document, w = window;
	var x, y, docEl;

	if ( typeof w.pageYOffset === 'number' ) {
		x = w.pageXOffset;
		y = w.pageYOffset;
	} else {
		docEl = (doc.compatMode && doc.compatMode === 'CSS1Compat') ?
			doc.documentElement : doc.body;
		x = docEl.scrollLeft;
		y = docEl.scrollTop;
	}
	return {x : x, y : y};
}

function getWindowViewport() {
	var doc = document, w = window;
	var docEl = (doc.compatMode && doc.compatMode === 'CSS1Compat') ?
			doc.documentElement: doc.body;

	var width = docEl.clientWidth;
	var height = docEl.clientHeight;

	if ( w.innerWidth && width > w.innerWidth ) {
		width = w.innerWidth;
		height = w.innerHeight;
	}

	return {width : width, height : height};
}

var left = document.getElementsByClassName('left')[0];
var right = document.getElementsByClassName('right')[0];
var rightOriginOffsetTop = parseInt(getElementOffsetTop(right));
var leftHeight, rightHeight;

left.originMarginTop = left.style.marginTop.match(/\d+/);
right.originMarginTop = right.style.marginTop.match(/\d+/);

var rightFloat = function(){
	leftHeight = left.offsetHeight;
	rightHeight = right.offsetHeight;
	if(leftHeight < rightHeight){
		var temp = right;
		right = left;
		left = temp;
		leftHeight = left.offsetHeight;
		rightHeight = right.offsetHeight;
	}

	if(left.originMarginTop){
		left.style.marginTop = left.originMarginTop + 'px';
	}

	var viewportHeight = parseInt(getWindowViewport().height);
	var pageScrollTop = parseInt(getPageScrollOffset().y);
	var leftOffsetTop = parseInt(getElementOffsetTop(left));
	var rightBoxOffsetTop = parseInt(getElementOffsetTop(right));
	var rightBoxMarginTop = parseInt(right.style.marginTop.match(/\d+/));
	var maxMarginTopVal = rightHeight + rightBoxOffsetTop - leftOffsetTop - leftHeight;

	if(maxMarginTopVal > 0){
		var startBack = rightBoxOffsetTop - pageScrollTop;
		if(startBack > 0){
			right.style.marginTop = (pageScrollTop - rightOriginOffsetTop) + 'px';
		}
		return;
	}

	var startFloatDownVal = pageScrollTop + viewportHeight
		- rightOriginOffsetTop - rightHeight;

	if(rightHeight<viewportHeight){
		startFloatDownVal = pageScrollTop - rightOriginOffsetTop;
	}

	if(startFloatDownVal >= 0){
		if(rightBoxMarginTop >= startFloatDownVal){
			if(rightBoxOffsetTop > pageScrollTop && rightBoxOffsetTop > rightOriginOffsetTop){
				var temp = pageScrollTop - rightOriginOffsetTop;
				right.style.marginTop = (temp>0?temp:0) +'px';
			}
			return;
		}
		var actualVal = leftHeight + leftOffsetTop - rightHeight - rightOriginOffsetTop;
		var pos = startFloatDownVal >= actualVal ? actualVal : startFloatDownVal;
		right.style.marginTop = pos + 'px';
	}

	if(rightBoxOffsetTop > pageScrollTop && rightBoxOffsetTop > rightOriginOffsetTop){
		var temp = pageScrollTop - rightOriginOffsetTop;
		right.style.marginTop = (temp>0?temp:0) +'px';
	}
};

if( window.addEventListener ){
	document.addEventListener( 'scroll', rightFloat, false );
}else if( window.attachEvent ){
	window.attachEvent("onscroll", rightFloat);
}

})();
<commit_msg>fix float<commit_after>(function(){

function getElementOffsetTop(element){
	var actualTop = element.offsetTop
		,offsetParentElement = element.offsetParent;
	if( offsetParentElement == null && element.parentNode ){
		/* when style display is none */
		var parentNode = element.parentNode;
		while( offsetParentElement == null ){
			offsetParentElement = parentNode.offsetParent;
			parentNode = parentNode.parentNode;
			if( !parentNode ){
				break;
			}
		}
	}
	while ( offsetParentElement !== null /* document.body */ ){
		actualTop += (offsetParentElement.offsetTop+offsetParentElement.clientTop);
		offsetParentElement = offsetParentElement.offsetParent;
	}
	return actualTop;
}

function getEleStyle(ele, cssName){
	var style = window.getComputedStyle ?
		window.getComputedStyle(ele, "") :
		ele.currentStyle;
	return style[cssName];
}

function getPageScrollOffset() {
	var doc = document, w = window;
	var x, y, docEl;

	if ( typeof w.pageYOffset === 'number' ) {
		x = w.pageXOffset;
		y = w.pageYOffset;
	} else {
		docEl = (doc.compatMode && doc.compatMode === 'CSS1Compat') ?
			doc.documentElement : doc.body;
		x = docEl.scrollLeft;
		y = docEl.scrollTop;
	}
	return {x : x, y : y};
}

function getWindowViewport() {
	var doc = document, w = window;
	var docEl = (doc.compatMode && doc.compatMode === 'CSS1Compat') ?
			doc.documentElement: doc.body;

	var width = docEl.clientWidth;
	var height = docEl.clientHeight;

	if ( w.innerWidth && width > w.innerWidth ) {
		width = w.innerWidth;
		height = w.innerHeight;
	}

	return {width : width, height : height};
}

var left = document.getElementsByClassName('left')[0];
var right = document.getElementsByClassName('right')[0];
var rightOriginOffsetTop = parseInt(getElementOffsetTop(right));
var leftHeight, rightHeight;

left.originMarginTop = left.style.marginTop.match(/\d+/);
right.originMarginTop = right.style.marginTop.match(/\d+/);

var rightFloat = function(){
	leftHeight = left.offsetHeight;
	rightHeight = right.offsetHeight;
	if(leftHeight < rightHeight){
		var temp = right;
		right = left;
		left = temp;
		leftHeight = left.offsetHeight;
		rightHeight = right.offsetHeight;
		left.style.marginTop = (left.originMarginTop || 0) + 'px';
	}

	if(left.originMarginTop){
		left.style.marginTop = left.originMarginTop + 'px';
	}

	var viewportHeight = parseInt(getWindowViewport().height);
	var pageScrollTop = parseInt(getPageScrollOffset().y);
	var leftOffsetTop = parseInt(getElementOffsetTop(left));
	var rightBoxOffsetTop = parseInt(getElementOffsetTop(right));
	var rightBoxMarginTop = parseInt(right.style.marginTop.match(/\d+/));
	var maxMarginTopVal = rightHeight + rightBoxOffsetTop - leftOffsetTop - leftHeight;

	if(maxMarginTopVal > 0){
		var startBack = rightBoxOffsetTop - pageScrollTop;
		if(startBack > 0){
			right.style.marginTop = (pageScrollTop - rightOriginOffsetTop) + 'px';
		}
		return;
	}

	var startFloatDownVal = pageScrollTop + viewportHeight
		- rightOriginOffsetTop - rightHeight;

	if(rightHeight<viewportHeight){
		startFloatDownVal = pageScrollTop - rightOriginOffsetTop;
	}

	if(startFloatDownVal >= 0){
		if(rightBoxMarginTop >= startFloatDownVal){
			if(rightBoxOffsetTop > pageScrollTop && rightBoxOffsetTop > rightOriginOffsetTop){
				var temp = pageScrollTop - rightOriginOffsetTop;
				right.style.marginTop = (temp>0?temp:0) +'px';
			}
			return;
		}
		var actualVal = leftHeight + leftOffsetTop - rightHeight - rightOriginOffsetTop;
		var pos = startFloatDownVal >= actualVal ? actualVal : startFloatDownVal;
		right.style.marginTop = pos + 'px';
	}

	if(rightBoxOffsetTop > pageScrollTop && rightBoxOffsetTop > rightOriginOffsetTop){
		var temp = pageScrollTop - rightOriginOffsetTop;
		right.style.marginTop = (temp>0?temp:0) +'px';
	}
};

if( window.addEventListener ){
	document.addEventListener( 'scroll', rightFloat, false );
}else if( window.attachEvent ){
	window.attachEvent("onscroll", rightFloat);
}

})();
<|endoftext|>


<commit_before>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

var async = require('async');
var test = require('prova');

var BatchDatabase = require('../../src/nosql/batch-database');

var nosql = require('../..').nosql;
var BatchOptions = nosql.BatchOptions;
var range = nosql.rowrange;
var ReadOnlyBatchError = nosql.ReadOnlyBatchError;

var testUtil = require('./util');
var assertScanRows = testUtil.assertScanRows;
var setupDatabase = testUtil.setupDatabase;
var setupTable = testUtil.setupTable;
var uniqueName = testUtil.uniqueName;

test('db.beginBatch creates a BatchDatabase with name', function(t) {
  setupDatabase(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    o.database.beginBatch(o.ctx, new BatchOptions({}), function(err, batch) {
      if (err) {
        t.error(err);
        return o.teardown(t.end);
      }

      t.ok(batch instanceof BatchDatabase, 'batch is a BatchDatabase');
      t.notEqual(batch.name, o.database.name,
                 'batch has different name than database');
      t.notEqual(batch.fullName, o.database.fullName,
                 'batch has different fullName than database');

      o.teardown(t.end);
    });
  });
});

test('transactions are not visible until commit', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    var keyName = uniqueName('key');
    var value = uniqueName('val');

    var emptyPrefix = range.prefix('');

    db.beginBatch(ctx, new BatchOptions({}), put);

    var batch;
    function put(err, _batch) {
      if (err) {
        t.error(err);
        return o.teardown(t.end);
      }

      batch = _batch;
      var batchTable = batch.table(table.name);
      batchTable.put(ctx, keyName, value, assertNoRows);
    }

    function assertNoRows(err) {
      if (err) {
        return end(err);
      }

      assertScanRows(ctx, table, emptyPrefix, [], commit);
    }

    function commit(err) {
      if (err) {
        return end(err);
      }

      batch.commit(ctx, assertRow);
    }

    function assertRow(err) {
      if (err) {
        return end(err);
      }

      var wantRows = [{
        key: keyName,
        value: value
      }];

      assertScanRows(ctx, table, emptyPrefix, wantRows, end);
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('concurrent transactions are isolated', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    var batches;
    var batchTables;
    var rows;

    var emptyPrefix = range.prefix('');

    startBatches();

    // Create two batches.
    function startBatches() {
      async.times(2, function(n, cb) {
        db.beginBatch(ctx, {}, cb);
      }, addRows);
    }

    // Each batch adds a new row.
    function addRows(err, _batches) {
      if (err) {
        return end(err);
      }

      batches = _batches;
      batchTables = batches.map(function(batch) {
        return batch.table(table.name);
      });

      async.mapSeries(batchTables, function(batchTable, cb) {
        var key = uniqueName('key');
        var value = uniqueName('value');
        batchTable.put(ctx, key, value, function(err) {
          if (err) {
            return cb(err);
          }
          return cb(null, [{key: key, value: value}]);
        });
      }, assertBatchesSeeCorrectRows);
    }

    // Verify that each batch sees only its own rows.
    function assertBatchesSeeCorrectRows(err, _rows) {
      if (err) {
        return end(err);
      }

      rows = _rows;
      async.forEachOfSeries(batchTables, function(batchTable, idx, cb) {
        // NOTE(nlacasse): Currently, a scan() inside a batch will return only
        // the rows that existed in the snapshot when the batch was started.
        // Thus, we can't use assertScanRows() to check that the batch has the
        // correct rows.  Instead we must call get() on the table directly to
        // ensure that the new rows exist in the snapshot.
        batchTable.get(ctx, rows[idx][0].key, function(err, row) {
          if (err) {
            return cb(err);
          }
          t.equal(rows[idx].key, row.key, 'row has correct key');
          t.equal(rows[idx].value, row.value, 'row has correct value');
          return cb(null);
        });
      }, commitFirstBatch);
    }

    function commitFirstBatch(err) {
      if (err) {
        return end(err);
      }

      batches[0].commit(ctx, commitSecondBatch);
    }

    function commitSecondBatch(err) {
      if (err) {
        return end(err);
      }

      // Second batch should fail on commit.
      batches[1].commit(ctx, function(err) {
        t.ok(err, 'second batch should fail on commit');

        assertFirstBatchesRowsExist();
      });
    }

    function assertFirstBatchesRowsExist() {
      // Check that only first batch's rows exist in table.
      assertScanRows(ctx, table, emptyPrefix, rows[0], end);
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('readonly batches', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    var key = uniqueName('key');
    var value = uniqueName('value');

    var batch;
    var batchTable;

    table.put(ctx, key, value, startReadOnlyBatch);

    function startReadOnlyBatch(err) {
      if (err) {
        return end(err);
      }

      var opts = new BatchOptions(new Map([
        ['ReadOnly', true]
      ]));

      db.beginBatch(ctx, opts, attemptBatchPut);
    }

    function attemptBatchPut(err, _batch) {
      if (err) {
        return end(err);
      }

      batch = _batch;
      batchTable = batch.table(table.name);

      batchTable.put(ctx, uniqueName('key'), uniqueName('val'), function(err) {
        assertReadOnlyBatchError(err);
        attemptBatchDeletePrefix();
      });
    }

    function attemptBatchDeletePrefix() {
      batchTable.delete(ctx, range.prefix(key), function(err) {
        assertReadOnlyBatchError(err);
        attemptBatchDeleteRow();
      });
    }

    function attemptBatchDeleteRow() {
      batchTable.row(key).delete(ctx, function(err) {
        assertReadOnlyBatchError(err);
        end();
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }

    function assertReadOnlyBatchError(err) {
      t.ok(err, 'should error');
      t.ok(err instanceof ReadOnlyBatchError,
           'err should be ReadOnlyBatchError');
    }

  });
});

test('new batch operations fail after successful batch commit', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    db.beginBatch(ctx, {}, put);

    var batch;

    function put(err, _batch) {
      if (err) {
        return end(err);
      }

      batch = _batch;
      var batchTable = batch.table(table.name);

      batchTable.put(ctx, uniqueName('key'), uniqueName('val'), commit);
    }

    function commit(err) {
      if (err) {
        return end(err);
      }

      batch.commit(ctx, function(err) {
        if (err) {
          return end(err);
        }

        assertOpsFail(t, ctx, batch, table.name, end);
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('new batch operations fail after unsuccessful batch commit', function(t) {
  setupTable(t, function(err, o) {

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    db.beginBatch(ctx, {}, putTable);

    var key = uniqueName('key');
    var value = uniqueName('value');

    var batch;

    function putTable(err, _batch) {
      if (err) {
        return end(err);
      }

      batch = _batch;

      // Put on the table directly, not the batch table.  This will conflict
      // with future batchTable.put() call.
      table.put(ctx, key, value, putBatchTable);
    }

    function putBatchTable(err) {
      if (err) {
        return end(err);
      }

      var newValue = uniqueName('value');

      var batchTable = batch.table(table.name);
      batchTable.put(ctx, key, newValue, commit);
    }

    function commit(err) {
      if (err) {
        return end(err);
      }

      batch.commit(ctx, function(err) {
        t.ok(err, 'commit() should error');
        assertOpsFail(t, ctx, batch, table.name, end);
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('new batch operations fail after batch is aborted', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    db.beginBatch(ctx, {}, abort);

    function abort(err, batch) {
      if (err) {
        return end(err);
      }

      batch.abort(ctx, function(err) {
        if (err) {
          return end(err);
        }

        assertOpsFail(t, ctx, batch, table.name, end);
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

function assertOpsFail(t, ctx, batch, tableName, cb) {
  var batchTable = batch.table(tableName);

  async.series([
    assertGetFails,
    assertScanFails,
    assertPutFails,
    assertDeleteFails,
    assertRowDeleteFails,
    assertCommitFails
  ], cb);

  function assertGetFails(cb) {
    batchTable.get(ctx, uniqueName('key'), function(err) {
      t.ok(err, 'get() should error');
      cb(null);
    });
  }

  function assertScanFails(cb) {
    var streamGotError = false;

    var stream = batchTable.scan(ctx, range.prefix(''), function(err) {
      t.ok(err, 'scan() should pass error to callback');
      t.ok(streamGotError, 'scan() should send error to stream');
      cb(null);
    });

    stream.on('error', function(err) {
      streamGotError = true;
    });
  }

  function assertPutFails(cb) {
    batchTable.put(ctx, uniqueName('key'), uniqueName('val'),
                   function(err) {
      t.ok(err, 'put() should error');
      cb(null);
    });
  }

  function assertDeleteFails(cb) {
    batchTable.delete(ctx, range.prefix(uniqueName('key')), function(err) {
      t.ok(err, 'delete() should error');
      cb(null);
    });
  }

  function assertRowDeleteFails(cb) {
    batchTable.row(uniqueName('key')).delete(ctx, function(err) {
      t.ok(err, 'row.delete() should error');
      cb(null);
    });
  }

  function assertCommitFails(cb) {
    batch.commit(ctx, function(err) {
      t.ok(err, 'commit() should error');
      cb(null);
    });
  }
}
<commit_msg>TBR: Add missing "if (err)" check spotted by sadovsky in go/vcl/12569<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

var async = require('async');
var test = require('prova');

var BatchDatabase = require('../../src/nosql/batch-database');

var nosql = require('../..').nosql;
var BatchOptions = nosql.BatchOptions;
var range = nosql.rowrange;
var ReadOnlyBatchError = nosql.ReadOnlyBatchError;

var testUtil = require('./util');
var assertScanRows = testUtil.assertScanRows;
var setupDatabase = testUtil.setupDatabase;
var setupTable = testUtil.setupTable;
var uniqueName = testUtil.uniqueName;

test('db.beginBatch creates a BatchDatabase with name', function(t) {
  setupDatabase(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    o.database.beginBatch(o.ctx, new BatchOptions({}), function(err, batch) {
      if (err) {
        t.error(err);
        return o.teardown(t.end);
      }

      t.ok(batch instanceof BatchDatabase, 'batch is a BatchDatabase');
      t.notEqual(batch.name, o.database.name,
                 'batch has different name than database');
      t.notEqual(batch.fullName, o.database.fullName,
                 'batch has different fullName than database');

      o.teardown(t.end);
    });
  });
});

test('transactions are not visible until commit', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    var keyName = uniqueName('key');
    var value = uniqueName('val');

    var emptyPrefix = range.prefix('');

    db.beginBatch(ctx, new BatchOptions({}), put);

    var batch;
    function put(err, _batch) {
      if (err) {
        t.error(err);
        return o.teardown(t.end);
      }

      batch = _batch;
      var batchTable = batch.table(table.name);
      batchTable.put(ctx, keyName, value, assertNoRows);
    }

    function assertNoRows(err) {
      if (err) {
        return end(err);
      }

      assertScanRows(ctx, table, emptyPrefix, [], commit);
    }

    function commit(err) {
      if (err) {
        return end(err);
      }

      batch.commit(ctx, assertRow);
    }

    function assertRow(err) {
      if (err) {
        return end(err);
      }

      var wantRows = [{
        key: keyName,
        value: value
      }];

      assertScanRows(ctx, table, emptyPrefix, wantRows, end);
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('concurrent transactions are isolated', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    var batches;
    var batchTables;
    var rows;

    var emptyPrefix = range.prefix('');

    startBatches();

    // Create two batches.
    function startBatches() {
      async.times(2, function(n, cb) {
        db.beginBatch(ctx, {}, cb);
      }, addRows);
    }

    // Each batch adds a new row.
    function addRows(err, _batches) {
      if (err) {
        return end(err);
      }

      batches = _batches;
      batchTables = batches.map(function(batch) {
        return batch.table(table.name);
      });

      async.mapSeries(batchTables, function(batchTable, cb) {
        var key = uniqueName('key');
        var value = uniqueName('value');
        batchTable.put(ctx, key, value, function(err) {
          if (err) {
            return cb(err);
          }
          return cb(null, [{key: key, value: value}]);
        });
      }, assertBatchesSeeCorrectRows);
    }

    // Verify that each batch sees only its own rows.
    function assertBatchesSeeCorrectRows(err, _rows) {
      if (err) {
        return end(err);
      }

      rows = _rows;
      async.forEachOfSeries(batchTables, function(batchTable, idx, cb) {
        // NOTE(nlacasse): Currently, a scan() inside a batch will return only
        // the rows that existed in the snapshot when the batch was started.
        // Thus, we can't use assertScanRows() to check that the batch has the
        // correct rows.  Instead we must call get() on the table directly to
        // ensure that the new rows exist in the snapshot.
        batchTable.get(ctx, rows[idx][0].key, function(err, row) {
          if (err) {
            return cb(err);
          }
          t.equal(rows[idx].key, row.key, 'row has correct key');
          t.equal(rows[idx].value, row.value, 'row has correct value');
          return cb(null);
        });
      }, commitFirstBatch);
    }

    function commitFirstBatch(err) {
      if (err) {
        return end(err);
      }

      batches[0].commit(ctx, commitSecondBatch);
    }

    function commitSecondBatch(err) {
      if (err) {
        return end(err);
      }

      // Second batch should fail on commit.
      batches[1].commit(ctx, function(err) {
        t.ok(err, 'second batch should fail on commit');

        assertFirstBatchesRowsExist();
      });
    }

    function assertFirstBatchesRowsExist() {
      // Check that only first batch's rows exist in table.
      assertScanRows(ctx, table, emptyPrefix, rows[0], end);
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('readonly batches', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    var key = uniqueName('key');
    var value = uniqueName('value');

    var batch;
    var batchTable;

    table.put(ctx, key, value, startReadOnlyBatch);

    function startReadOnlyBatch(err) {
      if (err) {
        return end(err);
      }

      var opts = new BatchOptions(new Map([
        ['ReadOnly', true]
      ]));

      db.beginBatch(ctx, opts, attemptBatchPut);
    }

    function attemptBatchPut(err, _batch) {
      if (err) {
        return end(err);
      }

      batch = _batch;
      batchTable = batch.table(table.name);

      batchTable.put(ctx, uniqueName('key'), uniqueName('val'), function(err) {
        assertReadOnlyBatchError(err);
        attemptBatchDeletePrefix();
      });
    }

    function attemptBatchDeletePrefix() {
      batchTable.delete(ctx, range.prefix(key), function(err) {
        assertReadOnlyBatchError(err);
        attemptBatchDeleteRow();
      });
    }

    function attemptBatchDeleteRow() {
      batchTable.row(key).delete(ctx, function(err) {
        assertReadOnlyBatchError(err);
        end();
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }

    function assertReadOnlyBatchError(err) {
      t.ok(err, 'should error');
      t.ok(err instanceof ReadOnlyBatchError,
           'err should be ReadOnlyBatchError');
    }

  });
});

test('new batch operations fail after successful batch commit', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    db.beginBatch(ctx, {}, put);

    var batch;

    function put(err, _batch) {
      if (err) {
        return end(err);
      }

      batch = _batch;
      var batchTable = batch.table(table.name);

      batchTable.put(ctx, uniqueName('key'), uniqueName('val'), commit);
    }

    function commit(err) {
      if (err) {
        return end(err);
      }

      batch.commit(ctx, function(err) {
        if (err) {
          return end(err);
        }

        assertOpsFail(t, ctx, batch, table.name, end);
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('new batch operations fail after unsuccessful batch commit', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return t.end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    db.beginBatch(ctx, {}, putTable);

    var key = uniqueName('key');
    var value = uniqueName('value');

    var batch;

    function putTable(err, _batch) {
      if (err) {
        return end(err);
      }

      batch = _batch;

      // Put on the table directly, not the batch table.  This will conflict
      // with future batchTable.put() call.
      table.put(ctx, key, value, putBatchTable);
    }

    function putBatchTable(err) {
      if (err) {
        return end(err);
      }

      var newValue = uniqueName('value');

      var batchTable = batch.table(table.name);
      batchTable.put(ctx, key, newValue, commit);
    }

    function commit(err) {
      if (err) {
        return end(err);
      }

      batch.commit(ctx, function(err) {
        t.ok(err, 'commit() should error');
        assertOpsFail(t, ctx, batch, table.name, end);
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

test('new batch operations fail after batch is aborted', function(t) {
  setupTable(t, function(err, o) {
    if (err) {
      return end(err);
    }

    var ctx = o.ctx;
    var db = o.database;
    var table = o.table;

    db.beginBatch(ctx, {}, abort);

    function abort(err, batch) {
      if (err) {
        return end(err);
      }

      batch.abort(ctx, function(err) {
        if (err) {
          return end(err);
        }

        assertOpsFail(t, ctx, batch, table.name, end);
      });
    }

    function end(err) {
      t.error(err);
      o.teardown(t.end);
    }
  });
});

function assertOpsFail(t, ctx, batch, tableName, cb) {
  var batchTable = batch.table(tableName);

  async.series([
    assertGetFails,
    assertScanFails,
    assertPutFails,
    assertDeleteFails,
    assertRowDeleteFails,
    assertCommitFails
  ], cb);

  function assertGetFails(cb) {
    batchTable.get(ctx, uniqueName('key'), function(err) {
      t.ok(err, 'get() should error');
      cb(null);
    });
  }

  function assertScanFails(cb) {
    var streamGotError = false;

    var stream = batchTable.scan(ctx, range.prefix(''), function(err) {
      t.ok(err, 'scan() should pass error to callback');
      t.ok(streamGotError, 'scan() should send error to stream');
      cb(null);
    });

    stream.on('error', function(err) {
      streamGotError = true;
    });
  }

  function assertPutFails(cb) {
    batchTable.put(ctx, uniqueName('key'), uniqueName('val'),
                   function(err) {
      t.ok(err, 'put() should error');
      cb(null);
    });
  }

  function assertDeleteFails(cb) {
    batchTable.delete(ctx, range.prefix(uniqueName('key')), function(err) {
      t.ok(err, 'delete() should error');
      cb(null);
    });
  }

  function assertRowDeleteFails(cb) {
    batchTable.row(uniqueName('key')).delete(ctx, function(err) {
      t.ok(err, 'row.delete() should error');
      cb(null);
    });
  }

  function assertCommitFails(cb) {
    batch.commit(ctx, function(err) {
      t.ok(err, 'commit() should error');
      cb(null);
    });
  }
}
<|endoftext|>


<commit_before>const path = require('path'),
      remoteOriginUrl = require('remote-origin-url'),
      config = require('../../config');

const project = require(path.resolve(config.paths.commands, 'project/controller')),
      command = require(path.resolve(config.paths.commands, 'command/controller'));

const { file, inquirer, ora } = require('schemium-api').utils;

function setProjectRoot(path) {
   return new Promise(resolve => {
      if (path) {
         console.log(`root path: ${path}`)
         resolve(path.trim().replace(new RegExp(' ', 'g'), '-').toLowerCase())
      } else {
         const cwd = process.cwd() + '/';

         return inquirer.prompt({
            type: 'input',
            name: 'path',
            message: 'root path:',
            default: cwd,
            filter: function (asw) {
               let path = asw.trim().replace(new RegExp(' ', 'g'), '-').toLowerCase();

               if (new RegExp('^/').test(path))
                  return path;
               else {
                  return cwd + path;
               }
            }
         })
         .then(path => resolve(path))
      }
   })
   .then(path => checkProjectRoot(path));
}

function setPackageJson(path) {
   return setGitInfo(path)
   .then(gitInfo => promptPackageJson(gitInfo, path))
   .then(answers => Object.assign(answers, {
      version: "0.0.1",
      main: "./bin/" + answers.name + '.js',
      scripts: {
         test: answers.test || "echo \"Error: no test specified\" && exit 1"
      },
      bin: {
         [answers.name]: "./bin/" + answers.name + '.js'
      },
      dependencies: {
         "schemium-api": "^0.0.3"
      },
      schemium: {
         path: {
            schemas: "commands/**/schema.js",
            models: "commands/**/model.js",
            controllers: "commands/**/controller.js"
         }
      }
   }))
   .then(package => {
      delete package.test;
      return package;
   })
   .then(package => {
      const packageStringified = JSON.stringify(package, null, 4);

      console.log(`\nAbout to write to: ${path}`)
      console.log(packageStringified)

      return inquirer.prompt({
         type: 'confirm',
         name: 'create',
         message: 'Is this ok?',
         default: true
      })
      .then(answer => Object.assign(answer, { packageStringified: packageStringified }))
   })
   .then(res => {
      if (res.create) {
         console.log("");
         const spinner = ora('Creating package.json file...').start();

         return file.write({
            to: path + '/package.json',
            content: res.packageStringified
         })
         .then(() => {
            return {
               spinner: spinner,
               package: JSON.parse(res.packageStringified)
            }
         });

      } else {
         console.log("Aborted!");
         process.exit(0);
      }
   })
   .then(res => {
      return new Promise(resolve => {
         setTimeout(function () {
            res.spinner.succeed();

            resolve({
               path: path,
               package: res.package
            });
         }, 1000);
      });
   })
   .catch(ex => {
      console.log()
      throw new Error(ex);
   });
}

function promptPackageJson(gitInfo, path){
   return inquirer.prompt([{
      type: 'input',
      name: 'name',
      message: 'package name:',
      default: getProjectName(path)
   }, {
      type: 'input',
      name: 'description',
      message: 'description:'
   }, {
      type: 'input',
      name: 'test',
      message: 'test command:'
   }, {
      type: 'input',
      name: 'keywords',
      message: 'keywords:',
      filter: function (asw) {
         return asw.split(' ')
      }
   }, {
      type: 'input',
      name: 'author',
      message: 'author:'
   }, {
      type: 'input',
      name: 'license',
      message: 'license:',
      default: 'ISC'
   }])
   .then(answers => Object.assign(answers, gitInfo));
}

function getProjectName(path) {
   try {
      let name = path.split('/')[path.split('/').length - 1];

      if (name === "") {
         name = path.split('/')[path.split('/').length - 2];
      }

      return name;
   } catch (ex) {
      return path;
   }
}

function checkProjectRoot(data) {
   return new Promise((resolve, reject) => {
      file.exists(`${data.path}/package.json`.replace('//', '/', 'g'), function (err, stat) {
         if (err == null) {
            console.log(`\nThe path ${data.path} already exists and has a package.json file.\
                         \nIf you decide to continue, the existent file will be overwritten.`);

            inquirer.prompt({
               type: 'confirm',
               name: 'continue',
               message: `Continue anyway?`,
               default: true
            })
            .then(asw => {
               console.log();
               resolve(Object.assign(asw, data))
            });
         } else if (err.code == 'ENOENT') {
            resolve(Object.assign({ continue: true }, data));
         } else {
            reject(err.code);
         }
      });
   })
   .then(res => {
      if (res.continue) {
         return res.path;
      } else {
         console.log("Aborted!");
         process.exit(0);
      }
   })
   .catch(ex => {
      throw new Error(ex);
   })
}

function setGitInfo(path) {
   return new Promise(resolve => {
      remoteOriginUrl(`${path}.git/config`,
      (err, url) => {
         if (url) {
            url = url.split('.git').shift();

            resolve({
               repository: {
                  url: `git+${url}.git`
               },
               bugs: {
                  url: `${url}/issues`
               },
               homepage: `${url}#readme`
            });

         } else {
            let prompt = inquirer.prompt({
               type: 'input',
               name: 'git',
               message: 'git url:',
               validate: function (input) {
                  var pattern = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
                  return (input && new RegExp(pattern).test(input)) || input && 'This is not a valid url.' || true
               }
            })
            .then(url => {
               if (url.git) {
                  url = url.git.split('.git').shift();

                  return {
                     repository: {
                        url: `git+${url}.git`
                     },
                     bugs: {
                        url: `${url}/issues`
                     },
                     homepage: `${url}#readme`
                  }
               }

               return;
            });

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

function buildProject(res) {
   return project.add(res.path)
   .then(() => file.writeFromTpl({
      from: path.resolve(config.paths.templates, 'bin.tpl'),
      to: path.resolve(res.path, res.package.bin[Object.keys(res.package.bin)[0]])
   }))
   .then(() => installDependencies(res.path))
   .then(() => project.treeView(res.path))
   .then(() => {

      console.log('Your project is ready!');

      return inquirer.prompt({
         type: 'confirm',
         name: 'continue',
         message: `Do you want to create some commands now?`,
         default: true
      })
      .then(command => Object.assign({ path: res.path }, command))
   });
}

function installDependencies(path) {
   const spinner = ora('Installing dependencies...').start();

   return new Promise((resolve, reject) => {
      require('child_process')
      .exec('npm install', {
         cwd: path
      }, (error, stdout, stderr) => {
         if (error) reject(`exec error: ${error}`);

         spinner.succeed();
         console.log("");

         process.stdout.write(stdout)
         console.log("");

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

module.exports = {
   setProjectRoot: setProjectRoot,
   setPackageJson: setPackageJson,
   buildProject: buildProject
}<commit_msg>update api version<commit_after>const path = require('path'),
      remoteOriginUrl = require('remote-origin-url'),
      config = require('../../config');

const project = require(path.resolve(config.paths.commands, 'project/controller')),
      command = require(path.resolve(config.paths.commands, 'command/controller'));

const { file, inquirer, ora } = require('schemium-api').utils;

function setProjectRoot(path) {
   return new Promise(resolve => {
      if (path) {
         console.log(`root path: ${path}`)
         resolve(path.trim().replace(new RegExp(' ', 'g'), '-').toLowerCase())
      } else {
         const cwd = process.cwd() + '/';

         return inquirer.prompt({
            type: 'input',
            name: 'path',
            message: 'root path:',
            default: cwd,
            filter: function (asw) {
               let path = asw.trim().replace(new RegExp(' ', 'g'), '-').toLowerCase();

               if (new RegExp('^/').test(path))
                  return path;
               else {
                  return cwd + path;
               }
            }
         })
         .then(path => resolve(path))
      }
   })
   .then(path => checkProjectRoot(path));
}

function setPackageJson(path) {
   return setGitInfo(path)
   .then(gitInfo => promptPackageJson(gitInfo, path))
   .then(answers => Object.assign(answers, {
      version: "0.0.1",
      main: "./bin/" + answers.name + '.js',
      scripts: {
         test: answers.test || "echo \"Error: no test specified\" && exit 1"
      },
      bin: {
         [answers.name]: "./bin/" + answers.name + '.js'
      },
      dependencies: {
         "schemium-api": "^0.0.6"
      },
      schemium: {
         path: {
            schemas: "commands/**/schema.js",
            models: "commands/**/model.js",
            controllers: "commands/**/controller.js"
         }
      }
   }))
   .then(package => {
      delete package.test;
      return package;
   })
   .then(package => {
      const packageStringified = JSON.stringify(package, null, 4);

      console.log(`\nAbout to write to: ${path}`)
      console.log(packageStringified)

      return inquirer.prompt({
         type: 'confirm',
         name: 'create',
         message: 'Is this ok?',
         default: true
      })
      .then(answer => Object.assign(answer, { packageStringified: packageStringified }))
   })
   .then(res => {
      if (res.create) {
         console.log("");
         const spinner = ora('Creating package.json file...').start();

         return file.write({
            to: path + '/package.json',
            content: res.packageStringified
         })
         .then(() => {
            return {
               spinner: spinner,
               package: JSON.parse(res.packageStringified)
            }
         });

      } else {
         console.log("Aborted!");
         process.exit(0);
      }
   })
   .then(res => {
      return new Promise(resolve => {
         setTimeout(function () {
            res.spinner.succeed();

            resolve({
               path: path,
               package: res.package
            });
         }, 1000);
      });
   })
   .catch(ex => {
      console.log()
      throw new Error(ex);
   });
}

function promptPackageJson(gitInfo, path){
   return inquirer.prompt([{
      type: 'input',
      name: 'name',
      message: 'package name:',
      default: getProjectName(path)
   }, {
      type: 'input',
      name: 'description',
      message: 'description:'
   }, {
      type: 'input',
      name: 'test',
      message: 'test command:'
   }, {
      type: 'input',
      name: 'keywords',
      message: 'keywords:',
      filter: function (asw) {
         return asw.split(' ')
      }
   }, {
      type: 'input',
      name: 'author',
      message: 'author:'
   }, {
      type: 'input',
      name: 'license',
      message: 'license:',
      default: 'ISC'
   }])
   .then(answers => Object.assign(answers, gitInfo));
}

function getProjectName(path) {
   try {
      let name = path.split('/')[path.split('/').length - 1];

      if (name === "") {
         name = path.split('/')[path.split('/').length - 2];
      }

      return name;
   } catch (ex) {
      return path;
   }
}

function checkProjectRoot(data) {
   return new Promise((resolve, reject) => {
      file.exists(`${data.path}/package.json`.replace('//', '/', 'g'), function (err, stat) {
         if (err == null) {
            console.log(`\nThe path ${data.path} already exists and has a package.json file.\
                         \nIf you decide to continue, the existent file will be overwritten.`);

            inquirer.prompt({
               type: 'confirm',
               name: 'continue',
               message: `Continue anyway?`,
               default: true
            })
            .then(asw => {
               console.log();
               resolve(Object.assign(asw, data))
            });
         } else if (err.code == 'ENOENT') {
            resolve(Object.assign({ continue: true }, data));
         } else {
            reject(err.code);
         }
      });
   })
   .then(res => {
      if (res.continue) {
         return res.path;
      } else {
         console.log("Aborted!");
         process.exit(0);
      }
   })
   .catch(ex => {
      throw new Error(ex);
   })
}

function setGitInfo(path) {
   return new Promise(resolve => {
      remoteOriginUrl(`${path}.git/config`,
      (err, url) => {
         if (url) {
            url = url.split('.git').shift();

            resolve({
               repository: {
                  url: `git+${url}.git`
               },
               bugs: {
                  url: `${url}/issues`
               },
               homepage: `${url}#readme`
            });

         } else {
            let prompt = inquirer.prompt({
               type: 'input',
               name: 'git',
               message: 'git url:',
               validate: function (input) {
                  var pattern = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
                  return (input && new RegExp(pattern).test(input)) || input && 'This is not a valid url.' || true
               }
            })
            .then(url => {
               if (url.git) {
                  url = url.git.split('.git').shift();

                  return {
                     repository: {
                        url: `git+${url}.git`
                     },
                     bugs: {
                        url: `${url}/issues`
                     },
                     homepage: `${url}#readme`
                  }
               }

               return;
            });

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

function buildProject(res) {
   return project.add(res.path)
   .then(() => file.writeFromTpl({
      from: path.resolve(config.paths.templates, 'bin.tpl'),
      to: path.resolve(res.path, res.package.bin[Object.keys(res.package.bin)[0]])
   }))
   .then(() => installDependencies(res.path))
   .then(() => project.treeView(res.path))
   .then(() => {

      console.log('Your project is ready!');

      return inquirer.prompt({
         type: 'confirm',
         name: 'continue',
         message: `Do you want to create some commands now?`,
         default: true
      })
      .then(command => Object.assign({ path: res.path }, command))
   });
}

function installDependencies(path) {
   const spinner = ora('Installing dependencies...').start();

   return new Promise((resolve, reject) => {
      require('child_process')
      .exec('npm install', {
         cwd: path
      }, (error, stdout, stderr) => {
         if (error) reject(`exec error: ${error}`);

         spinner.succeed();
         console.log("");

         process.stdout.write(stdout)
         console.log("");

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

module.exports = {
   setProjectRoot: setProjectRoot,
   setPackageJson: setPackageJson,
   buildProject: buildProject
}<|endoftext|>


<commit_before>const GReYBot = require('../greybot');

exports.commands = [
	'prune'
]

var lastPruned = new Date().getTime() - (GReYBot.Config.pruneInterval * 1000);

exports.prune = {
	usage: '<count|1-100>',
	process: (msg, suffix) => {
		var count = parseInt(suffix) || 0;

		if (msg.member.hasPermission('MANAGE_MESSAGES')) {
			var timeSinceLastPrune = Math.floor(new Date().getTime() - lastPruned);
			console.log(timeSinceLastPrune);
			if (timeSinceLastPrune > (GReYBot.Config.pruneInterval * 1000)) {
				count++;
				if (count > 1) {
					if (count > GReYBot.Config.pruneMax) count = GReYBot.Config.pruneMax;

					msg.channel.fetchMessages({ limit: count })
						.then(messages => messages.map(m => m.delete()))
						.then(function () {
							msg.channel.send({
								embed: {
									color: GReYBot.Config.defaultEmbedColor,
									description: `Pruning ${count - 1} messages...`
								}
							}).then(message => message.delete(5000));
						});

					lastPruned = new Date().getTime();
				}
			}
			else {
				var wait = Math.floor(GReYBot.Config.pruneInterval - (timeSinceLastPrune / 1000));
				msg.channel.send({
					embed: {
						color: GReYBot.Config.defaultEmbedColor,
						description: `You can't do that yet, please wait ${wait} second${wait > 1 ? "s" : ""}`
					}
				}).then(message => message.delete(5000));
			}
		}
		else {
			msg.channel.send({
				embed: {
					color: GReYBot.Config.defaultEmbedColor,
					description: `You can't do that ${msg.member}...`
				}
			}).then(message => message.delete(5000));
		}
	}
}
<commit_msg>added kick command, progress towards #15<commit_after>const GReYBot = require('../greybot');

exports.commands = [
	'prune',
	'kick'
]

var lastPruned = new Date().getTime() - (GReYBot.Config.pruneInterval * 1000);

exports.prune = {
	usage: '<count|1-100>',
	process: (msg, suffix) => {
		var count = parseInt(suffix) || 0;

		if (msg.member.hasPermission('MANAGE_MESSAGES')) {
			var timeSinceLastPrune = Math.floor(new Date().getTime() - lastPruned);
			console.log(timeSinceLastPrune);
			if (timeSinceLastPrune > (GReYBot.Config.pruneInterval * 1000)) {
				count++;
				if (count > 1) {
					if (count > GReYBot.Config.pruneMax) count = GReYBot.Config.pruneMax;

					msg.channel.fetchMessages({ limit: count })
						.then(messages => messages.map(m => m.delete()))
						.then(function () {
							msg.channel.send({
								embed: {
									color: GReYBot.Config.defaultEmbedColor,
									description: `Pruning ${count - 1} messages...`
								}
							}).then(message => message.delete(5000));
						});

					lastPruned = new Date().getTime();
				}
			}
			else {
				var wait = Math.floor(GReYBot.Config.pruneInterval - (timeSinceLastPrune / 1000));
				msg.channel.send({
					embed: {
						color: GReYBot.Config.defaultEmbedColor,
						description: `You can't do that yet, please wait ${wait} second${wait > 1 ? "s" : ""}`
					}
				}).then(message => message.delete(5000));
			}
		}
		else {
			msg.channel.send({
				embed: {
					color: GReYBot.Config.defaultEmbedColor,
					description: `You can't do that ${msg.member}...`
				}
			}).then(message => message.delete(5000));
		}
	}
}

exports.kick = {
	usage: '<user> <reason>',
	description: 'Kick a user with an optional reason. Requires both the command user and the bot to have kick permission',
	process: function (bot, msg, suffix) {
		let args = suffix.split(" ");
		if (args.length > 0 && args[0]) {
			let hasPermissonToKick =  msg.guild.members.get(bot.user.id).permissions.has("KICK_MEMBERS");
			if (!hasPermissonToKick) {
				msg.channel.send( "I don't have permission to kick people!");
				return;
			}
			if (!msg.guild.members.get(msg.author.id).permissions.has("KICK_MEMBERS")) {
				msg.channel.send( "You don't have permission to kick people!");
				return;
			}
			var targetId = resolveMention(args[0]);
			let target = msg.guild.members.get(targetId);
			if (target != undefined) {
				if (!target.kickable) {
					msg.channel.send("I can't kick " + target + ". Do they have the same or a higher role than me?");
					return;
				}
				if (args.length > 1) {
					let reason = args.slice(1).join(" ");
					target.kick(reason).then(x => {
						msg.channel.send("Kicking " + target + " from " + msg.guild + " for " + reason + "!");
					}).catch(err => msg.channel.send("Kicking " + target + " failed:\n"));
				} else {
					target.kick().then(x => {
						msg.channel.send("Kicking " + target + " from " + msg.guild + "!");
					}).catch(err => msg.channel.send("Kicking " + target + " failed:\n"));
				}
			} else {
				msg.channel.send("I couldn't find a user " + args[0]);
			}
		} else {
			msg.channel.send("You must specify a user to kick!");
		}
	}
}
<|endoftext|>


<commit_before>/**
 * @file serverInfo command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license GPL-3.0
 */

exports.exec = async (Bastion, message) => {
  try {
    let nonAnimatedEmojis = message.guild.emojis.filter(emoji => !emoji.animated);
    let guildEmojis = nonAnimatedEmojis.size > 0 ? nonAnimatedEmojis.size > 25 ? `${nonAnimatedEmojis.map(e => `<:${e.name}:${e.id}>`).splice(0, 25).join(' ')} and ${nonAnimatedEmojis.size - 25} more.` : nonAnimatedEmojis.map(e => `<:${e.name}:${e.id}>`).join(' ') : '-';

    let guildModel = await Bastion.database.models.guild.findOne({
      attributes: [ 'premium', 'description' ],
      where: {
        guildID: message.guild.id
      }
    });
    let guildDescription;
    if (guildModel && guildModel.dataValues.description) {
      guildDescription = await Bastion.functions.decodeString(guildModel.dataValues.description);
    }

    message.channel.send({
      embed: {
        color: Bastion.colors.BLUE,
        title: 'Server Info',
        description: guildDescription,
        fields: [
          {
            name: 'Name',
            value: message.guild.name,
            inline: true
          },
          {
            name: 'ID',
            value: message.guild.id,
            inline: true
          },
          {
            name: 'Premium',
            value: `[${guildModel && guildModel.dataValues.premium}](https://bastionbot.org 'Premium servers & perks are coming soon™')`.toUpperCase(),
            inline: true
          },
          {
            name: 'Owner',
            value: message.guild.owner.user.tag,
            inline: true
          },
          {
            name: 'Owner ID',
            value: message.guild.ownerID,
            inline: true
          },
          {
            name: 'Created At',
            value: message.guild.createdAt.toUTCString(),
            inline: true
          },
          {
            name: 'Region',
            value: message.guild.region.toUpperCase(),
            inline: true
          },
          {
            name: 'Roles',
            value: message.guild.roles.size - 1,
            inline: true
          },
          {
            name: 'Members',
            value: `${message.guild.members.filter(m => !m.user.bot).size} Cached Users\n${message.guild.members.filter(m => m.user.bot).size} Cached BOTs`,
            inline: true
          },
          {
            name: 'Text Channels',
            value: message.guild.channels.filter(channel => channel.type === 'text').size,
            inline: true
          },
          {
            name: 'Voice Channels',
            value: message.guild.channels.filter(channel => channel.type === 'voice').size,
            inline: true
          },
          {
            name: 'Server Emojis',
            value: guildEmojis
          }
        ],
        thumbnail: {
          url: message.guild.icon ? message.guild.iconURL : `https://dummyimage.com/128/7289DA/FFFFFF/&text=${encodeURIComponent(message.guild.nameAcronym)}`
        },
        image: {
          url: message.guild.splash ? message.guild.splashURL : null
        }
      }
    }).catch(e => {
      Bastion.log.error(e);
    });
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'sinfo' ],
  enabled: true
};

exports.help = {
  name: 'serverInfo',
  botPermission: '',
  userTextPermission: '',
  userVoicePermission: '',
  usage: 'serverInfo',
  example: []
};
<commit_msg>commands: minor changes to the UI of serverInfo command<commit_after>/**
 * @file serverInfo command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license GPL-3.0
 */

exports.exec = async (Bastion, message) => {
  try {
    let nonAnimatedEmojis = message.guild.emojis.filter(emoji => !emoji.animated);
    let guildEmojis = nonAnimatedEmojis.size > 0 ? nonAnimatedEmojis.size > 25 ? `${nonAnimatedEmojis.map(e => `<:${e.name}:${e.id}>`).splice(0, 25).join(' ')} and ${nonAnimatedEmojis.size - 25} more.` : nonAnimatedEmojis.map(e => `<:${e.name}:${e.id}>`).join(' ') : '-';

    let guildModel = await Bastion.database.models.guild.findOne({
      attributes: [ 'premium', 'description' ],
      where: {
        guildID: message.guild.id
      }
    });
    let guildDescription;
    if (guildModel && guildModel.dataValues.description) {
      guildDescription = await Bastion.functions.decodeString(guildModel.dataValues.description);
    }

    message.channel.send({
      embed: {
        color: Bastion.colors.BLUE,
        author: {
          name: message.guild.name
        },
        title: 'Server Info',
        description: guildDescription,
        fields: [
          {
            name: 'ID',
            value: message.guild.id,
            inline: true
          },
          {
            name: 'Premium',
            value: `[${guildModel && guildModel.dataValues.premium}](https://bastionbot.org 'Premium servers & perks are coming soon™')`.toUpperCase(),
            inline: true
          },
          {
            name: 'Owner',
            value: message.guild.owner.user.tag,
            inline: true
          },
          {
            name: 'Owner ID',
            value: message.guild.ownerID,
            inline: true
          },
          {
            name: 'Created At',
            value: message.guild.createdAt.toUTCString(),
            inline: true
          },
          {
            name: 'Region',
            value: message.guild.region.toUpperCase(),
            inline: true
          },
          {
            name: 'Members',
            value: `${message.guild.members.filter(m => !m.user.bot).size} Cached Users\n${message.guild.members.filter(m => m.user.bot).size} Cached BOTs`,
            inline: true
          },
          {
            name: 'Roles',
            value: message.guild.roles.size - 1,
            inline: true
          },
          {
            name: 'Text Channels',
            value: message.guild.channels.filter(channel => channel.type === 'text').size,
            inline: true
          },
          {
            name: 'Voice Channels',
            value: message.guild.channels.filter(channel => channel.type === 'voice').size,
            inline: true
          },
          {
            name: 'Server Emojis',
            value: guildEmojis
          }
        ],
        thumbnail: {
          url: message.guild.icon ? message.guild.iconURL : `https://dummyimage.com/128/7289DA/FFFFFF/&text=${encodeURIComponent(message.guild.nameAcronym)}`
        },
        image: {
          url: message.guild.splash ? message.guild.splashURL : null
        }
      }
    }).catch(e => {
      Bastion.log.error(e);
    });
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [ 'sinfo' ],
  enabled: true
};

exports.help = {
  name: 'serverInfo',
  botPermission: '',
  userTextPermission: '',
  userVoicePermission: '',
  usage: 'serverInfo',
  example: []
};
<|endoftext|>


<commit_before>//const Discord = require('discord.js');

module.exports = (client, message, args) => {
  /*const embed = new Discord.MessageEmbed()
    .setDescription(`${message.guild.name}'s Information and Details`)
    .setThumbnail(message.guild.iconURL())
    .setFooter(message.guild.owner.user.tag, message.guild.owner.user.avatarURL())
    .addField('Members', `${message.guild.members.filter(member => member.user.bot).size} bots of ${message.guild.memberCount} members.`)
    .addField('Channels', `${message.guild.channels.filter(chan => chan.type === 'voice').size} voice / ${message.guild.channels.filter(chan => chan.type === 'text').size} text`)
    .addField('Roles', message.guild.roles.map(role => role.name).join(', '));
  message.channel.send({ embed });*/

  //console.log(`Connected as ${c.user.username} / Currently in ${c.guilds.size} servers`)

  message.channel.send({embed: {
    color: 3447003
    .setDescription(`${message.guild.name}'s Information and Details`)
    .setThumbnail(message.guild.iconURL())
    .setFooter(message.guild.owner.user.tag, message.guild.owner.user.avatarURL())
    .addField('Members', `${message.guild.members.filter(member => member.user.bot).size} bots of ${message.guild.memberCount} members.`)
    .addField('Channels', `${message.guild.channels.filter(chan => chan.type === 'voice').size} voice / ${message.guild.channels.filter(chan => chan.type === 'text').size} text`)
    .addField('Roles', message.guild.roles.map(role => role.name).join(', ')) }})

};<commit_msg><commit_after>const Discord = require('discord.js');

module.exports = (client, message, args) => {
  /*const embed = new Discord.MessageEmbed()
    .setDescription(`${message.guild.name}'s Information and Details`)
    .setThumbnail(message.guild.iconURL())
    .setFooter(message.guild.owner.user.tag, message.guild.owner.user.avatarURL())
    .addField('Members', `${message.guild.members.filter(member => member.user.bot).size} bots of ${message.guild.memberCount} members.`)
    .addField('Channels', `${message.guild.channels.filter(chan => chan.type === 'voice').size} voice / ${message.guild.channels.filter(chan => chan.type === 'text').size} text`)
    .addField('Roles', message.guild.roles.map(role => role.name).join(', '));
  message.channel.send({ embed });*/

  //console.log(`Connected as ${c.user.username} / Currently in ${c.guilds.size} servers`)

  message.channel.send({embed: {
    color: 3447003
    .setDescription(`${message.guild.name}'s Information and Details`)
    .setThumbnail(message.guild.iconURL())
    .setFooter(message.guild.owner.user.tag, message.guild.owner.user.avatarURL())
    .addField('Members', `${message.guild.members.filter(member => member.user.bot).size} bots of ${message.guild.memberCount} members.`)
    .addField('Channels', `${message.guild.channels.filter(chan => chan.type === 'voice').size} voice / ${message.guild.channels.filter(chan => chan.type === 'text').size} text`)
    .addField('Roles', message.guild.roles.map(role => role.name).join(', ')) }})

};<|endoftext|>