<commit_before>var parseBuildErrors     = require('./parseBuildErrors');
var linkNodeModules      = require('./linkNodeModules');
var Promise              = require('es6-promise').Promise;
var chalk                = require('chalk');
var spawn                = require('child_process').spawn;
var tools                = require('../tools');
var path                 = require('path');
var logs                 = require('../logs');
var fs                   = require('fs');
var utils                = require('../utils');

var memoize = {};

module.exports = function Build (options) {
  "use strict";
  options = options || {};

  var pathToApp = options.pathToApp || path.resolve('.');
  var timeout   = options.timeout   || 120000;
  var verbose   = options.verbose !== undefined ? !!options.verbose : false;

  if (logs.isSilentBuild()) {
    // the global settings get precedence here
    verbose = false;
  }
  
  var pathToSmartJson = path.join(pathToApp, 'smart.json');
  var pathToMain      = path.join(pathToApp, '.meteor', 'local', 'build', 'main.js');
  var pathToMain2     = path.join(pathToApp, '.gagarin', 'local', 'bundle', 'main.js');
  var skipBuild       = !!options.skipBuild;

  this.start = function start () {

    // TODO: in the future, we will also want to cache
    //       w/r/t build options (e.g. production/debug)

    if (memoize[pathToApp]) {
      return memoize[pathToApp];
    }

    memoize[pathToApp] = new Promise(function (resolve, reject) {

      checkIfMeteorIsRunning(pathToApp).then(function (isRunning) {

        if (isRunning) {
          if (!fs.existsSync(pathToMain)) {
            throw new Error("Even though meteor seems to be running, the file " +
               "'.meteor/local/build/main.js' does not exist. Either, there is a stale mongod process, " +
                "or you just need to remove '.meteor/local/db/mongo.lock' manually.");
          }
          logs.system('using ' + pathToMain);
          return pathToMain
        }

        if (skipBuild) {
          // first, try using the previous build ...
          if (fs.existsSync(pathToMain2)) {
            logs.system('using ' + pathToMain2);
            return pathToMain2;
          } else { // as a fallback solution try using main.js from develop mode
            if (fs.existsSync(pathToMain)) {
              logs.system('using ' + pathToMain);
              return pathToMain;
            }
            throw new Error('There is no build available, so you cannot "skip build".');
          }
        }

        return smartJsonWarning(pathToApp).then(function () {
          // finally run the builder ...

          logs.system('running meteor build at ' + pathToApp);

          return ensureGagarinVersionsMatch(pathToApp, verbose).then(function () {

            return BuildPromise({
              pathToApp : pathToApp,
              verbose   : verbose,
              timeout   : timeout
            });

          });

        });

      }).then(resolve, reject);

    });

    return memoize[pathToApp];

  }; // start
};

// PRIVATE BUILD PROMISE IMPLEMENTATION

