<commit_before>(function() {
    'use strict';

    var fs          = require('fs'),
        EventEmitter= require('events').EventEmitter,

        versionio   = require('version-io'),
        changelog   = require('changelog-io'),
        Util        = require('util-io'),
        spawnify    = require('spawnify'),
        async       = require('async'),
        minor       = require('minor'),
        prepend     = require('prepend'),
        exec        = require('execon'),
        grizzly     = require('grizzly'),

        Cmd         = [ 'git add package.json',
                        'git add ChangeLog',
                        'git commit -am "feature(package) v{{ version }}"',
                        'git tag v{{version}}',
                        'git push origin v{{version}}',
                        'git push origin master',
                        'npm publish'
                    ].join('&&'),

        MSG         = [ 'publish <version>',
                        'package: {{ name }} v{{ version }}'
                    ].join('\n');

    module.exports  = function(version) {
        var emitter = new EventEmitter(),
            name    = process.cwd() + '/package.json';

        readjson(name, function(error, info) {
            if (!info)
                emitter.emit('error', Error('package.json not found'));
            else if (!version)
                emitter.emit('data', Util.render(MSG, {
                    name    : info.name,
                    version : info.version
                }));
            else
                publish(version, info, emitter);
        });

        return emitter;
    };

    function publish(version, info, emitter) {
        var cmd,
            chlog       = '';

        if (!version.indexOf('v'))
            version = version.slice(1);
        else if (/major|minor|patch/.test(version))
            version = minor(version, info.version);

        cmd = Util.render(Cmd, {
            version: version
        });

        async.series([

            function(callback) {
                changelog(version, function(error, data) {
                    if (error) {
                        callback(error);
                    } else {
                        prepend('ChangeLog', data, callback);

                        chlog = rmLines(data, 2);
                        chlog = markdown(chlog);
                    }
                });
            },

            function(callback) {
                versionio(version, callback);
            },

            function(callback) {
                var done,
                    spawn = spawnify(cmd);

                spawn.on('error', function(error) {
                    if (!done) {
                        done = true;
                        callback();
                    }

                    emitter.emit('error', error);
                });

                spawn.on('data', function(data) {
                    emitter.emit('data', data);
                });

                spawn.on('exit', function() {
                    spawn = null;

                    if (!done) {
                        done = true;
                        callback();
                    }
                });
            },

            function (callback) {
                var v = 'v' + version;

                grizzly(null, {
                    owner       : info.author.split(' ')[0],
                    repo        : info.name,
                    tag_name    : v,
                    name        : info.name + ' ' + v,
                    body        : chlog
                }, function(error) {
                    if (!error)
                        emitter.emit('data', 'release: ok');

                    callback(error);
                });
            }

        ], function(error) {
            if (error)
                emitter.emit('error', error);

            emitter.emit('exit');
        });

        return emitter;
    }

    function rmLines(str, count) {
        return str
            .split('\n')
            .slice(count)
            .join('\n');
    }

    function markdown(str) {
        return str
            .replace(/fix:/g, '## fix')
            .replace(/feature:/g, '## feature');
    }

    function readjson(name, callback) {
        fs.readFile(name, 'utf8', function(error, data) {
            var json;

            if (!error)
                error = exec.try(function() {
                    json = JSON.parse(data);
                });

            callback(error, json);
        });
    }
})();
<commit_msg>feature(publish) grizzly: add owner<commit_after>(function() {
    'use strict';

    var fs          = require('fs'),
        EventEmitter= require('events').EventEmitter,

        versionio   = require('version-io'),
        changelog   = require('changelog-io'),
        Util        = require('util-io'),
        spawnify    = require('spawnify'),
        async       = require('async'),
        minor       = require('minor'),
        prepend     = require('prepend'),
        exec        = require('execon'),
        grizzly     = require('grizzly'),

        Cmd         = [ 'git add package.json',
                        'git add ChangeLog',
                        'git commit -am "feature(package) v{{ version }}"',
                        'git tag v{{version}}',
                        'git push origin v{{version}}',
                        'git push origin master',
                        'npm publish'
                    ].join('&&'),

        MSG         = [ 'publish <version>',
                        'package: {{ name }} v{{ version }}'
                    ].join('\n');

    module.exports  = function(version) {
        var emitter = new EventEmitter(),
            name    = process.cwd() + '/package.json';

        readjson(name, function(error, info) {
            if (!info)
                emitter.emit('error', Error('package.json not found'));
            else if (!version)
                emitter.emit('data', Util.render(MSG, {
                    name    : info.name,
                    version : info.version
                }));
            else
                publish(version, info, emitter);
        });

        return emitter;
    };

    function publish(version, info, emitter) {
        var cmd,
            chlog       = '';

        if (!version.indexOf('v'))
            version = version.slice(1);
        else if (/major|minor|patch/.test(version))
            version = minor(version, info.version);

        cmd = Util.render(Cmd, {
            version: version
        });

        async.series([

            function(callback) {
                changelog(version, function(error, data) {
                    if (error) {
                        callback(error);
                    } else {
                        prepend('ChangeLog', data, callback);

                        chlog = rmLines(data, 2);
                        chlog = markdown(chlog);
                    }
                });
            },

            function(callback) {
                versionio(version, callback);
            },

            function(callback) {
                var done,
                    spawn = spawnify(cmd);

                spawn.on('error', function(error) {
                    if (!done) {
                        done = true;
                        callback();
                    }

                    emitter.emit('error', error);
                });

                spawn.on('data', function(data) {
                    emitter.emit('data', data);
                });

                spawn.on('exit', function() {
                    spawn = null;

                    if (!done) {
                        done = true;
                        callback();
                    }
                });
            },

            function (callback) {
                var v       = 'v' + version,
                    owner   = info.author.split(' ')[0];

                grizzly(null, {
                    owner       : owner,
                    repo        : info.name,
                    tag_name    : v,
                    name        : info.name + ' ' + v,
                    body        : chlog
                }, function(error) {
                    if (!error)
                        emitter.emit('data', 'release: ok');

                    callback(error);
                });
            }

        ], function(error) {
            if (error)
                emitter.emit('error', error);

            emitter.emit('exit');
        });

        return emitter;
    }

    function rmLines(str, count) {
        return str
            .split('\n')
            .slice(count)
            .join('\n');
    }

    function markdown(str) {
        return str
            .replace(/fix:/g, '## fix')
            .replace(/feature:/g, '## feature');
    }

    function readjson(name, callback) {
        fs.readFile(name, 'utf8', function(error, data) {
            var json;

            if (!error)
                error = exec.try(function() {
                    json = JSON.parse(data);
                });

            callback(error, json);
        });
    }
})();
<|endoftext|>


<commit_before>var _ = require('lodash'),
    Async = require('async'),

    Fs = require('fs'),
    Path = require('path'),
    recast = require('recast'),
    rework = require('rework'),
    reworkUrl = require('rework-plugin-url'),

    SourceMapResolve = require('source-map-resolve'),
    UglifyJS = require('uglify-js');

module.exports.publish = function(options) {
  var buildDir = options.buildDir,
      circus = JSON.parse(Fs.readFileSync(buildDir + '/circus.json').toString()),
      published = {};

  if (circus.children) {
    Async.each(_.values(circus.children), function(dir, callback) {
        if (options.filter) {
          options.filter(dir, function(publish) {
            if (publish) {
              run();
            } else {
              callback();
            }
          });
        } else {
          run();
        }

        function run() {
          module.exports.publish(_.defaults({
            buildDir: Path.join(buildDir, dir),
            prefix: dir,
            callback: function(err, childrenPublished) {
              _.each(childrenPublished, function(url, file) {
                published[Path.join(dir, file)] = url;
              });
              callback(err);
            }
          }, options));
        }
      }, function(err) {
        options.callback(err, published);
      });
    return;
  }

  Async.series([
    // Publish files that are not css, js, or source maps
    publishFiles(
      function(file) {
        return !/\.map$/.test(file)
            && !/\.css$/.test(file)
            && !/\.js$/.test(file);
      }),

    // Publish css files
    publishFiles(
      function(file) {
        return /\.css$/.test(file);
      },
      processCSS),

    // Publish non-entry js files
    publishFiles(
      function(file) {
        return /\.js$/.test(file) && file !== circus.entry;
      },
      processJS),

    // Publish entry file. This must go last as it could have references to
    // anu of the above files.
    publishFiles(
      function(file) {
        return file === circus.entry;
      },
      processJS)
  ], function(err) {
    /*istnabul ignore if */
    if (err) {
      return options.callback(err);
    }

    Fs.writeFile(buildDir + '/circus.json', JSON.stringify(circus, undefined, '  '), function(err) {
      options.callback(err, published);
    });
  });

  function processCSS(file, data, callback) {
    // Replace any url references to the above
    data = updateUrls(circus.published, data + '');

    callback(undefined, data);
  }
  function processJS(file, data, callback) {
    // Preemptively kill the sourcemap published entry
    circus.published[file + '.map'] = undefined;

    if (options.sourceMap !== false) {
      SourceMapResolve.resolveSourceMap(data + '', Path.resolve(buildDir, file), Fs.readFile, function(err, sourceMap) {
        // Transform embedded urls using resolve
        var ast = recast.parse(data, {sourceFileName : file});

        recast.visit(ast, {
          visitLiteral: function(path) {
            // Replace literal file references
            if (circus.published.hasOwnProperty(path.value.value)) {
              path.value.value = circus.published[path.value.value];
            }
            return path.value;
          }
        });

        var output = recast.print(ast, {
          sourceMapName: sourceMap && sourceMap.sourceMappingURL,
          inputSourceMap: sourceMap && sourceMap.map
        });

        var minified = minifyJS(file, output.code, output.map),
            mapSource = JSON.stringify(minified.map);
        Fs.writeFile(Path.join(buildDir, file + '.prod.map'), mapSource, function(err) {
          /*istanbul ignore if */
          if (err) {
            return callback(err);
          }

          if (options.sourceMap !== 'local') {
            var relativeFile = Path.join(options.prefix || '', file + '.map');
            options.publish(relativeFile, mapSource, function(err, name) {
              circus.published[file + '.map'] = name;
              published[file + '.map'] = name;

              var source = minified.code;
              source = source.replace(/sourceMappingURL=.*/, 'sourceMappingURL=' + name);
              callback(undefined, source);
            });
          } else {
            // Strip out any source map comment
            callback(undefined, stripSourceMap(minified.code));
          }
        });
      });
    } else {
      // Strip out any source map comment
      callback(undefined, minifyJS(file, data));
    }
  }

  function minifyJS(file, source, map) {
    return UglifyJS.minify(source+'', {
      fromString: true,
      inSourceMap: map,
      outSourceMap: map && (file + '.prod.map')
    });
  }
  function stripSourceMap(source) {
    return source.replace(/.*sourceMappingURL=.*$/, '');
  }

  function publishFiles(filter, preprocessor) {
    preprocessor = preprocessor || function(file, data, callback) { callback(undefined, data); };

    return function(callback) {
      var files = _.filter(circus.files, filter);

      Async.each(files, function(file, callback) {
        Fs.readFile(Path.join(buildDir, file), function(err, data) {
          /*istanbul ignore if */
          if (err) {
            return callback(err);
          }

          preprocessor(file, data, function(err, data) {
            /*istanbul ignore if */
            if (err) {
              return callback(err);
            }

            var relativeFile = Path.join(options.prefix || '', file);
            options.publish(relativeFile, data, function(err, name) {
              if (err) {
                return callback(err);
              }

              circus.published[file] = name;
              published[file] = name;
              callback();
            });
          });
        });
      },
      callback);
    };
  }
};