function BuildPromise(options) {
  "use strict";

  options = options || {};

  var pathToApp = options.pathToApp || path.resolve('.');
  var mongoUrl  = options.mongoUrl  || "http://localhost:27017";
  var timeout   = options.timeout   || 120000;
  var verbose   = options.verbose !== undefined ? !!options.verbose : false;

  var pathToMain  = path.join(pathToApp, '.gagarin', 'local', 'bundle', 'main.js');
  var pathToLocal = path.join(pathToApp, '.gagarin', 'local');

  var env = Object.create(process.env);

  return tools.getReleaseVersion(pathToApp).then(function (version) { return new Promise(function (resolve, reject) {

    var args;

    logs.system("detected METEOR@" + version);

    if (version >= '1.0.0') {
      args = [ 'build', '--debug', '--directory', pathToLocal ];
    } else {
      args = [ 'bundle', '--debug', '--directory', path.join(pathToLocal, 'bundle') ];
    }

    logs.system("spawning meteor process with the following args");
    logs.system(JSON.stringify(args));

    var buildTimeout = null;

    var meteorBinary = tools.getMeteorBinary();
    var meteor = spawn(meteorBinary, args, {
      cwd: pathToApp, env: env, stdio: verbose ? 'inherit' : 'ignore'
    });

    var output = "";

    meteor.on('exit', function onExit (code) {

      if (code !== 0) {
        return reject(new Error('meteor build exited with code ' + code));
      }

      /*
      var err = parseBuildErrors(output);

      if (err) {
        return reject(err);
      }
      */

      logs.system('linking node_modules');

      linkNodeModules(pathToApp).then(function () {

        logs.system('everything is fine');

        resolve(pathToMain);
      }).catch(reject);

      clearTimeout(buildTimeout);

    });

    //-----------------------------------------------
    /*<commit_msg>Allow exit code to be null<commit_after>var parseBuildErrors     = require('./parseBuildErrors');
var linkNodeModules      = require('./linkNodeModules');
var Promise              = require('es6-promise').Promise;
var chalk                = require('chalk');
var spawn                = require('child_process').spawn;
var tools                = require('../tools');
var path                 = require('path');
var logs                 = require('../logs');
var fs                   = require('fs');
var utils                = require('../utils');

var memoize = {};

module.exports = function Build (options) {
  "use strict";
  options = options || {};

  var pathToApp = options.pathToApp || path.resolve('.');
  var timeout   = options.timeout   || 120000;
  var verbose   = options.verbose !== undefined ? !!options.verbose : false;

  if (logs.isSilentBuild()) {
    // the global settings get precedence here
    verbose = false;
  }

  var pathToSmartJson = path.join(pathToApp, 'smart.json');
  var pathToMain      = path.join(pathToApp, '.meteor', 'local', 'build', 'main.js');
  var pathToMain2     = path.join(pathToApp, '.gagarin', 'local', 'bundle', 'main.js');
  var skipBuild       = !!options.skipBuild;

  this.start = function start () {

    // TODO: in the future, we will also want to cache
    //       w/r/t build options (e.g. production/debug)

    if (memoize[pathToApp]) {
      return memoize[pathToApp];
    }

    memoize[pathToApp] = new Promise(function (resolve, reject) {

      checkIfMeteorIsRunning(pathToApp).then(function (isRunning) {

        if (isRunning) {
          if (!fs.existsSync(pathToMain)) {
            throw new Error("Even though meteor seems to be running, the file " +
               "'.meteor/local/build/main.js' does not exist. Either, there is a stale mongod process, " +
                "or you just need to remove '.meteor/local/db/mongo.lock' manually.");
          }
          logs.system('using ' + pathToMain);
          return pathToMain
        }

        if (skipBuild) {
          // first, try using the previous build ...
          if (fs.existsSync(pathToMain2)) {
            logs.system('using ' + pathToMain2);
            return pathToMain2;
          } else { // as a fallback solution try using main.js from develop mode
            if (fs.existsSync(pathToMain)) {
              logs.system('using ' + pathToMain);
              return pathToMain;
            }
            throw new Error('There is no build available, so you cannot "skip build".');
          }
        }

        return smartJsonWarning(pathToApp).then(function () {
          // finally run the builder ...

          logs.system('running meteor build at ' + pathToApp);

          return ensureGagarinVersionsMatch(pathToApp, verbose).then(function () {

            return BuildPromise({
              pathToApp : pathToApp,
              verbose   : verbose,
              timeout   : timeout
            });

          });

        });

      }).then(resolve, reject);

    });

    return memoize[pathToApp];

  }; // start
};

// PRIVATE BUILD PROMISE IMPLEMENTATION

function BuildPromise(options) {
  "use strict";

  options = options || {};

  var pathToApp = options.pathToApp || path.resolve('.');
  var mongoUrl  = options.mongoUrl  || "http://localhost:27017";
  var timeout   = options.timeout   || 120000;
  var verbose   = options.verbose !== undefined ? !!options.verbose : false;

  var pathToMain  = path.join(pathToApp, '.gagarin', 'local', 'bundle', 'main.js');
  var pathToLocal = path.join(pathToApp, '.gagarin', 'local');

  var env = Object.create(process.env);

  return tools.getReleaseVersion(pathToApp).then(function (version) { return new Promise(function (resolve, reject) {

    var args;

    logs.system("detected METEOR@" + version);

    if (version >= '1.0.0') {
      args = [ 'build', '--debug', '--directory', pathToLocal ];
    } else {
      args = [ 'bundle', '--debug', '--directory', path.join(pathToLocal, 'bundle') ];
    }

    logs.system("spawning meteor process with the following args");
    logs.system(JSON.stringify(args));

    var buildTimeout = null;

    var meteorBinary = tools.getMeteorBinary();
    var meteor = spawn(meteorBinary, args, {
      cwd: pathToApp, env: env, stdio: verbose ? 'inherit' : 'ignore'
    });

    var output = "";

    meteor.on('exit', function onExit (code) {

      if (code !== 0 && code !== null) {
        return reject(new Error('meteor build exited with code ' + code));
      }

      /*
      var err = parseBuildErrors(output);

      if (err) {
        return reject(err);
      }
      */

      logs.system('linking node_modules');

      linkNodeModules(pathToApp).then(function () {

        logs.system('everything is fine');

        resolve(pathToMain);
      }).catch(reject);

      clearTimeout(buildTimeout);

    });

    //-----------------------------------------------
    /*
{'fraction_non_alphanumeric': 0.14716024340770792, 'fraction_numerical': 0.005273833671399594, 'mean_word_length': 2.199545749513303, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2314691', 'n_tokens_mistral': 2955, 'n_tokens_neox': 2775, 'n_words': 713}