// Via https://github.com/webpack/css-loader/blob/982f37476d51655d4ac017a70b77eed2d3698adf/index.js#L134
/*
  MIT License http://www.opensource.org/licenses/mit-license.php
  Author Tobias Koppers @sokra
*/
function updateUrls(published, content) {
  return rework(content)
      .use(reworkUrl(function(value) {
        var tail = '';
        if (/^([^?#]*)([\?#].*?)$/.exec(value)) {
          value = RegExp.$1;
          tail = RegExp.$2;
        }
        return published[value] ? published[value] + tail : value;
      }))
      .toString({compress: true});
}
<commit_msg>Only check strings for published replacement<commit_after>var _ = require('lodash'),
    Async = require('async'),

    Fs = require('fs'),
    Path = require('path'),
    recast = require('recast'),
    rework = require('rework'),
    reworkUrl = require('rework-plugin-url'),

    SourceMapResolve = require('source-map-resolve'),
    UglifyJS = require('uglify-js');

module.exports.publish = function(options) {
  var buildDir = options.buildDir,
      circus = JSON.parse(Fs.readFileSync(buildDir + '/circus.json').toString()),
      published = {};

  if (circus.children) {
    Async.each(_.values(circus.children), function(dir, callback) {
        if (options.filter) {
          options.filter(dir, function(publish) {
            if (publish) {
              run();
            } else {
              callback();
            }
          });
        } else {
          run();
        }

        function run() {
          module.exports.publish(_.defaults({
            buildDir: Path.join(buildDir, dir),
            prefix: dir,
            callback: function(err, childrenPublished) {
              _.each(childrenPublished, function(url, file) {
                published[Path.join(dir, file)] = url;
              });
              callback(err);
            }
          }, options));
        }
      }, function(err) {
        options.callback(err, published);
      });
    return;
  }

  Async.series([
    // Publish files that are not css, js, or source maps
    publishFiles(
      function(file) {
        return !/\.map$/.test(file)
            && !/\.css$/.test(file)
            && !/\.js$/.test(file);
      }),

    // Publish css files
    publishFiles(
      function(file) {
        return /\.css$/.test(file);
      },
      processCSS),

    // Publish non-entry js files
    publishFiles(
      function(file) {
        return /\.js$/.test(file) && file !== circus.entry;
      },
      processJS),

    // Publish entry file. This must go last as it could have references to
    // anu of the above files.
    publishFiles(
      function(file) {
        return file === circus.entry;
      },
      processJS)
  ], function(err) {
    /*istnabul ignore if */
    if (err) {
      return options.callback(err);
    }

    Fs.writeFile(buildDir + '/circus.json', JSON.stringify(circus, undefined, '  '), function(err) {
      options.callback(err, published);
    });
  });

  function processCSS(file, data, callback) {
    // Replace any url references to the above
    data = updateUrls(circus.published, data + '');

    callback(undefined, data);
  }
  function processJS(file, data, callback) {
    // Preemptively kill the sourcemap published entry
    circus.published[file + '.map'] = undefined;

    if (options.sourceMap !== false) {
      SourceMapResolve.resolveSourceMap(data + '', Path.resolve(buildDir, file), Fs.readFile, function(err, sourceMap) {
        // Transform embedded urls using resolve
        var ast = recast.parse(data, {sourceFileName : file});

        recast.visit(ast, {
          visitLiteral: function(path) {
            // Replace literal file references
            var value = path.value.value;
            if (typeof value === 'string' && circus.published.hasOwnProperty(value)) {
              path.value.value = circus.published[value];
            }
            return path.value;
          }
        });

        var output = recast.print(ast, {
          sourceMapName: sourceMap && sourceMap.sourceMappingURL,
          inputSourceMap: sourceMap && sourceMap.map
        });

        var minified = minifyJS(file, output.code, output.map),
            mapSource = JSON.stringify(minified.map);
        Fs.writeFile(Path.join(buildDir, file + '.prod.map'), mapSource, function(err) {
          /*istanbul ignore if */
          if (err) {
            return callback(err);
          }

          if (options.sourceMap !== 'local') {
            var relativeFile = Path.join(options.prefix || '', file + '.map');
            options.publish(relativeFile, mapSource, function(err, name) {
              circus.published[file + '.map'] = name;
              published[file + '.map'] = name;

              var source = minified.code;
              source = source.replace(/sourceMappingURL=.*/, 'sourceMappingURL=' + name);
              callback(undefined, source);
            });
          } else {
            // Strip out any source map comment
            callback(undefined, stripSourceMap(minified.code));
          }
        });
      });
    } else {
      // Strip out any source map comment
      callback(undefined, minifyJS(file, data));
    }
  }

  function minifyJS(file, source, map) {
    return UglifyJS.minify(source+'', {
      fromString: true,
      inSourceMap: map,
      outSourceMap: map && (file + '.prod.map')
    });
  }
  function stripSourceMap(source) {
    return source.replace(/.*sourceMappingURL=.*$/, '');
  }

  function publishFiles(filter, preprocessor) {
    preprocessor = preprocessor || function(file, data, callback) { callback(undefined, data); };

    return function(callback) {
      var files = _.filter(circus.files, filter);

      Async.each(files, function(file, callback) {
        Fs.readFile(Path.join(buildDir, file), function(err, data) {
          /*istanbul ignore if */
          if (err) {
            return callback(err);
          }

          preprocessor(file, data, function(err, data) {
            /*istanbul ignore if */
            if (err) {
              return callback(err);
            }

            var relativeFile = Path.join(options.prefix || '', file);
            options.publish(relativeFile, data, function(err, name) {
              if (err) {
                return callback(err);
              }

              circus.published[file] = name;
              published[file] = name;
              callback();
            });
          });
        });
      },
      callback);
    };
  }
};

// Via https://github.com/webpack/css-loader/blob/982f37476d51655d4ac017a70b77eed2d3698adf/index.js#L134
/*
  MIT License http://www.opensource.org/licenses/mit-license.php
  Author Tobias Koppers @sokra
*/
function updateUrls(published, content) {
  return rework(content)
      .use(reworkUrl(function(value) {
        var tail = '';
        if (/^([^?#]*)([\?#].*?)$/.exec(value)) {
          value = RegExp.$1;
          tail = RegExp.$2;
        }
        return published[value] ? published[value] + tail : value;
      }))
      .toString({compress: true});
}
<|endoftext|>


<commit_before>
module.exports = exports = rebuild

exports.usage = 'Attempts to install pre-built binary for module'

var fs = require('fs')
  , tar = require('tar')
  , path = require('path')
  , zlib = require('zlib')
  , log = require('npmlog')
  , semver = require('semver')
  , request = require('request')
  , win = process.platform == 'win32'
  , os = require('os')
  , existsAsync = fs.exists || path.exists
  , cp = require('child_process')

function test_binary(opts,callback) {
    var args = [];
    var shell_cmd;
    var arch_names = {
        'ia32':'-i386',
        'x64':'-x86_64'
    }
    if (process.platform === 'darwin' && arch_names[opts.target_arch]) {
        shell_cmd = 'arch';
        args.push(arch_names[opts.target_arch]);
        args.push(process.execPath);
    } else if (process.arch == opts.target_arch) {
        shell_cmd = process.execPath;
    }
    if (!shell_cmd) {
        return callback();
    }
    args.push(opts.module_main);
    cp.execFile(shell_cmd, args, function(err, stdout, stderr) {
        if (err || stderr) {
            return callback(new Error(err.message || stderr));
        }
        return callback();
    });
}

function compile(args,callback) {
    var shell_cmd = 'node-gyp';
    if (win) {
        shell_cmd = 'node-gyp.cmd';
    }
    console.log(args);
    var cmd = cp.spawn(shell_cmd,args, {cwd: undefined, env: process.env, customFds: [ 0, 1, 2]});
    cmd.on('error', function (err) {
        if (err) {
            return callback(new Error("Failed to execute '" + shell_cmd + ' ' + shell_args.join(' ') + "' (" + err + ")"));
        }
        callback();
    });
    cmd.on('close', function (err, stdout, stderr) {
        if (err) {
            return callback(new Error("Failed to execute '" + shell_cmd + ' ' + shell_args.join(' ') + "' (" + err + ")"));
        }
        callback();
    });
}

function download(url,opts,callback) {
    log.http('GET', url)

    var req = null
    var requestOpts = {
        uri: url
      , headers: {
          'User-Agent': 'node-pre-gyp (node ' + process.version + ')'
        }
    }

    var proxyUrl = opts.proxy
                || process.env.http_proxy
                || process.env.HTTP_PROXY
                || process.env.npm_config_proxy
    if (proxyUrl) {
      if (/^https?:\/\//i.test(proxyUrl)) {
        log.verbose('download', 'using proxy url: "%s"', proxyUrl)
        requestOpts.proxy = proxyUrl
      } else {
        log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
      }
    }
    try {
      req = request(requestOpts)
    } catch (e) {
      callback(e)
    }
    if (req) {
      req.on('response', function (res) {
        log.http(res.statusCode, url)
      })
    }
    callback(null,req);
}

function place_binary(from,to,opts,callback) {
    download(from,opts,function(err,req) {
        if (err) return callback(err);
        if (!req) return callback(new Error("empty req"));
        var badDownload = false
            , extractCount = 0
            , gunzip = zlib.createGunzip()
            , extracter = tar.Extract({ path: to, strip: 1, filter: isValid });
        function afterTarball(err) {
            if (err) return callback(err);
            if (badDownload) return callback(new Error("bad download"));
            if (extractCount === 0) {
              return callback(new Error('There was a fatal problem while downloading/extracting the tarball'))
            }
            log.verbose('tarball', 'done parsing tarball')
            callback();
        }
        function isValid () {
            extractCount++
            return true
        };
        gunzip.on('error', callback)
        extracter.on('error', callback)
        extracter.on('end', afterTarball)

        req.on('error', function (err) {
            badDownload = true
            callback(err)
        })

        req.on('close', function () {
            if (extractCount === 0) {
              callback(new Error('Connection closed while downloading tarball file'))
            }
        })

        req.on('response', function (res) {
            if (res.statusCode !== 200) {
              badDownload = true
              callback(new Error(res.statusCode + ' status code downloading tarball'))
              return
            }
            // start unzipping and untaring
            req.pipe(gunzip).pipe(extracter)
        })
    });
}

function validate_config(package_json,callback) {
    if (!package_json.main) {
        return callback(new Error("package.json must declare 'main'"));
    }
    if (!package_json.binary) {
        return callback(new Error("package.json must declare 'binary' object'"));
    }
    var o = package_json.binary;
    if (!o.module_path) {
        return callback(new Error("package.json must declare 'binary.module_path'"));
    }
    if (!o.module_name) {
        return callback(new Error("package.json must declare 'binary.module_name'"));
    }
    if (!o.template) {
        return callback(new Error("package.json must declare 'binary.template'"));
    }
    if (!o.remote_uri) {
        return callback(new Error("package.json must declare 'binary.remote_uri'"));
    }
    callback();
};

function eval_template(template,opts) {
    Object.keys(opts).forEach(function(key) {
        template = template.replace('{'+key+'}',opts[key]);
    });
    return template;
}

function get_node_abi() {
    // process.versions.modules added in >= v0.10.4 and v0.11.7
    // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e
    return process.versions.modules ? 'node-v' + (+process.versions.modules) :
           'v8-' + process.versions.v8.split('.').slice(0,2).join('.');
}

function rebuild(gyp, argv, callback) {
    // @TODO - respect -C/--directory
    var package_json = JSON.parse(fs.readFileSync('./package.json'));
    validate_config(package_json,function(err) {
        if (err) return callback(err);
        if (gyp.opts['build-from-source']
            && (gyp.opts['build-from-source'] === true
                || gyp.opts['build-from-source'] === package_json.name)) {
            return compile(['rebuild'],callback);
        }
        var module_version = semver.parse(package_json.version);
        var opts = {
            configuration: (gyp.opts.debug === true) ? 'Debug' : 'Release'
            , module_name: package_json.binary.module_name
            , major: module_version.major
            , minor: module_version.minor
            , patch: module_version.patch
            , node_abi: get_node_abi()
            , platform: process.platform
            , arch: process.arch
            , target_arch: gyp.opts.target_arch || process.arch
            , module_main: package_json.main
        }
        var versioned = eval_template(package_json.binary.template,opts);
        var from = package_json.binary.remote_uri + '/' + versioned;
        var to = package_json.binary.module_path;
        var binary_module = path.join(to,opts.module_name);
        if (existsAsync(binary_module,function(found) {
            if (found) {
                log.verbose('install','already in place');
                callback();
            } else {
                place_binary(from,to,opts,function(err) {
                    if (err) {
                        log.verbose('build','source compile required');
                        compile(['rebuild'],callback);
                    } else {
                        test_binary(opts,function(err) {
                            if (err) compile(['rebuild'],callback);
                            return callback();
                        });
                    };
                });
            }
        }));
    });
}
<commit_msg>remove console.log<commit_after>
module.exports = exports = rebuild

exports.usage = 'Attempts to install pre-built binary for module'

var fs = require('fs')
  , tar = require('tar')
  , path = require('path')
  , zlib = require('zlib')
  , log = require('npmlog')
  , semver = require('semver')
  , request = require('request')
  , win = process.platform == 'win32'
  , os = require('os')
  , existsAsync = fs.exists || path.exists
  , cp = require('child_process')

function test_binary(opts,callback) {
    var args = [];
    var shell_cmd;
    var arch_names = {
        'ia32':'-i386',
        'x64':'-x86_64'
    }
    if (process.platform === 'darwin' && arch_names[opts.target_arch]) {
        shell_cmd = 'arch';
        args.push(arch_names[opts.target_arch]);
        args.push(process.execPath);
    } else if (process.arch == opts.target_arch) {
        shell_cmd = process.execPath;
    }
    if (!shell_cmd) {
        return callback();
    }
    args.push(opts.module_main);
    cp.execFile(shell_cmd, args, function(err, stdout, stderr) {
        if (err || stderr) {
            return callback(new Error(err.message || stderr));
        }
        return callback();
    });
}

function compile(args,callback) {
    var shell_cmd = 'node-gyp';
    if (win) {
        shell_cmd = 'node-gyp.cmd';
    }
    var cmd = cp.spawn(shell_cmd,args, {cwd: undefined, env: process.env, customFds: [ 0, 1, 2]});
    cmd.on('error', function (err) {
        if (err) {
            return callback(new Error("Failed to execute '" + shell_cmd + ' ' + shell_args.join(' ') + "' (" + err + ")"));
        }
        callback();
    });
    cmd.on('close', function (err, stdout, stderr) {
        if (err) {
            return callback(new Error("Failed to execute '" + shell_cmd + ' ' + shell_args.join(' ') + "' (" + err + ")"));
        }
        callback();
    });
}

function download(url,opts,callback) {
    log.http('GET', url)

    var req = null
    var requestOpts = {
        uri: url
      , headers: {
          'User-Agent': 'node-pre-gyp (node ' + process.version + ')'
        }
    }

    var proxyUrl = opts.proxy
                || process.env.http_proxy
                || process.env.HTTP_PROXY
                || process.env.npm_config_proxy
    if (proxyUrl) {
      if (/^https?:\/\//i.test(proxyUrl)) {
        log.verbose('download', 'using proxy url: "%s"', proxyUrl)
        requestOpts.proxy = proxyUrl
      } else {
        log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
      }
    }
    try {
      req = request(requestOpts)
    } catch (e) {
      callback(e)
    }
    if (req) {
      req.on('response', function (res) {
        log.http(res.statusCode, url)
      })
    }
    callback(null,req);
}

function place_binary(from,to,opts,callback) {
    download(from,opts,function(err,req) {
        if (err) return callback(err);
        if (!req) return callback(new Error("empty req"));
        var badDownload = false
            , extractCount = 0
            , gunzip = zlib.createGunzip()
            , extracter = tar.Extract({ path: to, strip: 1, filter: isValid });
        function afterTarball(err) {
            if (err) return callback(err);
            if (badDownload) return callback(new Error("bad download"));
            if (extractCount === 0) {
              return callback(new Error('There was a fatal problem while downloading/extracting the tarball'))
            }
            log.verbose('tarball', 'done parsing tarball')
            callback();
        }
        function isValid () {
            extractCount++
            return true
        };
        gunzip.on('error', callback)
        extracter.on('error', callback)
        extracter.on('end', afterTarball)

        req.on('error', function (err) {
            badDownload = true
            callback(err)
        })

        req.on('close', function () {
            if (extractCount === 0) {
              callback(new Error('Connection closed while downloading tarball file'))
            }
        })

        req.on('response', function (res) {
            if (res.statusCode !== 200) {
              badDownload = true
              callback(new Error(res.statusCode + ' status code downloading tarball'))
              return
            }
            // start unzipping and untaring
            req.pipe(gunzip).pipe(extracter)
        })
    });
}

function validate_config(package_json,callback) {
    if (!package_json.main) {
        return callback(new Error("package.json must declare 'main'"));
    }
    if (!package_json.binary) {
        return callback(new Error("package.json must declare 'binary' object'"));
    }
    var o = package_json.binary;
    if (!o.module_path) {
        return callback(new Error("package.json must declare 'binary.module_path'"));
    }
    if (!o.module_name) {
        return callback(new Error("package.json must declare 'binary.module_name'"));
    }
    if (!o.template) {
        return callback(new Error("package.json must declare 'binary.template'"));
    }
    if (!o.remote_uri) {
        return callback(new Error("package.json must declare 'binary.remote_uri'"));
    }
    callback();
};

function eval_template(template,opts) {
    Object.keys(opts).forEach(function(key) {
        template = template.replace('{'+key+'}',opts[key]);
    });
    return template;
}

function get_node_abi() {
    // process.versions.modules added in >= v0.10.4 and v0.11.7
    // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e
    return process.versions.modules ? 'node-v' + (+process.versions.modules) :
           'v8-' + process.versions.v8.split('.').slice(0,2).join('.');
}

function rebuild(gyp, argv, callback) {
    // @TODO - respect -C/--directory
    var package_json = JSON.parse(fs.readFileSync('./package.json'));
    validate_config(package_json,function(err) {
        if (err) return callback(err);
        if (gyp.opts['build-from-source']
            && (gyp.opts['build-from-source'] === true
                || gyp.opts['build-from-source'] === package_json.name)) {
            return compile(['rebuild'],callback);
        }
        var module_version = semver.parse(package_json.version);
        var opts = {
            configuration: (gyp.opts.debug === true) ? 'Debug' : 'Release'
            , module_name: package_json.binary.module_name
            , major: module_version.major
            , minor: module_version.minor
            , patch: module_version.patch
            , node_abi: get_node_abi()
            , platform: process.platform
            , arch: process.arch
            , target_arch: gyp.opts.target_arch || process.arch
            , module_main: package_json.main
        }
        var versioned = eval_template(package_json.binary.template,opts);
        var from = package_json.binary.remote_uri + '/' + versioned;
        var to = package_json.binary.module_path;
        var binary_module = path.join(to,opts.module_name);
        if (existsAsync(binary_module,function(found) {
            if (found) {
                log.verbose('install','already in place');
                callback();
            } else {
                place_binary(from,to,opts,function(err) {
                    if (err) {
                        log.verbose('build','source compile required');
                        compile(['rebuild'],callback);
                    } else {
                        test_binary(opts,function(err) {
                            if (err) compile(['rebuild'],callback);
                            return callback();
                        });
                    };
                });
            }
        }));
    });
}
<|endoftext|>


<commit_before>// Load in dependencies
var assert = require('assert');
var fs = require('fs');
var spawn = require('child_process').spawn;
var util = require('util');
var _ = require('underscore');
var async = require('async');
var bufferedSpawn = require('buffered-spawn');
var Chalk = require('chalk').constructor;
var deepEqual = require('deep-equal');

// Define constants for our environment variables
var FOUNDRY_VERSION_KEY = 'FOUNDRY_VERSION';
var FOUNDRY_MESSAGE_KEY = 'FOUNDRY_MESSAGE';
var FOUNDRY_VERSION_VAR = '$FOUNDRY_VERSION';
var FOUNDRY_MESSAGE_VAR = '$FOUNDRY_MESSAGE';
if (process.platform === 'win32') {
  FOUNDRY_VERSION_VAR = '%FOUNDRY_VERSION%';
  FOUNDRY_MESSAGE_VAR = '%FOUNDRY_MESSAGE%';
}

// Define a class to wrap release internals
function Release(releaseCommands, options) {
  // Assert against releaseCommands
  if (!Array.isArray(releaseCommands)) {
    throw new Error('foundry expected `releaseCommands` to be an array. Received: ' + JSON.stringify(releaseCommands));
  }

  // Upcast our releaseCommands from strings to objects
  // TODO: If these one-offs for `releaseCommand` become unwieldy, consider writing a `ReleaseCommand` class
  //   with abstractions for `updateFiles`/etc and `specVersion`
  releaseCommands = releaseCommands.map(function upcastReleaseCommand (releaseCommand) {
    if (typeof releaseCommand === 'string') {
      return {
        type: 'releaseCommand',
        command: releaseCommand
      };
    } else {
      return releaseCommand;
    }
  });

  // Validate each of our command types
  releaseCommands.forEach(function validateReleaseCommand (releaseCommand) {
    if (releaseCommand.type === 'releaseCommand') {
      assert(releaseCommand.command, 'Expected `releaseCommand.command` to be defined but it was not. ' +
        'Received: ' + JSON.stringify(releaseCommand));
    } else if (releaseCommand.type === 'customCommand') {
      // Verify any of `updateFiles`, `commit`, `register`, or `publish`
      var hasValidCommand = Release.STEPS.some(function verifyStepExists (step) {
        return releaseCommand[step];
      });
      assert(hasValidCommand, 'Expected `customCommand` to have command for `updateFiles`, `commit`, `publish`, ' +
        'or `register` but none were defined. Received: ' + JSON.stringify(releaseCommand));
    } else {
      assert.fail('Unknown `releaseCommand.type` found, expected `releaseCommand` or `customCommand`. ' +
        'Received: ' + JSON.stringify(releaseCommand));
    }
  });

  // Define commands for our release commands to have a consistent API with custom commands
  releaseCommands = releaseCommands.map(function upcastReleaseCommand (releaseCommand) {
    if (releaseCommand.type === 'releaseCommand') {
      var command = releaseCommand.command;
      return _.defaults({}, releaseCommand, {
        // Example: foundry-release-npm update-files "$FOUNDRY_VERSION" "$FOUNDRY_MESSAGE"
        // DEV: We use only string concatenation for the later parts since `shell-quote` won't work for Windows
        updateFiles: command + ' update-files "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"',
        commit: command + ' commit "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"',
        publish: command + ' publish "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"',
        register: command + ' register "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"'
      });
    } else {
      return releaseCommand;
    }
  });

  // Save releaseCommands and options for later
  this.releaseCommands = releaseCommands;
  this.options = options || {};
  this.stdout = this.options.stdout || process.stdout;
  this.customStdout = !!this.options.stdout;
  this.stderr = this.options.stderr || process.stderr;
  this.customStderr = !!this.options.stderr;
  this.chalk = new Chalk({enabled: this.options.color});
}
Release.RESUME_FILE = 'foundry-resume.json';
Release.STEPS = ['updateFiles', 'commit', 'publish', 'register'];
Release.specVersion = '2.0.0';
Release.readResumeFile = function (callback) {
  fs.readFile(Release.RESUME_FILE, 'utf8', callback);
};
Release.writeResumeFile = function (content, callback) {
  fs.writeFile(Release.RESUME_FILE, content, callback);
};
Release.prototype = {
  validateSpecVersion: function (callback) {
    var releaseCommands = this.releaseCommands;
    async.map(releaseCommands, function getSpecVersion (releaseCommand, cb) {
      // If the command is a release command, get the version
      //   e.g.: foundry-release-git --spec-version
      if (releaseCommand.type === 'releaseCommand') {
        bufferedSpawn(releaseCommand.command, ['--spec-version'], function handleSpecVersion (err, stdout, stderr) {
          // If there was an error
          if (err) {
            // If the command wasn't found, generate a better error
            if (err.code === 'ENOENT') {
              return cb(new Error('Attempted to run "' + releaseCommand.command + ' --spec-version" ' +
                'but it wasn\'t found. Please verify your dependencies are installed ' +
                'and the PATH environment variables are set up properly'));
            // Otherwise if there was stderr, callback with it as our error
            } else if (stderr) {
              return cb(new Error(stderr));
            // Otherwise, callback with our error
            } else {
              return cb(err);
            }
          // Otherwise, callback with a trimmed stdout (removes any newlines)
          } else {
            return cb(null, stdout.trim());
          }
        });
      // Otherwise, assume it's foundry's version
      } else {
        process.nextTick(function replyWithFoundrySpecVersion () {
          cb(null, Release.specVersion);
        });
      }
    }, function handleSpecVersions (err, specVersions) {
      // If there was an error for any command, callback with it
      if (err) {
        return callback(err);
      }

      // Otherwise, validate our spec versions
      var i = 0;
      var len = specVersions.length;
      for (; i < len; i++) {
        // If the specVersion doesn't line up, error out with library info
        var specVersion = specVersions[i];
        if (specVersion !== Release.specVersion) {
          var releaseCommand = releaseCommands[i];
          return callback(new Error('Expected release command "' + releaseCommand.command +
            '" to have a `--spec-version` of "' + Release.specVersion + '" but it was "' + specVersion + '"'));
        }
      }

      // Callback with no error
      return callback(null);
    });
  },

  getReleaseSteps: function (params) {
    // Generate a container for our steps
    var steps = [];
    var that = this;

    // For each of step keys, add their respective steps
    function addSteps(stepKey) {
      that.releaseCommands.forEach(function addReleaseStep (releaseComand) {
        if (releaseComand[stepKey]) {
          steps.push({
            step: releaseComand[stepKey],
            completed: false
          });
        }
      });
    }
    addSteps('updateFiles');
    addSteps('commit');
    // Only run register if we are at the 'register' semver (e.g. 1.0.0)
    if (params[FOUNDRY_VERSION_KEY] === '1.0.0') {
      addSteps('register');
    }
    addSteps('publish');

    // Return our steps
    return steps;
  },

  notifyUserReleaseSteps: function (params) {
    var stdout = this.stdout;
    var chalk = this.chalk;
    stdout.write(
      'Configuring steps with ' + chalk.bold('FOUNDRY_VERSION') + ': ' + params[FOUNDRY_VERSION_KEY] + '\n');
    stdout.write(
      'Configuring steps with ' + chalk.bold('FOUNDRY_MESSAGE') + ': ' + params[FOUNDRY_MESSAGE_KEY] + '\n');
  },

  release: function (version, callback) {
    var that = this;
    var params = {
      FOUNDRY_VERSION: version,
      FOUNDRY_MESSAGE: 'Release ' + version
    };
    async.series([
      function validateSpecVersionFn (cb) {
        that.validateSpecVersion(cb);
      },
      function prepareReleaseSteps (cb) {
        params.steps = that.getReleaseSteps(params);
        process.nextTick(cb);
      },
      function notifyUserReleaseSteps (cb) {
        that.notifyUserReleaseSteps(params);
        process.nextTick(cb);
      },
      function runReleaseSteps (cb) {
        that._runReleaseSteps(params, cb);
      }
    ], callback);
  },

  resume: function (params, callback) {
    var that = this;
    async.series([
      function validateSpecVersionFn (cb) {
        that.validateSpecVersion(cb);
      },
      function validateParams (cb) {
        // If there is no version nor message, error out
        if (params[FOUNDRY_VERSION_KEY] === undefined) {
          return cb(new Error('Expected `' + FOUNDRY_VERSION_KEY + '` to be defined in `' +
            Release.RESUME_FILE + '` but it was not.'));
        }
        if (params[FOUNDRY_MESSAGE_KEY] === undefined) {
          return cb(new Error('Expected `' + FOUNDRY_MESSAGE_KEY + '` to be defined in `' +
            Release.RESUME_FILE + '` but it was not.'));
        }

        // Verify our steps line up exactly (order and properties)
        var configSteps = that.getReleaseSteps(params);
        var resumeSteps = params.steps;
        var incompleteResumeSteps = resumeSteps.map(function normalizeCompletedProperties (step) {
          step = _.clone(step);
          // DEV: We are overly protective of our properties changing to ensure the tests fail when appropriate
          if (step.hasOwnProperty('completed')) {
            step.completed = false;
          }
          return step;
        });
        if (!deepEqual(incompleteResumeSteps, configSteps)) {
          return cb(new Error(
            'Expected `foundry-resume.json` and `.foundryrc/package.json` commands to line up exactly. ' +
            'Please do not adjust `foundry` configuration nor `foundry-resume.json`. ' +
            'Otherwise, the release will be terminate in an incomplete state.'));
        }
        process.nextTick(cb);
      },
      function notifyUserReleaseSteps (cb) {
        that.notifyUserReleaseSteps(params);
        process.nextTick(cb);
      },
      function runReleaseSteps (cb) {
        that._runReleaseSteps(params, cb);
      }
    ], callback);
  },

  _runReleaseSteps: function (params, callback) {
    var that = this;
    async.eachSeries(params.steps, function _runReleaseStepFn (stepInfo, cb) {
      // Localize common step variables
      var cmd = stepInfo.step;
      var stdout = that.stdout;
      var stderr = that.stderr;
      var chalk = that.chalk;

      // If the step has already been completed, skip it
      if (stepInfo.completed) {
        stdout.write(chalk.green('Step already complete') + ': ' + cmd + '\n');
        return process.nextTick(cb);
      }

      // Log the step we are running
      stdout.write(chalk.green('Running step') + ': ' + cmd + '\n');

      // Prepare our command environment
      var cmdEnv = _.defaults(_.object([
        [FOUNDRY_VERSION_KEY, params[FOUNDRY_VERSION_KEY]],
        [FOUNDRY_MESSAGE_KEY, params[FOUNDRY_MESSAGE_KEY]]
      ]), process.env);
      // DEV: We conditionally use 'pipe' on `stdout` to allow for buffering during testing
      var stdio = [process.stdin, that.customStdout ? 'pipe' : stdout, that.customStderr ? 'pipe' : stderr];
      var conf = {stdio: stdio, env: cmdEnv};

      // Prepare the command itself
      // DEV: We use `sh` or `cmd` to support interpretting environment variables like `npm run-script`
      // https://github.com/npm/npm/blob/v3.3.6/lib/utils/lifecycle.js#L210-L225
      // DEV: `-c` means command
      var sh = 'sh';
      var shFlag = '-c';
      if (process.platform === 'win32') {
        sh = process.env.comspec || 'cmd';
        // DEV: `/d` disables AutoRun command execution
        // DEV: `/s /c` means use the following command as is
        //   https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/cmd.mspx?mfr=true
        shFlag = '/d /s /c';
        conf.windowsVerbatimArguments = true;
      }

      // If we aren't on a dry run
      if (!that.options.dryRun) {
        // Run our command and pipe stdout if appropriate
        var child = spawn(sh, [shFlag, cmd], conf);
        if (that.customStdout) {
          child.stdout.on('data', function writeToStdout (data) {
            stdout.write(data);
          });
          child.stdout.on('error', function forwardErrorToStdout (err) {
            stdout.emit('error', err);
          });
        }
        if (that.customStderr) {
          child.stderr.on('data', function writeToStdout (data) {
            stderr.write(data);
          });
          child.stderr.on('error', function forwardErrorToStdout (err) {
            stderr.emit('error', err);
          });
        }

        // When the child exits, handle its exit code
        child.on('close', function handleChildClose (code) {
          // If the exit code was not zero, complain and leave
          if (code !== 0) {
            cb(new Error('Received non-zero exit code "' + code + '" from command "' + cmd + '"'));
          // Otherwise, mark the step as a success and continue
          } else {
            stepInfo.completed = true;
            cb(null);
          }
        });
      // Otherwise, callback shortly
      } else {
        process.nextTick(cb);
      }
    }, function handleFailure (err) {
      // If there was an error, output our progress to a file
      if (err) {
        // Output our error immediately
        // TODO: Figure out way to stack/concatenate errors instead of using `console.error`
        that.stderr.write('There was an error while executing a command\n');
        that.stderr.write(util.inspect(err));

        // Output params to disk in verbatim fashion
        var content = JSON.stringify(params, null, 2);
        Release.writeResumeFile(content, function handleOutputResumeFile (err2) {
          // If there was a secondary error, callback with it
          if (err2) {
            // TODO: Figure out way to stack/concatenate errors instead of using `console.error`
            that.stderr.write('Attempted to write `' + Release.RESUME_FILE + '` but failed\n');
            return callback(err2);
          }

          // Callback with an error about running resume
          callback(new Error('We have generated a `' + Release.RESUME_FILE + '` file. ' +
            'Once issues have been resolved, the current release can be resumed by running `foundry resume`.'));
        });
      // Otherwise, attempt to clean up resume file
      } else {
        // DEV: We don't use `stat` + `unlink` since the file could be created in that time
        fs.unlink(Release.RESUME_FILE, function handleError (err) {
          // If there was an error about the file not existing, nullify it
          if (err && err.code === 'ENOENT') {
            err = null;
          }

          // Callback with our error
          callback(err);
        });
      }
    });
  }
};

// Export Release
module.exports = Release;
<commit_msg>Added nice DEV note<commit_after>// Load in dependencies
var assert = require('assert');
var fs = require('fs');
var spawn = require('child_process').spawn;
var util = require('util');
var _ = require('underscore');
var async = require('async');
var bufferedSpawn = require('buffered-spawn');
var Chalk = require('chalk').constructor;
var deepEqual = require('deep-equal');

// Define constants for our environment variables
var FOUNDRY_VERSION_KEY = 'FOUNDRY_VERSION';
var FOUNDRY_MESSAGE_KEY = 'FOUNDRY_MESSAGE';
var FOUNDRY_VERSION_VAR = '$FOUNDRY_VERSION';
var FOUNDRY_MESSAGE_VAR = '$FOUNDRY_MESSAGE';
if (process.platform === 'win32') {
  FOUNDRY_VERSION_VAR = '%FOUNDRY_VERSION%';
  FOUNDRY_MESSAGE_VAR = '%FOUNDRY_MESSAGE%';
}

// Define a class to wrap release internals
function Release(releaseCommands, options) {
  // Assert against releaseCommands
  if (!Array.isArray(releaseCommands)) {
    throw new Error('foundry expected `releaseCommands` to be an array. Received: ' + JSON.stringify(releaseCommands));
  }

  // Upcast our releaseCommands from strings to objects
  // TODO: If these one-offs for `releaseCommand` become unwieldy, consider writing a `ReleaseCommand` class
  //   with abstractions for `updateFiles`/etc and `specVersion`
  releaseCommands = releaseCommands.map(function upcastReleaseCommand (releaseCommand) {
    if (typeof releaseCommand === 'string') {
      return {
        type: 'releaseCommand',
        command: releaseCommand
      };
    } else {
      return releaseCommand;
    }
  });

  // Validate each of our command types
  releaseCommands.forEach(function validateReleaseCommand (releaseCommand) {
    if (releaseCommand.type === 'releaseCommand') {
      assert(releaseCommand.command, 'Expected `releaseCommand.command` to be defined but it was not. ' +
        'Received: ' + JSON.stringify(releaseCommand));
    } else if (releaseCommand.type === 'customCommand') {
      // Verify any of `updateFiles`, `commit`, `register`, or `publish`
      var hasValidCommand = Release.STEPS.some(function verifyStepExists (step) {
        return releaseCommand[step];
      });
      assert(hasValidCommand, 'Expected `customCommand` to have command for `updateFiles`, `commit`, `publish`, ' +
        'or `register` but none were defined. Received: ' + JSON.stringify(releaseCommand));
    } else {
      assert.fail('Unknown `releaseCommand.type` found, expected `releaseCommand` or `customCommand`. ' +
        'Received: ' + JSON.stringify(releaseCommand));
    }
  });

  // Define commands for our release commands to have a consistent API with custom commands
  releaseCommands = releaseCommands.map(function upcastReleaseCommand (releaseCommand) {
    if (releaseCommand.type === 'releaseCommand') {
      var command = releaseCommand.command;
      return _.defaults({}, releaseCommand, {
        // Example: foundry-release-npm update-files "$FOUNDRY_VERSION" "$FOUNDRY_MESSAGE"
        // DEV: We use only string concatenation for the later parts since `shell-quote` won't work for Windows
        updateFiles: command + ' update-files "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"',
        commit: command + ' commit "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"',
        publish: command + ' publish "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"',
        register: command + ' register "' + FOUNDRY_VERSION_VAR + '" "' + FOUNDRY_MESSAGE_VAR + '"'
      });
    } else {
      return releaseCommand;
    }
  });

  // Save releaseCommands and options for later
  this.releaseCommands = releaseCommands;
  this.options = options || {};
  this.stdout = this.options.stdout || process.stdout;
  this.customStdout = !!this.options.stdout;
  this.stderr = this.options.stderr || process.stderr;
  this.customStderr = !!this.options.stderr;
  this.chalk = new Chalk({enabled: this.options.color});
}
Release.RESUME_FILE = 'foundry-resume.json';
Release.STEPS = ['updateFiles', 'commit', 'publish', 'register'];
Release.specVersion = '2.0.0';
Release.readResumeFile = function (callback) {
  fs.readFile(Release.RESUME_FILE, 'utf8', callback);
};
Release.writeResumeFile = function (content, callback) {
  fs.writeFile(Release.RESUME_FILE, content, callback);
};
Release.prototype = {
  validateSpecVersion: function (callback) {
    var releaseCommands = this.releaseCommands;
    async.map(releaseCommands, function getSpecVersion (releaseCommand, cb) {
      // If the command is a release command, get the version
      //   e.g.: foundry-release-git --spec-version
      if (releaseCommand.type === 'releaseCommand') {
        bufferedSpawn(releaseCommand.command, ['--spec-version'], function handleSpecVersion (err, stdout, stderr) {
          // If there was an error
          if (err) {
            // If the command wasn't found, generate a better error
            if (err.code === 'ENOENT') {
              return cb(new Error('Attempted to run "' + releaseCommand.command + ' --spec-version" ' +
                'but it wasn\'t found. Please verify your dependencies are installed ' +
                'and the PATH environment variables are set up properly'));
            // Otherwise if there was stderr, callback with it as our error
            } else if (stderr) {
              return cb(new Error(stderr));
            // Otherwise, callback with our error
            } else {
              return cb(err);
            }
          // Otherwise, callback with a trimmed stdout (removes any newlines)
          } else {
            return cb(null, stdout.trim());
          }
        });
      // Otherwise, assume it's foundry's version
      } else {
        process.nextTick(function replyWithFoundrySpecVersion () {
          cb(null, Release.specVersion);
        });
      }
    }, function handleSpecVersions (err, specVersions) {
      // If there was an error for any command, callback with it
      if (err) {
        return callback(err);
      }

      // Otherwise, validate our spec versions
      var i = 0;
      var len = specVersions.length;
      for (; i < len; i++) {
        // If the specVersion doesn't line up, error out with library info
        var specVersion = specVersions[i];
        if (specVersion !== Release.specVersion) {
          var releaseCommand = releaseCommands[i];
          return callback(new Error('Expected release command "' + releaseCommand.command +
            '" to have a `--spec-version` of "' + Release.specVersion + '" but it was "' + specVersion + '"'));
        }
      }

      // Callback with no error
      return callback(null);
    });
  },

  getReleaseSteps: function (params) {
    // Generate a container for our steps
    var steps = [];
    var that = this;

    // For each of step keys, add their respective steps
    function addSteps(stepKey) {
      that.releaseCommands.forEach(function addReleaseStep (releaseComand) {
        if (releaseComand[stepKey]) {
          steps.push({
            step: releaseComand[stepKey],
            completed: false
          });
        }
      });
    }
    addSteps('updateFiles');
    addSteps('commit');
    // Only run register if we are at the 'register' semver (e.g. 1.0.0)
    if (params[FOUNDRY_VERSION_KEY] === '1.0.0') {
      addSteps('register');
    }
    addSteps('publish');

    // Return our steps
    return steps;
  },

  notifyUserReleaseSteps: function (params) {
    var stdout = this.stdout;
    var chalk = this.chalk;
    stdout.write(
      'Configuring steps with ' + chalk.bold('FOUNDRY_VERSION') + ': ' + params[FOUNDRY_VERSION_KEY] + '\n');
    stdout.write(
      'Configuring steps with ' + chalk.bold('FOUNDRY_MESSAGE') + ': ' + params[FOUNDRY_MESSAGE_KEY] + '\n');
  },

  release: function (version, callback) {
    var that = this;
    var params = {
      FOUNDRY_VERSION: version,
      FOUNDRY_MESSAGE: 'Release ' + version
    };
    async.series([
      function validateSpecVersionFn (cb) {
        that.validateSpecVersion(cb);
      },
      function prepareReleaseSteps (cb) {
        params.steps = that.getReleaseSteps(params);
        process.nextTick(cb);
      },
      function notifyUserReleaseSteps (cb) {
        that.notifyUserReleaseSteps(params);
        process.nextTick(cb);
      },
      function runReleaseSteps (cb) {
        that._runReleaseSteps(params, cb);
      }
    ], callback);
  },

  resume: function (params, callback) {
    var that = this;
    async.series([
      function validateSpecVersionFn (cb) {
        that.validateSpecVersion(cb);
      },
      function validateParams (cb) {
        // If there is no version nor message, error out
        if (params[FOUNDRY_VERSION_KEY] === undefined) {
          return cb(new Error('Expected `' + FOUNDRY_VERSION_KEY + '` to be defined in `' +
            Release.RESUME_FILE + '` but it was not.'));
        }
        if (params[FOUNDRY_MESSAGE_KEY] === undefined) {
          return cb(new Error('Expected `' + FOUNDRY_MESSAGE_KEY + '` to be defined in `' +
            Release.RESUME_FILE + '` but it was not.'));
        }

        // Verify our steps line up exactly (order and properties)
        var configSteps = that.getReleaseSteps(params);
        var resumeSteps = params.steps;
        var incompleteResumeSteps = resumeSteps.map(function normalizeCompletedProperties (step) {
          step = _.clone(step);
          // DEV: We are overly protective of our properties changing to ensure the tests fail when appropriate
          if (step.hasOwnProperty('completed')) {
            step.completed = false;
          }
          return step;
        });
        if (!deepEqual(incompleteResumeSteps, configSteps)) {
          return cb(new Error(
            'Expected `foundry-resume.json` and `.foundryrc/package.json` commands to line up exactly. ' +
            'Please do not adjust `foundry` configuration nor `foundry-resume.json`. ' +
            'Otherwise, the release will be terminate in an incomplete state.'));
        }
        process.nextTick(cb);
      },
      function notifyUserReleaseSteps (cb) {
        that.notifyUserReleaseSteps(params);
        process.nextTick(cb);
      },
      function runReleaseSteps (cb) {
        that._runReleaseSteps(params, cb);
      }
    ], callback);
  },

  _runReleaseSteps: function (params, callback) {
    var that = this;
    async.eachSeries(params.steps, function _runReleaseStepFn (stepInfo, cb) {
      // Localize common step variables
      var cmd = stepInfo.step;
      var stdout = that.stdout;
      var stderr = that.stderr;
      var chalk = that.chalk;

      // If the step has already been completed, skip it
      if (stepInfo.completed) {
        stdout.write(chalk.green('Step already complete') + ': ' + cmd + '\n');
        return process.nextTick(cb);
      }

      // Log the step we are running
      stdout.write(chalk.green('Running step') + ': ' + cmd + '\n');

      // Prepare our command environment
      var cmdEnv = _.defaults(_.object([
        [FOUNDRY_VERSION_KEY, params[FOUNDRY_VERSION_KEY]],
        [FOUNDRY_MESSAGE_KEY, params[FOUNDRY_MESSAGE_KEY]]
      ]), process.env);
      // DEV: We conditionally use 'pipe' on `stdout` to allow for buffering during testing
      var stdio = [process.stdin, that.customStdout ? 'pipe' : stdout, that.customStderr ? 'pipe' : stderr];
      var conf = {stdio: stdio, env: cmdEnv};

      // Prepare the command itself
      // DEV: We use `sh` or `cmd` to support interpretting environment variables like `npm run-script`
      // https://github.com/npm/npm/blob/v3.3.6/lib/utils/lifecycle.js#L210-L225
      // DEV: `-c` means command
      var sh = 'sh';
      var shFlag = '-c';
      if (process.platform === 'win32') {
        sh = process.env.comspec || 'cmd';
        // DEV: `/d` disables AutoRun command execution
        // DEV: `/s /c` means use the following command as is
        //   https://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/cmd.mspx?mfr=true
        shFlag = '/d /s /c';
        conf.windowsVerbatimArguments = true;
      }

      // If we aren't on a dry run
      if (!that.options.dryRun) {
        // Run our command and pipe stdout if appropriate
        var child = spawn(sh, [shFlag, cmd], conf);
        if (that.customStdout) {
          child.stdout.on('data', function writeToStdout (data) {
            stdout.write(data);
          });
          child.stdout.on('error', function forwardErrorToStdout (err) {
            stdout.emit('error', err);
          });
        }
        if (that.customStderr) {
          child.stderr.on('data', function writeToStdout (data) {
            stderr.write(data);
          });
          child.stderr.on('error', function forwardErrorToStdout (err) {
            stderr.emit('error', err);
          });
        }

        // When the child exits, handle its exit code
        child.on('close', function handleChildClose (code) {
          // If the exit code was not zero, complain and leave
          if (code !== 0) {
            cb(new Error('Received non-zero exit code "' + code + '" from command "' + cmd + '"'));
          // Otherwise, mark the step as a success and continue
          } else {
            stepInfo.completed = true;
            cb(null);
          }
        });
      // Otherwise, callback shortly
      } else {
        process.nextTick(cb);
      }
    }, function handleFailure (err) {
      // If there was an error, output our progress to a file
      if (err) {
        // Output our error immediately
        // TODO: Figure out way to stack/concatenate errors instead of using `console.error`
        that.stderr.write('There was an error while executing a command\n');
        that.stderr.write(util.inspect(err));

        // Output params to disk in verbatim fashion
        var content = JSON.stringify(params, null, 2);
        Release.writeResumeFile(content, function handleOutputResumeFile (err2) {
          // If there was a secondary error, callback with it
          if (err2) {
            // TODO: Figure out way to stack/concatenate errors instead of using `console.error`
            that.stderr.write('Attempted to write `' + Release.RESUME_FILE + '` but failed\n');
            return callback(err2);
          }

          // Callback with an error about running resume
          callback(new Error('We have generated a `' + Release.RESUME_FILE + '` file. ' +
            'Once issues have been resolved, the current release can be resumed by running `foundry resume`.'));
        });
      // Otherwise, attempt to clean up resume file
      // DEV: This also covers the scenario where a release fails and then someone re-runs `release`
      } else {
        // DEV: We don't use `stat` + `unlink` since the file could be created in that time
        fs.unlink(Release.RESUME_FILE, function handleError (err) {
          // If there was an error about the file not existing, nullify it
          if (err && err.code === 'ENOENT') {
            err = null;
          }

          // Callback with our error
          callback(err);
        });
      }
    });
  }
};

// Export Release
module.exports = Release;
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */
var qs = require('querystring');
var hyperquest = require('hyperquest');

module.exports = {
  get: function(url, callback) {
    var req = hyperquest.get(url);
    resolveRequest(req, callback);
    return req;
  },

  post: function(url, data, callback) {
    var req = hyperquest.post(url);
    var buf = new Buffer(qs.stringify(data));

    req.setHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
    req.setHeader("Content-Length", buf.length);
    req.end(buf);

    resolveRequest(req, callback);
    return req;
  }
};

/**
 * Streams a stream value into a Buffer
 *
 * @param {Object} stream Readable stream
 * @param {Function} callback Callback function with (err, data)
 */
function resolveRequest(stream, callback) {
  var responded = false;
  var chunks = [];
  var chunkLen = 0;

  stream.on('error', function(err) {
    if (responded) {
      return;
    }

    responded = true;
    callback(err);
  });

  stream.on('data', function(chunk) {
    if (chunk && chunk.length) {
      chunks.push(chunk);
      chunkLen += chunk.length;
    }
  });

  stream.on('end', function() {
    if (responded) {
      return;
    }
    responded = true;

    var data;

    try {
      data = Buffer.concat(chunks, chunkLen);
    } catch (e) {
      return callback(e);
    }

    callback(null, data);
  });
}
<commit_msg>parse response data to JSON object<commit_after>/**
 * Module dependencies
 */
var qs = require('querystring');
var hyperquest = require('hyperquest');

module.exports = {
  get: function(url, callback) {
    var req = hyperquest.get(url);
    resolveRequest(req, callback);
    return req;
  },

  post: function(url, data, callback) {
    var req = hyperquest.post(url);
    var buf = new Buffer(qs.stringify(data));

    req.setHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
    req.setHeader("Content-Length", buf.length);
    req.end(buf);

    resolveRequest(req, callback);
    return req;
  }
};

/**
 * Streams a stream value into a Buffer
 *
 * @param {Object} stream Readable stream
 * @param {Function} callback Callback function with (err, data)
 */
function resolveRequest(stream, callback) {
  var responded = false;
  var chunks = [];
  var chunkLen = 0;

  stream.on('error', function(err) {
    if (responded) {
      return;
    }

    responded = true;
    callback(err);
  });

  stream.on('data', function(chunk) {
    if (chunk && chunk.length) {
      chunks.push(chunk);
      chunkLen += chunk.length;
    }
  });

  stream.on('end', function() {
    if (responded) {
      return;
    }
    responded = true;

    var data;

    try {
      data = JSON.parse(Buffer.concat(chunks, chunkLen));
    } catch (e) {
      return callback(e);
    }

    callback(null, data);
  });
}
<|endoftext|>


<commit_before>var https = require("https");
var url = require("url");
var userAgent = "Node GitHub Request " + require( "../package" ).version;

function extend(a, b) {
	for (var prop in b) {
		a[prop] = b[prop];
	}

	return a;
}

function xHeader(str) {
	if (str.substring(0, 2) === "x-" ) {
		str = str.substring(2);
	}

	return str.replace(/-([a-z])/g, function(all, letter) {
		return letter.toUpperCase();
	});
}

function request(settings, data, callback) {
	if (typeof data === "function") {
		callback = data;
		data = null;
	} else {
		data = JSON.stringify(data);
	}
	callback = callback || function() {};

	settings = extend({
		method: "GET",
		headers: extend({
			"user-agent": userAgent,
			"content-length": typeof data === "string" ? data.length : 0
		}, settings.headers || {})
	}, settings);

	var req = https.request(extend({
		host: "api.github.com"
	}, settings), function(res) {
		var meta = {};
		Object.keys(res.headers).forEach(function(header) {
			if (/^(x-(ratelimit|github))/.test(header)) {
				meta[xHeader(header)] = res.headers[header];
			} else if (header === "link") {
				var links = res.headers.link.split(/,\s*/);
				meta.links = {};
				links.forEach(function(link) {
					var parts = /<([^>]+)>;\s*rel="([^"]+)"/.exec(link);
					meta.links[parts[2]] = parts[1];
				});
			}
		});

		var response = "";
		res.setEncoding("utf8");
		res.on("data", function(chunk) {
			response += chunk;
		});

		res.on("end", function() {
			if (res.statusCode >= 400) {
				var message;
				if (res.headers["content-type"].indexOf("json") !== -1) {
					message = JSON.parse(response).message;
				} else {
					message = response;
				}
				if (!message && res.statusCode === 403) {
					message = "Forbidden";
				}
				callback(new Error(message));
			} else {
				callback(null, JSON.parse(response), meta);
			}
		});
	});

	if (data) {
		req.write(data);
	}

	req.end();
}

function requestAll(settings, callback) {
	request(settings, function(error, data, meta) {
		if (error) {
			return callback(error);
		}

		if (!meta.links || !meta.links.next) {
			return callback(null, data, meta);
		}

		settings.path = url.parse(meta.links.next).path;
		requestAll(settings, function(error, nextData, nextMeta) {
			if (error) {
				return callback(error);
			}

			callback(null, data.concat(nextData), nextMeta);
		});
	});
}

module.exports = {
	request: request,
	requestAll: requestAll
};
<commit_msg>Fix merging of headers<commit_after>var https = require("https");
var url = require("url");
var userAgent = "Node GitHub Request " + require( "../package" ).version;

function extend(a, b) {
	for (var prop in b) {
		a[prop] = b[prop];
	}

	return a;
}

function xHeader(str) {
	if (str.substring(0, 2) === "x-" ) {
		str = str.substring(2);
	}

	return str.replace(/-([a-z])/g, function(all, letter) {
		return letter.toUpperCase();
	});
}

function request(settings, data, callback) {
	if (typeof data === "function") {
		callback = data;
		data = null;
	} else {
		data = JSON.stringify(data);
	}
	callback = callback || function() {};

	settings = extend({
		method: "GET"
	}, settings);
	settings.headers = extend({
		"user-agent": userAgent,
		"content-length": typeof data === "string" ? data.length : 0
	}, settings.headers || {});

	var req = https.request(extend({
		host: "api.github.com"
	}, settings), function(res) {
		var meta = {};
		Object.keys(res.headers).forEach(function(header) {
			if (/^(x-(ratelimit|github))/.test(header)) {
				meta[xHeader(header)] = res.headers[header];
			} else if (header === "link") {
				var links = res.headers.link.split(/,\s*/);
				meta.links = {};
				links.forEach(function(link) {
					var parts = /<([^>]+)>;\s*rel="([^"]+)"/.exec(link);
					meta.links[parts[2]] = parts[1];
				});
			}
		});

		var response = "";
		res.setEncoding("utf8");
		res.on("data", function(chunk) {
			response += chunk;
		});

		res.on("end", function() {
			if (res.statusCode >= 400) {
				var message;
				if (res.headers["content-type"].indexOf("json") !== -1) {
					message = JSON.parse(response).message;
				} else {
					message = response;
				}
				if (!message && res.statusCode === 403) {
					message = "Forbidden";
				}
				callback(new Error(message));
			} else {
				callback(null, JSON.parse(response), meta);
			}
		});
	});

	if (data) {
		req.write(data);
	}

	req.end();
}

function requestAll(settings, callback) {
	request(settings, function(error, data, meta) {
		if (error) {
			return callback(error);
		}

		if (!meta.links || !meta.links.next) {
			return callback(null, data, meta);
		}

		settings.path = url.parse(meta.links.next).path;
		requestAll(settings, function(error, nextData, nextMeta) {
			if (error) {
				return callback(error);
			}

			callback(null, data.concat(nextData), nextMeta);
		});
	});
}

module.exports = {
	request: request,
	requestAll: requestAll
};
<|endoftext|>


<commit_before>/*
 * min-webdriver
 *
 * Copyright (c) 2014 Maximilian Antoni <mail@maxantoni.de>
 *
 * @license MIT
 */
'use strict';

var http = require('http');

function indent(string) {
  return string.replace(/^/gm, '    ');
}

function fail(options, message, body, callback) {
  process.stderr.write(options.method);
  process.stderr.write(' ');
  process.stderr.write(options.path);
  process.stderr.write('\n\n');
  process.stderr.write(message);
  if (body) {
    process.stderr.write('\n');
    process.stderr.write(indent(body.replace(/^\s+$/gm, '')));
  }
  process.stderr.write('\n\n');
  callback(new Error(message));
}

function request(context, method, path, json, callback) {
  var payload = json ? JSON.stringify(json) : null;
  var options = {
    hostname           : context.hostname,
    port               : context.port,
    path               : context.basePath + path,
    method             : method,
    headers            : {
      'Connection'     : 'keep-alive',
      'Accept'         : 'application/json;charset=utf-8',
      'Content-Type'   : 'application/json;charset=utf-8',
      'Content-Length' : payload ? Buffer.byteLength(payload) : 0
    }
  };

  var req = http.request(options, function (res) {

    var body = '';
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
      body += chunk;
    });
    res.on('end', function () {
      if (res.statusCode < 200 || res.status >= 300) {
        fail(options, 'Unexpected HTTP status: ' + res.statusCode, body,
            callback);
      } else {
        if (body) {
          var parsed = JSON.parse(body);
          if (parsed.status) {
            fail(options, 'Unexpected response status: ' + parsed.status,
                parsed.value.message, callback);
          } else {
            callback(null, parsed);
          }
        } else {
          callback(null);
        }
      }
    });

  });

  req.on('error', function (e) {
    fail(options, 'Unexcected request error: ' + e.message, e.stack, callback);
  });

  if (payload) {
    req.write(payload);
  }
  req.end();
}

module.exports = request;
<commit_msg>Handle redirects in session requests<commit_after>/*
 * min-webdriver
 *
 * Copyright (c) 2014 Maximilian Antoni <mail@maxantoni.de>
 *
 * @license MIT
 */
'use strict';

var http = require('http');

var contentType = 'application/json;charset=utf-8';

function indent(string) {
  return string.replace(/^/gm, '    ');
}

function fail(options, message, headers, body, callback) {
  process.stderr.write(options.method);
  process.stderr.write(' ');
  process.stderr.write(options.path);
  process.stderr.write('\n\n');
  process.stderr.write(message);
  if (headers) {
    process.stderr.write('\n');
    Object.keys(headers).forEach(function (header) {
      process.stderr.write('\n' + header + ': ' + headers[header]);
    });
    process.stderr.write('\n');
  }
  if (body) {
    process.stderr.write('\n');
    process.stderr.write(indent(body.replace(/^\s+$/gm, '')));
    process.stderr.write('\n');
  }
  process.stderr.write('\n');
  callback(new Error(message));
}

function request(context, method, path, json, callback) {
  var payload = json ? JSON.stringify(json) : null;
  var options = {
    hostname           : context.hostname,
    port               : context.port,
    path               : context.basePath + path,
    method             : method,
    headers            : {
      'Connection'     : 'keep-alive',
      'Accept'         : contentType,
      'Content-Type'   : contentType,
      'Content-Length' : payload ? Buffer.byteLength(payload) : 0
    }
  };

  var req = http.request(options, function (res) {

    var body = '';
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
      body += chunk;
    });
    res.on('end', function () {
      if ((res.statusCode === 302 || res.statusCode === 303)
          && path === '/session') {
        var sessionId = res.headers.location;
        sessionId = sessionId.substring(sessionId.lastIndexOf('/') + 1);
        callback(null, {
          sessionId : sessionId
        });
        return;
      }
      if (res.statusCode < 200 || res.statusCode >= 300) {
        fail(options, 'Unexpected HTTP status: ' + res.statusCode + ' '
            + http.STATUS_CODES[res.statusCode], res.headers, body, callback);
        return;
      }
      if (body) {
        var parsed;
        try {
          parsed = JSON.parse(body);
        } catch (e) {
          fail(options, 'Unexpected response:', null, body, callback);
          return;
        }
        if (parsed.status) {
          fail(options, 'Unexpected response status: ' + parsed.status,
              null, parsed.value.message, callback);
        } else {
          callback(null, parsed);
        }
      } else {
        callback(null);
      }
    });

  });

  req.on('error', function (e) {
    fail(options, 'Unexcected request error: ' + e.message, null, e.stack,
        callback);
  });

  if (payload) {
    req.write(payload);
  }
  req.end();
}

module.exports = request;
<|endoftext|>


<commit_before>'use strict';

const EventEmitter = require('events').EventEmitter;

const uuid = require('uuid');
const debug = require('debug')('sequelize-msnodesqlv8');

class Request extends EventEmitter {
	constructor(sql, callback) {
		super();

		this.uuid = uuid.v4();
		this.sql = sql;
		this.callback = callback;

		debug(`creating request (${ this.uuid }): ${ this.sql.length > 80 ? this.sql.slice(0, 80) + '...' : this.sql }`);
	}

	execute(context) {
		let metadata = null;
		let rowBuffer = null;
		let done = false;
		debug(`connection (${ context.uuid }): executing request (${ this.uuid })`);
		context.requests.push(this);
		try {
			let request = context.connection.queryRaw(this.sql, (err, results) => {
				if (err) {
					// HACK: Close connection because error may have put connection in invalid state.
					context.removeRequest(this, err);
					context.close();
				} else if (done) {
					context.removeRequest(this);
					if (typeof this.callback === 'function') {
						this.callback(err, results);
					}
				}
			});
			request.on('meta', (meta) => {
				metadata = meta;
			});
			request.on('row', () => {
				if (rowBuffer) {
					this.emit('row', rowBuffer);
				}
				rowBuffer = [];
			});
			request.on('column', (index, data) => {
				let columnMetadata = metadata[index];
				let existing = rowBuffer[index];

				if (existing && existing.metadata.colName === columnMetadata.name) {
					if (typeof existing.value === 'string') {
						existing.value += data;
						return;
					} else if (existing.value instanceof Buffer) {
						existing.value = Buffer.concat([existing.value, data]);
						return;
					}
				}

				rowBuffer[index] = {
					metadata: {
						colName: columnMetadata.name,
						type: {
							id: columnMetadata.sqlType
						},
						nullable: columnMetadata.nullable,
						size: columnMetadata.size
					},
					value: data
				};
			});
			request.on('done', () => {
				done = true;
				if (rowBuffer) {
					this.emit('row', rowBuffer);
				}
			});
		} catch (err) {
			context.removeRequest(this, err);
			context.close();
		}
	}
}

module.exports = Request;
<commit_msg>request: Remove error handling hack<commit_after>'use strict';

const EventEmitter = require('events').EventEmitter;

const uuid = require('uuid');
const debug = require('debug')('sequelize-msnodesqlv8');

class Request extends EventEmitter {
	constructor(sql, callback) {
		super();

		this.uuid = uuid.v4();
		this.sql = sql;
		this.callback = callback;

		debug(`creating request (${ this.uuid }): ${ this.sql.length > 80 ? this.sql.slice(0, 80) + '...' : this.sql }`);
	}

	execute(context) {
		let metadata = null;
		let rowBuffer = null;
		let done = false;
		debug(`connection (${ context.uuid }): executing request (${ this.uuid })`);
		context.requests.push(this);
		try {
			let request = context.connection.queryRaw(this.sql, (err, results) => {
				if (err) {
					context.removeRequest(this, err);
				} else if (done) {
					context.removeRequest(this);
					if (typeof this.callback === 'function') {
						this.callback(err, results);
					}
				}
			});
			request.on('meta', (meta) => {
				metadata = meta;
			});
			request.on('row', () => {
				if (rowBuffer) {
					this.emit('row', rowBuffer);
				}
				rowBuffer = [];
			});
			request.on('column', (index, data) => {
				let columnMetadata = metadata[index];
				let existing = rowBuffer[index];

				if (existing && existing.metadata.colName === columnMetadata.name) {
					if (typeof existing.value === 'string') {
						existing.value += data;
						return;
					} else if (existing.value instanceof Buffer) {
						existing.value = Buffer.concat([existing.value, data]);
						return;
					}
				}

				rowBuffer[index] = {
					metadata: {
						colName: columnMetadata.name,
						type: {
							id: columnMetadata.sqlType
						},
						nullable: columnMetadata.nullable,
						size: columnMetadata.size
					},
					value: data
				};
			});
			request.on('done', () => {
				done = true;
				if (rowBuffer) {
					this.emit('row', rowBuffer);
				}
			});
		} catch (err) {
			context.removeRequest(this, err);
			context.close();
		}
	}
}

module.exports = Request;
<|endoftext|>