<commit_before>'use strict';

var url          = require('url');
var path         = require('path');
var http         = require('http');
var fs           = require('fs');
var unzip        = require('unzip');
var postgresdb   = require('pg');
var ip           = require("ip");
var useOracle    = false;
var program      = require('commander');
var drivers      = new Object();
var connections  = new Object();
var express      = require('express')
var app          = express()
var timeout      = 0;
var init_drivers = false;
var port;
var hostaddress;
var typeOfSystem;
var centralHostAddress;
var centralHostPort;
var request      = require("request");

path.join(__dirname, '../public/blockly/blockly_compressed.js')
path.join(__dirname, '../public/blockly/blocks_compressed.js')
path.join(__dirname, '../public/yazz_blockly_blocks.js')
path.join(__dirname, '../public/yazz_blockly_generator.js')
path.join(__dirname, '../public/yazz_blockly_output_code.js')
path.join(__dirname, '../public/blockly/msg/js/en.js')
path.join(__dirname, '../public/jquery-1.9.1.min.js')
path.join(__dirname, '../public/jquery.zoomooz.js')
path.join(__dirname, '../public/blockly_helper.js')
path.join(__dirname, '../public/blockly.png')
path.join(__dirname, '../public/polyfill.min.js')
path.join(__dirname, '../src/oracle.js')
path.join(__dirname, '../src/postgres.js')
path.join(__dirname, '../public/blockly_setup.js')
path.join(__dirname, '../public/tether.min.js')
path.join(__dirname, '../public/bootstrap.min.js')
path.join(__dirname, '../public/bootstrap.min.css')
path.join(__dirname, '../public/es6-shim.js')
path.join(__dirname, '../public/vue_app.css')
path.join(__dirname, '../public/dist/build.js')
path.join(__dirname, '../oracle_driver.zip')

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

program
  .version('0.0.1')
  .option('-t, --type [type]', 'Add the specified type of app [type]', 'client')
  .option('-p, --port [port]', 'Which port should I listen on? [port]', parseInt)
  .option('-h, --host [host]', 'Server address of the central host [host]', 'yazz.com')
  .option('-s, --hostport [hostport]', 'Server port of the central host [hostport]', parseInt)
  .parse(process.argv);

  port = program.port;
  if (!isNumber(port)) {port = 80;};
  typeOfSystem = program.type;
  centralHostAddress = program.host;
  centralHostPort = program.hostport;
  if (!isNumber(centralHostPort)) {centralHostPort = 80;};

  if (!(typeOfSystem == 'client' || typeOfSystem == 'server')) {
      console.log('-------* Invalid system type: ' + typeOfSystem);
      process.exit();
  };
  console.log('-------* System type: ' + typeOfSystem);
  console.log('-------* Port: ' + port);
  console.log('-------* Central host: ' + centralHostAddress);
  console.log('-------* Central host port: ' + centralHostPort);

console.dir ( ip.address() );

console.log('addr: '+ ip.address());
hostaddress = ip.address();

//------------------------------------------------------------
// copy the oracle files if they exist
//------------------------------------------------------------
if (fs.existsSync(path.join(__dirname, '../oracle_driver.zip'))) {
    useOracle = true;
}
if (useOracle) {
    if (!fs.existsSync(process.cwd() + '\\oracle_driver\\instantclient32')) {
      fs.createReadStream(path.join(__dirname, '../oracle_driver.zip')).pipe(unzip.Extract({ path: process.cwd() + '\\.' }));
      timeout = 3000;
      console.log('Creating oracle_driver');
    } else {
      console.log('oracle_driver already exists');
    };
}
var toeval = fs.readFileSync(path.join(__dirname, './oracle.js')).toString();
if (useOracle) {
    process.env['PATH'] = process.cwd() + '\\oracle_driver\\instantclient32' + ';' + process.env['PATH'];
}

//------------------------------------------------------------
// postgres
//------------------------------------------------------------
var pgeval = fs.readFileSync(path.join(__dirname, './postgres.js')).toString();

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
setTimeout(startYazz, timeout);
console.log('Creating timeout: ' + timeout);

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
function startYazz() {
  //
  // start the server
  //
  var Gun = require('gun');
  var gun = Gun({
    file: 'data.json',
    s3: {
      key: '', // AWS Access Key
      secret: '', // AWS Secret Token
      bucket: '' // The bucket you want to save into
    }
  });

  gun.wsp(app);

  console.log(typeOfSystem + ' started on port ' + port + ' with /gun');

  app.get('/', function (req, res) {
      if (!init_drivers) {
        init_drivers = true;
        if (useOracle) {
             eval(toeval);
        }
        eval(pgeval);

      };

      if (typeOfSystem == 'client') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index.html')));
      }
      if (typeOfSystem == 'server') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index_server.html')));
      }
  })

app.use(express.static(path.join(__dirname, '../public/')))

  app.get('/getresult', function (req, res) {
    var queryData = url.parse(req.url, true).query;
    //console.log('request received: ' + queryData.sql);
    if (connections[queryData.source]) {
        //console.log('query driver: ' + connections[queryData.source].driver);
        drivers[connections[queryData.source].driver]['get'](connections[queryData.source],queryData.sql,function(ordata) {
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end(JSON.stringify(ordata));
        });
    } else {
        console.log('query driver not found: ' + connections[queryData.source]);
    };
})

var requestClientInternalHostAddress = '';
var requestClientInternalPort        = -1;
var requestClientPublicIp            = '';
var requestClientPublicHostName      = '';

//------------------------------------------------------------------------------
// This is called by the central server to get the details of the last
// client that connected tp the central server
//------------------------------------------------------------------------------
app.get('/get_connect', function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(
            JSON.stringify(
                {
                    requestClientInternalHostAddress: requestClientInternalHostAddress
                    ,
                    requestClientInternalPort:        requestClientInternalPort
                    ,
                    requestClientPublicIp:            requestClientPublicIp
                    ,
                    requestClientPublicHostName:      requestClientPublicHostName
                    ,
                    version:      2
                }
          ));
})

//app.enable('trust proxy')

//------------------------------------------------------------------------------
// This is where the client sends its details to the central server
//------------------------------------------------------------------------------
app.get('/client_connect', function (req, res) {
    var queryData = url.parse(req.url, true).query;

    requestClientInternalHostAddress = req.query.requestClientInternalHostAddress;
    requestClientInternalPort        = req.query.requestClientInternalPort;
    requestClientPublicIp            = req.ip;
    //requestClientPublicHostName      = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    requestClientPublicHostName      = req.connection.remoteAddress;

    console.log('Client attempting to connect from:');
    console.log('client internal host address:    ' + requestClientInternalHostAddress)
    console.log('client internal port:            ' + requestClientInternalPort)
    console.log('client public IP address:        ' + requestClientPublicIp)
    console.log('client public IP host name:      ' + requestClientPublicHostName)

})

app.listen(port, hostaddress, function () {
    console.log('Example app listening on port ' + port + '!')
})

  //
  // open the app in a web browser
  //
  //console.log('Ran postgres too');

  var open = require('open');

  open('http://' + hostaddress  + ":" + port);

  //process.env['PATH'] = path.join(__dirname, '/instantclient') + ';' + process.env['PATH'];
  //var oracledb = require('oracledb');
  //console.log('Start oracle');

  //eval("oracledb= require('oracledb');");

  console.log('addr: '+ hostaddress + ":" + port);

  //console.log(toeval);
  //setTimeout(function(){eval(toeval)},1000);

  //  console.log('Done.');

  console.log("*********** CHECKING CONNECTIONS *****************8");
  var connectionrows        = new Object();
  gun.get("connections").on().map(function(a,b){
    delete a["_"];
    if (!connectionrows[a.id]) {
      //data_connections_list.push(a);
      connectionrows[a.id] = a;
      //console.log(a);
      connections[a.id] = a;
    }

  },true);

    if (typeOfSystem == 'client') {
        var urlToConnectTo = "http://" + centralHostAddress + ":" + centralHostPort + '/client_connect';
        console.log('-------* urlToConnectTo: ' + urlToConnectTo);
        console.log('trying to connect to central server...');
        request({
              uri: urlToConnectTo,
              method: "GET",
              timeout: 10000,
              followRedirect: true,
              maxRedirects: 10,
              qs: {
                  requestClientInternalHostAddress: hostaddress
                  ,
                  requestClientInternalPort:        port
              }
            },
            function(error, response, body) {
                console.log(body);
            });
    }

}
<commit_msg>try hostname<commit_after>'use strict';

var url          = require('url');
var path         = require('path');
var http         = require('http');
var fs           = require('fs');
var unzip        = require('unzip');
var postgresdb   = require('pg');
var ip           = require("ip");
var useOracle    = false;
var program      = require('commander');
var drivers      = new Object();
var connections  = new Object();
var express      = require('express')
var app          = express()
var timeout      = 0;
var init_drivers = false;
var port;
var hostaddress;
var typeOfSystem;
var centralHostAddress;
var centralHostPort;
var request      = require("request");

path.join(__dirname, '../public/blockly/blockly_compressed.js')
path.join(__dirname, '../public/blockly/blocks_compressed.js')
path.join(__dirname, '../public/yazz_blockly_blocks.js')
path.join(__dirname, '../public/yazz_blockly_generator.js')
path.join(__dirname, '../public/yazz_blockly_output_code.js')
path.join(__dirname, '../public/blockly/msg/js/en.js')
path.join(__dirname, '../public/jquery-1.9.1.min.js')
path.join(__dirname, '../public/jquery.zoomooz.js')
path.join(__dirname, '../public/blockly_helper.js')
path.join(__dirname, '../public/blockly.png')
path.join(__dirname, '../public/polyfill.min.js')
path.join(__dirname, '../src/oracle.js')
path.join(__dirname, '../src/postgres.js')
path.join(__dirname, '../public/blockly_setup.js')
path.join(__dirname, '../public/tether.min.js')
path.join(__dirname, '../public/bootstrap.min.js')
path.join(__dirname, '../public/bootstrap.min.css')
path.join(__dirname, '../public/es6-shim.js')
path.join(__dirname, '../public/vue_app.css')
path.join(__dirname, '../public/dist/build.js')
path.join(__dirname, '../oracle_driver.zip')

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

program
  .version('0.0.1')
  .option('-t, --type [type]', 'Add the specified type of app [type]', 'client')
  .option('-p, --port [port]', 'Which port should I listen on? [port]', parseInt)
  .option('-h, --host [host]', 'Server address of the central host [host]', 'yazz.com')
  .option('-s, --hostport [hostport]', 'Server port of the central host [hostport]', parseInt)
  .parse(process.argv);

  port = program.port;
  if (!isNumber(port)) {port = 80;};
  typeOfSystem = program.type;
  centralHostAddress = program.host;
  centralHostPort = program.hostport;
  if (!isNumber(centralHostPort)) {centralHostPort = 80;};

  if (!(typeOfSystem == 'client' || typeOfSystem == 'server')) {
      console.log('-------* Invalid system type: ' + typeOfSystem);
      process.exit();
  };
  console.log('-------* System type: ' + typeOfSystem);
  console.log('-------* Port: ' + port);
  console.log('-------* Central host: ' + centralHostAddress);
  console.log('-------* Central host port: ' + centralHostPort);

console.dir ( ip.address() );

console.log('addr: '+ ip.address());
hostaddress = ip.address();

//------------------------------------------------------------
// copy the oracle files if they exist
//------------------------------------------------------------
if (fs.existsSync(path.join(__dirname, '../oracle_driver.zip'))) {
    useOracle = true;
}
if (useOracle) {
    if (!fs.existsSync(process.cwd() + '\\oracle_driver\\instantclient32')) {
      fs.createReadStream(path.join(__dirname, '../oracle_driver.zip')).pipe(unzip.Extract({ path: process.cwd() + '\\.' }));
      timeout = 3000;
      console.log('Creating oracle_driver');
    } else {
      console.log('oracle_driver already exists');
    };
}
var toeval = fs.readFileSync(path.join(__dirname, './oracle.js')).toString();
if (useOracle) {
    process.env['PATH'] = process.cwd() + '\\oracle_driver\\instantclient32' + ';' + process.env['PATH'];
}

//------------------------------------------------------------
// postgres
//------------------------------------------------------------
var pgeval = fs.readFileSync(path.join(__dirname, './postgres.js')).toString();

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
setTimeout(startYazz, timeout);
console.log('Creating timeout: ' + timeout);

//------------------------------------------------------------
// wait three seconds for stuff to initialize
//------------------------------------------------------------
function startYazz() {
  //
  // start the server
  //
  var Gun = require('gun');
  var gun = Gun({
    file: 'data.json',
    s3: {
      key: '', // AWS Access Key
      secret: '', // AWS Secret Token
      bucket: '' // The bucket you want to save into
    }
  });

  gun.wsp(app);

  console.log(typeOfSystem + ' started on port ' + port + ' with /gun');

  app.get('/', function (req, res) {
      if (!init_drivers) {
        init_drivers = true;
        if (useOracle) {
             eval(toeval);
        }
        eval(pgeval);

      };

      if (typeOfSystem == 'client') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index.html')));
      }
      if (typeOfSystem == 'server') {
          res.end(fs.readFileSync(path.join(__dirname, '../public/index_server.html')));
      }
  })

app.use(express.static(path.join(__dirname, '../public/')))

  app.get('/getresult', function (req, res) {
    var queryData = url.parse(req.url, true).query;
    //console.log('request received: ' + queryData.sql);
    if (connections[queryData.source]) {
        //console.log('query driver: ' + connections[queryData.source].driver);
        drivers[connections[queryData.source].driver]['get'](connections[queryData.source],queryData.sql,function(ordata) {
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end(JSON.stringify(ordata));
        });
    } else {
        console.log('query driver not found: ' + connections[queryData.source]);
    };
})

var requestClientInternalHostAddress = '';
var requestClientInternalPort        = -1;
var requestClientPublicIp            = '';
var requestClientPublicHostName      = '';

//------------------------------------------------------------------------------
// This is called by the central server to get the details of the last
// client that connected tp the central server
//------------------------------------------------------------------------------
app.get('/get_connect', function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(
            JSON.stringify(
                {
                    requestClientInternalHostAddress: requestClientInternalHostAddress
                    ,
                    requestClientInternalPort:        requestClientInternalPort
                    ,
                    requestClientPublicIp:            requestClientPublicIp
                    ,
                    requestClientPublicHostName:      requestClientPublicHostName
                    ,
                    version:      3
                }
          ));
})

//app.enable('trust proxy')

//------------------------------------------------------------------------------
// This is where the client sends its details to the central server
//------------------------------------------------------------------------------
app.get('/client_connect', function (req, res) {
    var queryData = url.parse(req.url, true).query;

    requestClientInternalHostAddress = req.query.requestClientInternalHostAddress;
    requestClientInternalPort        = req.query.requestClientInternalPort;
    requestClientPublicIp            = req.ip;
    //requestClientPublicHostName      = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    requestClientPublicHostName      = req.hostname;

    console.log('Client attempting to connect from:');
    console.log('client internal host address:    ' + requestClientInternalHostAddress)
    console.log('client internal port:            ' + requestClientInternalPort)
    console.log('client public IP address:        ' + requestClientPublicIp)
    console.log('client public IP host name:      ' + requestClientPublicHostName)

})

app.listen(port, hostaddress, function () {
    console.log('Example app listening on port ' + port + '!')
})

  //
  // open the app in a web browser
  //
  //console.log('Ran postgres too');

  var open = require('open');

  open('http://' + hostaddress  + ":" + port);

  //process.env['PATH'] = path.join(__dirname, '/instantclient') + ';' + process.env['PATH'];
  //var oracledb = require('oracledb');
  //console.log('Start oracle');

  //eval("oracledb= require('oracledb');");

  console.log('addr: '+ hostaddress + ":" + port);

  //console.log(toeval);
  //setTimeout(function(){eval(toeval)},1000);

  //  console.log('Done.');

  console.log("*********** CHECKING CONNECTIONS *****************8");
  var connectionrows        = new Object();
  gun.get("connections").on().map(function(a,b){
    delete a["_"];
    if (!connectionrows[a.id]) {
      //data_connections_list.push(a);
      connectionrows[a.id] = a;
      //console.log(a);
      connections[a.id] = a;
    }

  },true);

    if (typeOfSystem == 'client') {
        var urlToConnectTo = "http://" + centralHostAddress + ":" + centralHostPort + '/client_connect';
        console.log('-------* urlToConnectTo: ' + urlToConnectTo);
        console.log('trying to connect to central server...');
        request({
              uri: urlToConnectTo,
              method: "GET",
              timeout: 10000,
              followRedirect: true,
              maxRedirects: 10,
              qs: {
                  requestClientInternalHostAddress: hostaddress
                  ,
                  requestClientInternalPort:        port
              }
            },
            function(error, response, body) {
                console.log(body);
            });
    }

}
<|endoftext|>


<commit_before>import React from 'react'

class Footer extends React.PureComponent {
  render () {
    return

        Copyright 2017 Junyoung Choi. Source code of Carbonstack is published under MIT.

  }
}

export default Footer
<commit_msg>Fix stye bug of footer again<commit_after>import React from 'react'

class Footer extends React.PureComponent {
  render () {
    return

        Copyright 2017 Junyoung Choi. Source code of Carbonstack is published under MIT.

  }
}

export default Footer
<|endoftext|>


<commit_before>import isPromise from './isPromise';

const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED'];

export default function promiseMiddleware(config={}) {
  const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypes;
  return (_ref) => {
    const dispatch = _ref.dispatch;
    return next => action => {
      if (!isPromise(action.payload)) {
        return next(action);
      }

      const { type, payload, meta } = action;
      const { promise, data } = payload;
      const [ PENDING, FULFILLED, REJECTED ] = (meta || {}).promiseTypeSuffixes || promiseTypeSuffixes;

     /**
      * Dispatch the first async handler. This tells the
      * reducer that an async action has been dispatched.
      */
      next({
        type: `${type}_${PENDING}`,
        ...data && { payload: data },
        ...meta && { meta }
      });

      /**
       * Return either the fulfilled action object or the rejected
       * action object.
       */
      return promise.then(
        (resolved={}) => dispatch({
          type: `${type}_${FULFILLED}`,
          ...resolved.meta || resolved.payload ? resolved : {
            ...resolved && { payload: resolved },
            ...meta && { meta }
          }
        }),
        error => dispatch({
          type: `${type}_${REJECTED}`,
          payload: error,
          error: true,
          ...meta && { meta }
        })
      );
    };
  };
}
<commit_msg>Use default parameters for default suffixes<commit_after>import isPromise from './isPromise';

const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED'];

export default function promiseMiddleware(config={}) {
  const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypes;

  return (_ref) => {
    const dispatch = _ref.dispatch;

    return next => action => {
      if (!isPromise(action.payload)) {
        return next(action);
      }

      const { type, payload, meta } = action;
      const { promise, data } = payload;
      const [ PENDING, FULFILLED, REJECTED ] = (meta || {}).promiseTypeSuffixes || promiseTypeSuffixes;

     /**
      * Dispatch the first async handler. This tells the
      * reducer that an async action has been dispatched.
      */
      next({
        type: `${type}_${PENDING}`,
        ...data && { payload: data },
        ...meta && { meta }
      });

      /**
       * Return either the fulfilled action object or the rejected
       * action object.
       */
      return promise.then(
        (resolved={}) => dispatch({
          type: `${type}_${FULFILLED}`,
          ...resolved.meta || resolved.payload ? resolved : {
            ...resolved && { payload: resolved },
            ...meta && { meta }
          }
        }),
        error => dispatch({
          type: `${type}_${REJECTED}`,
          payload: error,
          error: true,
          ...meta && { meta }
        })
      );
    };
  };
}
<|endoftext|>


<commit_before>'use strict';

var Promise = require('bluebird');
Promise.longStackTraces();
var fs = Promise.promisifyAll(require('fs-extra'));
var path = require('path');
var glob = Promise.promisify(require('glob'));
var endOfLine = require('os').EOL;
var _ = require('lodash');
var pathIsAbsolute = require('path-is-absolute');
var semver = require('semver');
var chalk = require('chalk');

function AutoLinkNotFound() {
}
AutoLinkNotFound.prototype = Object.create(Error.prototype);

function getNodeModulesPath() {
  return path.join(process.cwd(), 'node_modules');
}

function getDevPackagesFromPath(autolinkDir) {

  var autolinkPath = path.join(autolinkDir, '.autolink');

  return fs.readFileAsync(autolinkPath)
    .catch(function() {
      return Promise.reject(new AutoLinkNotFound("Error reading .autolink file : " + autolinkPath));
    })
    .then(function(data) {
      var globPatterns = data.toString().split(endOfLine);
      return Promise.all(_.map(globPatterns, function(pattern) {
        if (!pattern) {
          return;
        }

        return glob(pattern, {
          cwd: autolinkDir,
          ignore: ['**/node_modules/**', '**/bower_components/**']
        });
      }));

    })
    .then(function(files) {
      var packages = {};
      _.each(_.flatten(files), function(file) {
        if (!file) {
          return;
        }
        var absoluteFilePath = pathIsAbsolute(file) ? file : path.join(autolinkDir, file);
        var pack = fs.readJsonSync(absoluteFilePath);
        //FIXME
        var dirname = path.dirname(absoluteFilePath);
        var versions = packages[pack.name];
        if (!versions) {
          versions = {};
          packages[pack.name] = versions;
        }
        var currentVersion = versions[pack.version];
        if (currentVersion && currentVersion.path !== dirname) {
          console.log(chalk.red("version conflict : ", currentVersion.path, dirname));
        } else {
          versions[pack.version] = {
            path: dirname,
            package: pack
          };
        }
      });
      return packages;
    });
}

function getDevPackage() {
  var currentDir = process.cwd();
  var oldDir = null;

  var promises = [];
  do {
    promises.push(getDevPackagesFromPath(currentDir));
    oldDir = currentDir;
    currentDir = path.dirname(currentDir);
  } while (currentDir !== oldDir);

  return Promise.settle(promises)
    .then(function(results) {
      var packages = {};
      var autoLinkFound = false;
      var rejections = [];

      _.each(results, function(res) {
        if (res.isFulfilled()) {
          autoLinkFound = true;
          _.mergeWith(packages, res.value(), function(a, b) {
            if (a && _.isString(a.path) && a.path !== b.path) {
              console.log(chalk.red("version conflict : ", a.path, b.path));
            }
          });
        } else {
          if (!(res.reason() instanceof AutoLinkNotFound)) {
            rejections.push(res.reason());
          }
        }
      });

      if (autoLinkFound) {
        return packages;
      } else if (rejections.length) {
        return Promise.reject(rejections[0].message);
      } else {
        return Promise.reject('No .autolink file could be found');
      }

    });
}

function getMatches() {
  var pack;
  try {
    pack = fs.readJsonSync(path.join(process.cwd(), 'package.json'));
  } catch (e) {
    return Promise.reject('No package.json found');
  }

  return getDevPackage().then(function(devPackages) {
    var matches = [];
    _.forOwn(_.merge({},
      pack.dependencies,
      pack.devDependencies,
      pack.optionalDependencies), function(range, name) {
      if (devPackages[name]) {
        var devVersions = _.filter(_.keys(devPackages[name]), function(version) {
          return semver.satisfies(version, range);
        });

        if (devVersions.length) {

          devVersions = devVersions.sort(semver.rcompare);
          var bestVersion = devVersions[0];
          var matchPackage = devPackages[name][bestVersion];
          matches.push({
            name: name,
            devVersion: bestVersion,
            requiredRange: range,
            devPath: matchPackage.path,
            bin: matchPackage.package.bin
          });
        }
      }
    });
    return matches;
  });
}

function linkModules(moduleName) {
  return getMatches()
    .then(function(matches) {
      return Promise.all(_.reduce(matches, function(res, match) {
        if (!moduleName || moduleName === match.name) {
          res.push(linkModule(match));
        }
        return res;
      }, []));
    });
}

function linkModule(match) {

  var scopeMatch = match.name.match(/^(@.*)\/.*/);
  var scope;
  if (!!scopeMatch) {
    scope = scopeMatch[1];
  }
  const nodeModulesPath = getNodeModulesPath();
  var scopedPath = (scope) ? path.join(nodeModulesPath, scope) : nodeModulesPath;
  var targetPath = path.join(nodeModulesPath, match.name);
  var binPath = path.join(nodeModulesPath, '.bin');
  var sourcePath = match.devPath;

  var backPath = targetPath + '.bak';

  return fs.lstatAsync(targetPath)
    .catch(function(err) {})
    .then(function(stat) {
      if (!stat) {
        return;
      }
      if (stat.isSymbolicLink()) {
        //If symlink alreadu exist then remove it
        return fs.removeAsync(targetPath);
      } else {
        //if real directory, remove backPath and rename

        return fs.removeAsync(backPath)
          .then(function() {
            return fs.renameAsync(targetPath, backPath);
          });

      }
    })
    //Create node directory if doesn't exist.
    .then(function() {
      return fs.ensureDirAsync(scopedPath);
    })
    //Create symlink
    .then(function() {
      return fs.symlinkAsync(sourcePath, targetPath);
    })
    .then(function() {
      if (match.bin) {
        return fs.ensureDirAsync(binPath)
          .then(function() {
            return linkBins(binPath, match.bin, sourcePath);
          });
      }
    })
    .then(function() {
      return {
        target: sourcePath,
        path: targetPath,
        added: true,
        version: match.devVersion,
        bins: (match.bin) ? _.keys(match.bin) : ''
      };
    });
}

function linkBins(binPath, bins, sourcePath) {
  return Promise.all(_.reduce(bins, function(res, bin, binName) {
    var sourceBin = path.join(sourcePath, bin);
    var targetLink = path.join(binPath, binName);
    //var bakTargetLink = path.join(binPath, binName) + '.bak';

    var promise = fs.removeAsync(targetLink)
      .then(function() {
        return fs.symlinkAsync(sourceBin, targetLink);
      })
      .then(function() {
        return fs.chmodAsync(targetLink, '755');
      });

    res.push(promise);
    return res;
  }, []));
}

function removeLinks(moduleName) {
  return listLinks().then(function(links) {
    return Promise.all(_.reduce(links, function(res, link) {
      var linkName = path.basename(link.path);
      if (!moduleName || linkName === moduleName) {
        res.push(fs.removeAsync(link.path)
          .then(function() {
            return fs.renameAsync(link.path + '.bak', link.path);
          })
          .catch(function() {})
          .then(function() {
            link.removed = true;
          }));
      }
      return res;
    }, []))
      .then(function() {
        return links;
      });
  });
}

function listLinks(directory) {
  if (!directory) {
    directory = getNodeModulesPath();
  }
  return fs.ensureDirAsync(directory)
    .then(function() {
      return fs.readdirAsync(directory);
    })
    .then(function(files) {
      return Promise.settle(_.map(files, function(fileName) {
        var file = path.join(directory, fileName);

        if (fileName[0] === '@') {
          return listLinks(file);
        }

        return fs.lstatAsync(file)
          .then(function(stat) {
            if (stat.isSymbolicLink()) {
              return fs.readlinkAsync(file);
            } else {
              return Promise.reject();
            }
          })
          .then(function(linkTarget) {
            return {
              path: file,
              target: linkTarget,
              version: fs.readJsonSync(path.join(linkTarget, 'package.json')).version
            };
          });
      }));
    })
    .then(function(res) {
      return _.flatten(_.reduce(res, function(links, item) {
        if (item.isFulfilled()) {
          links.push(item.value());
        }
        return links;
      }, []));
    });
}

module.exports = {
  getDevPackage: getDevPackage,
  getMatches: getMatches,
  linkModules: linkModules,
  removeLinks: removeLinks,
  listLinks: listLinks
};
<commit_msg>Allow git dependencies to be matched against<commit_after>'use strict';

var Promise = require('bluebird');
Promise.longStackTraces();
var fs = Promise.promisifyAll(require('fs-extra'));
var path = require('path');
var glob = Promise.promisify(require('glob'));
var endOfLine = require('os').EOL;
var _ = require('lodash');
var pathIsAbsolute = require('path-is-absolute');
var semver = require('semver');
var chalk = require('chalk');

function AutoLinkNotFound() {
}
AutoLinkNotFound.prototype = Object.create(Error.prototype);

function getNodeModulesPath() {
  return path.join(process.cwd(), 'node_modules');
}

function getDevPackagesFromPath(autolinkDir) {

  var autolinkPath = path.join(autolinkDir, '.autolink');

  return fs.readFileAsync(autolinkPath)
    .catch(function() {
      return Promise.reject(new AutoLinkNotFound("Error reading .autolink file : " + autolinkPath));
    })
    .then(function(data) {
      var globPatterns = data.toString().split(endOfLine);
      return Promise.all(_.map(globPatterns, function(pattern) {
        if (!pattern) {
          return;
        }

        return glob(pattern, {
          cwd: autolinkDir,
          ignore: ['**/node_modules/**', '**/bower_components/**']
        });
      }));

    })
    .then(function(files) {
      var packages = {};
      _.each(_.flatten(files), function(file) {
        if (!file) {
          return;
        }
        var absoluteFilePath = pathIsAbsolute(file) ? file : path.join(autolinkDir, file);
        var pack = fs.readJsonSync(absoluteFilePath);
        //FIXME
        var dirname = path.dirname(absoluteFilePath);
        var versions = packages[pack.name];
        if (!versions) {
          versions = {};
          packages[pack.name] = versions;
        }
        var currentVersion = versions[pack.version];
        if (currentVersion && currentVersion.path !== dirname) {
          console.log(chalk.red("version conflict : ", currentVersion.path, dirname));
        } else {
          versions[pack.version] = {
            path: dirname,
            package: pack
          };
        }
      });
      return packages;
    });
}

function getDevPackage() {
  var currentDir = process.cwd();
  var oldDir = null;

  var promises = [];
  do {
    promises.push(getDevPackagesFromPath(currentDir));
    oldDir = currentDir;
    currentDir = path.dirname(currentDir);
  } while (currentDir !== oldDir);

  return Promise.settle(promises)
    .then(function(results) {
      var packages = {};
      var autoLinkFound = false;
      var rejections = [];

      _.each(results, function(res) {
        if (res.isFulfilled()) {
          autoLinkFound = true;
          _.mergeWith(packages, res.value(), function(a, b) {
            if (a && _.isString(a.path) && a.path !== b.path) {
              console.log(chalk.red("version conflict : ", a.path, b.path));
            }
          });
        } else {
          if (!(res.reason() instanceof AutoLinkNotFound)) {
            rejections.push(res.reason());
          }
        }
      });

      if (autoLinkFound) {
        return packages;
      } else if (rejections.length) {
        return Promise.reject(rejections[0].message);
      } else {
        return Promise.reject('No .autolink file could be found');
      }

    });
}

function getMatches() {
  var pack;
  try {
    pack = fs.readJsonSync(path.join(process.cwd(), 'package.json'));
  } catch (e) {
    return Promise.reject('No package.json found');
  }

  return getDevPackage().then(function(devPackages) {
    var matches = [];
    _.forOwn(_.merge({},
      pack.dependencies,
      pack.devDependencies,
      pack.optionalDependencies), function(range, name) {
      if (devPackages[name]) {
        var devVersions = _.filter(_.keys(devPackages[name]), function(version) {
          return range.startsWith("git+") || semver.satisfies(version, range);
        });

        if (devVersions.length) {

          devVersions = devVersions.sort(semver.rcompare);
          var bestVersion = devVersions[0];
          var matchPackage = devPackages[name][bestVersion];
          matches.push({
            name: name,
            devVersion: bestVersion,
            requiredRange: range,
            devPath: matchPackage.path,
            bin: matchPackage.package.bin
          });
        }
      }
    });
    return matches;
  });
}

function linkModules(moduleName) {
  return getMatches()
    .then(function(matches) {
      return Promise.all(_.reduce(matches, function(res, match) {
        if (!moduleName || moduleName === match.name) {
          res.push(linkModule(match));
        }
        return res;
      }, []));
    });
}

function linkModule(match) {

  var scopeMatch = match.name.match(/^(@.*)\/.*/);
  var scope;
  if (!!scopeMatch) {
    scope = scopeMatch[1];
  }
  const nodeModulesPath = getNodeModulesPath();
  var scopedPath = (scope) ? path.join(nodeModulesPath, scope) : nodeModulesPath;
  var targetPath = path.join(nodeModulesPath, match.name);
  var binPath = path.join(nodeModulesPath, '.bin');
  var sourcePath = match.devPath;

  var backPath = targetPath + '.bak';

  return fs.lstatAsync(targetPath)
    .catch(function(err) {})
    .then(function(stat) {
      if (!stat) {
        return;
      }
      if (stat.isSymbolicLink()) {
        //If symlink alreadu exist then remove it
        return fs.removeAsync(targetPath);
      } else {
        //if real directory, remove backPath and rename

        return fs.removeAsync(backPath)
          .then(function() {
            return fs.renameAsync(targetPath, backPath);
          });

      }
    })
    //Create node directory if doesn't exist.
    .then(function() {
      return fs.ensureDirAsync(scopedPath);
    })
    //Create symlink
    .then(function() {
      return fs.symlinkAsync(sourcePath, targetPath);
    })
    .then(function() {
      if (match.bin) {
        return fs.ensureDirAsync(binPath)
          .then(function() {
            return linkBins(binPath, match.bin, sourcePath);
          });
      }
    })
    .then(function() {
      return {
        target: sourcePath,
        path: targetPath,
        added: true,
        version: match.devVersion,
        bins: (match.bin) ? _.keys(match.bin) : ''
      };
    });
}

function linkBins(binPath, bins, sourcePath) {
  return Promise.all(_.reduce(bins, function(res, bin, binName) {
    var sourceBin = path.join(sourcePath, bin);
    var targetLink = path.join(binPath, binName);
    //var bakTargetLink = path.join(binPath, binName) + '.bak';

    var promise = fs.removeAsync(targetLink)
      .then(function() {
        return fs.symlinkAsync(sourceBin, targetLink);
      })
      .then(function() {
        return fs.chmodAsync(targetLink, '755');
      });

    res.push(promise);
    return res;
  }, []));
}

function removeLinks(moduleName) {
  return listLinks().then(function(links) {
    return Promise.all(_.reduce(links, function(res, link) {
      var linkName = path.basename(link.path);
      if (!moduleName || linkName === moduleName) {
        res.push(fs.removeAsync(link.path)
          .then(function() {
            return fs.renameAsync(link.path + '.bak', link.path);
          })
          .catch(function() {})
          .then(function() {
            link.removed = true;
          }));
      }
      return res;
    }, []))
      .then(function() {
        return links;
      });
  });
}

function listLinks(directory) {
  if (!directory) {
    directory = getNodeModulesPath();
  }
  return fs.ensureDirAsync(directory)
    .then(function() {
      return fs.readdirAsync(directory);
    })
    .then(function(files) {
      return Promise.settle(_.map(files, function(fileName) {
        var file = path.join(directory, fileName);

        if (fileName[0] === '@') {
          return listLinks(file);
        }

        return fs.lstatAsync(file)
          .then(function(stat) {
            if (stat.isSymbolicLink()) {
              return fs.readlinkAsync(file);
            } else {
              return Promise.reject();
            }
          })
          .then(function(linkTarget) {
            return {
              path: file,
              target: linkTarget,
              version: fs.readJsonSync(path.join(linkTarget, 'package.json')).version
            };
          });
      }));
    })
    .then(function(res) {
      return _.flatten(_.reduce(res, function(links, item) {
        if (item.isFulfilled()) {
          links.push(item.value());
        }
        return links;
      }, []));
    });
}

module.exports = {
  getDevPackage: getDevPackage,
  getMatches: getMatches,
  linkModules: linkModules,
  removeLinks: removeLinks,
  listLinks: listLinks
};
<|endoftext|>


<commit_before>// site1.js

Cloud.Instance = function(){
    this.branch = null;
    this.name = this.branch;
    this.db = null;
    this.pool = null;
};

Cloud.Site = function( name ){
    this.name = name;
    this.created = new Date();
    this.instances = [];
    this.instances._dbCons = Cloud.Instance;
};

Cloud.Site.forName = function( name , create ){
    var s = db.sites.findOne( { name : name } );

    if ( s || ! create )
	return s;

    s = new Cloud.Site( name );
    db.sites.apply( s );
    return s;
};

db.sites.setConstructor( Cloud.Site );
db.sites.ensureIndex( { name : 1 } );
<commit_msg>better<commit_after>// site1.js

Cloud.Environment = function(){
    this.branch = null;
    this.name = this.branch;
    this.db = null;
    this.pool = null;
    this.iid = ObjectId();
};

Cloud.Site = function( name ){
    this.name = name;
    this.created = new Date();
    this.environments = [];
    this.environments._dbCons = Cloud.Environment;
};

Cloud.Site.prototype.findEnvironmentByName = function( name ){
    if ( ! name )
        return null;

    var ret = null;
    this.environments.forEach( function(z){
        if ( z.name == name )
            ret = z;
    } );
    return ret;
};

Cloud.Site.prototype.findEnvironmentById = function( iid ){
    if ( ! iid )
        return null;

    if ( isString( iid ) )
        iid = ObjectId( iid );

    var ret = null;
    this.environments.forEach( function(z){
        if ( z.iid == iid )
            ret = z;
    } );
    return ret;
};

Cloud.Site.forName = function( name , create ){
    var s = db.sites.findOne( { name : name } );

    if ( s || ! create )
	return s;

    s = new Cloud.Site( name );
    db.sites.apply( s );
    return s;
};

db.sites.setConstructor( Cloud.Site );
db.sites.ensureIndex( { name : 1 } );
<|endoftext|>


<commit_before>import React from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { INPUT } from '../identifiers.js';
import InjectedFontIcon from '../font_icon/FontIcon.js';

const factory = (FontIcon) => {
  class Input extends React.Component {
    static propTypes = {
      children: React.PropTypes.any,
      className: React.PropTypes.string,
      disabled: React.PropTypes.bool,
      error: React.PropTypes.string,
      floating: React.PropTypes.bool,
      hint: React.PropTypes.string,
      icon: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.element
      ]),
      label: React.PropTypes.string,
      maxLength: React.PropTypes.number,
      multiline: React.PropTypes.bool,
      name: React.PropTypes.string,
      onBlur: React.PropTypes.func,
      onChange: React.PropTypes.func,
      onFocus: React.PropTypes.func,
      onKeyPress: React.PropTypes.func,
      required: React.PropTypes.bool,
      theme: React.PropTypes.shape({
        bar: React.PropTypes.string,
        counter: React.PropTypes.string,
        disabled: React.PropTypes.string,
        error: React.PropTypes.string,
        errored: React.PropTypes.string,
        hidden: React.PropTypes.string,
        hint: React.PropTypes.string,
        icon: React.PropTypes.string,
        input: React.PropTypes.string,
        inputElement: React.PropTypes.string,
        required: React.PropTypes.string,
        withIcon: React.PropTypes.string
      }),
      type: React.PropTypes.string,
      value: React.PropTypes.any
    };

    static defaultProps = {
      className: '',
      hint: '',
      disabled: false,
      floating: true,
      multiline: false,
      required: false,
      type: 'text'
    };

    componentDidMount () {
      if (this.props.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
        this.handleAutoresize();
      }
    }

    componentWillReceiveProps (nextProps) {
      if (!this.props.multiline && nextProps.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
      } else if (this.props.multiline && !nextProps.multiline) {
        window.removeEventListener('resize', this.handleAutoresize);
      }
    }

    componentDidUpdate (prevProps) {
      const { multiline, value } = this.props;

      // resize the textarea, if nessesary
      if (multiline && (prevProps.value && prevProps.value.length) !== (value && value.length)) {
        this.handleAutoresize();
      }
    }

    componentWillUnmount () {
      if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
    }

    handleChange = (event) => {
      const { onChange, multiline, maxLength } = this.props;
      const valueFromEvent = event.target.value;

      // trim value to maxLength if that exists (only on multiline inputs)
      const haveToTrim = (multiline && maxLength && event.target.value.length > maxLength);
      const value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;

      // propagate to to store and therefore to the input
      if (onChange) onChange(value, event);
    };

    handleAutoresize = () => {
      const element = this.refs.input;
      // compute the height difference between inner height and outer height
      const style = getComputedStyle(element, null);
      const heightOffset = style.boxSizing === 'content-box'
        ? -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom))
        : parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);

      // resize the input to its content size
      element.style.height = 'auto';
      element.style.height = `${element.scrollHeight + heightOffset}px`;
    }

    blur () {
      this.refs.input.blur();
    }

    focus () {
      this.refs.input.focus();
    }

    render () {
      const { children, disabled, error, floating, hint, icon,
              name, label: labelText, maxLength, multiline, required,
              theme, type, value, ...others} = this.props;
      const length = maxLength && value ? value.length : 0;
      const labelClassName = classnames(theme.label, {[theme.fixed]: !floating});

      const className = classnames(theme.input, {
        [theme.disabled]: disabled,
        [theme.errored]: error,
        [theme.hidden]: type === 'hidden',
        [theme.withIcon]: icon
      }, this.props.className);

      const valuePresent = value !== null
        && value !== undefined
        && value !== ''
        && !(typeof value === Number && isNaN(value));

      const InputElement = React.createElement(multiline ? 'textarea' : 'input', {
        ...others,
        className: classnames(theme.inputElement, {[theme.filled]: valuePresent}),
        onChange: this.handleChange,
        ref: 'input',
        role: 'input',
        name,
        disabled,
        required,
        type,
        value
      });

      return (

          {InputElement}
          {icon ? <FontIcon className={theme.icon} value={icon} /> : null}

          {labelText
            ?
                {labelText}
                {required ?  *  : null}

            : null}
          {hint ? {hint} : null}
          {error ? {error} : null}
          {maxLength ? {length}/{maxLength} : null}
          {children}

      );
    }
  }

  return Input;
};

const Input = factory(InjectedFontIcon);
export default themr(INPUT, null, { withRef: true })(Input);
export { factory as inputFactory };
export { Input };
<commit_msg>feat(input): set the default row amount for multiline inputs to 1<commit_after>import React from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { INPUT } from '../identifiers.js';
import InjectedFontIcon from '../font_icon/FontIcon.js';

const factory = (FontIcon) => {
  class Input extends React.Component {
    static propTypes = {
      children: React.PropTypes.any,
      className: React.PropTypes.string,
      disabled: React.PropTypes.bool,
      error: React.PropTypes.string,
      floating: React.PropTypes.bool,
      hint: React.PropTypes.string,
      icon: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.element
      ]),
      label: React.PropTypes.string,
      maxLength: React.PropTypes.number,
      multiline: React.PropTypes.bool,
      name: React.PropTypes.string,
      onBlur: React.PropTypes.func,
      onChange: React.PropTypes.func,
      onFocus: React.PropTypes.func,
      onKeyPress: React.PropTypes.func,
      required: React.PropTypes.bool,
      theme: React.PropTypes.shape({
        bar: React.PropTypes.string,
        counter: React.PropTypes.string,
        disabled: React.PropTypes.string,
        error: React.PropTypes.string,
        errored: React.PropTypes.string,
        hidden: React.PropTypes.string,
        hint: React.PropTypes.string,
        icon: React.PropTypes.string,
        input: React.PropTypes.string,
        inputElement: React.PropTypes.string,
        required: React.PropTypes.string,
        withIcon: React.PropTypes.string
      }),
      type: React.PropTypes.string,
      value: React.PropTypes.any
    };

    static defaultProps = {
      className: '',
      hint: '',
      disabled: false,
      floating: true,
      multiline: false,
      required: false,
      type: 'text'
    };

    componentDidMount () {
      if (this.props.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
        this.handleAutoresize();
      }
    }

    componentWillReceiveProps (nextProps) {
      if (!this.props.multiline && nextProps.multiline) {
        window.addEventListener('resize', this.handleAutoresize);
      } else if (this.props.multiline && !nextProps.multiline) {
        window.removeEventListener('resize', this.handleAutoresize);
      }
    }

    componentDidUpdate (prevProps) {
      const { multiline, value } = this.props;

      // resize the textarea, if nessesary
      if (multiline && (prevProps.value && prevProps.value.length) !== (value && value.length)) {
        this.handleAutoresize();
      }
    }

    componentWillUnmount () {
      if (this.props.multiline) window.removeEventListener('resize', this.handleAutoresize);
    }

    handleChange = (event) => {
      const { onChange, multiline, maxLength } = this.props;
      const valueFromEvent = event.target.value;

      // trim value to maxLength if that exists (only on multiline inputs)
      const haveToTrim = (multiline && maxLength && event.target.value.length > maxLength);
      const value = haveToTrim ? valueFromEvent.substr(0, maxLength) : valueFromEvent;

      // propagate to to store and therefore to the input
      if (onChange) onChange(value, event);
    };

    handleAutoresize = () => {
      const element = this.refs.input;
      // compute the height difference between inner height and outer height
      const style = getComputedStyle(element, null);
      const heightOffset = style.boxSizing === 'content-box'
        ? -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom))
        : parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);

      // resize the input to its content size
      element.style.height = 'auto';
      element.style.height = `${element.scrollHeight + heightOffset}px`;
    }

    blur () {
      this.refs.input.blur();
    }

    focus () {
      this.refs.input.focus();
    }

    render () {
      const { children, disabled, error, floating, hint, icon,
              name, label: labelText, maxLength, multiline, required,
              theme, type, value, ...others} = this.props;
      const length = maxLength && value ? value.length : 0;
      const labelClassName = classnames(theme.label, {[theme.fixed]: !floating});

      const className = classnames(theme.input, {
        [theme.disabled]: disabled,
        [theme.errored]: error,
        [theme.hidden]: type === 'hidden',
        [theme.withIcon]: icon
      }, this.props.className);

      const valuePresent = value !== null
        && value !== undefined
        && value !== ''
        && !(typeof value === Number && isNaN(value));

      const inputElementProps = {
        ...others,
        className: classnames(theme.inputElement, {[theme.filled]: valuePresent}),
        onChange: this.handleChange,
        ref: 'input',
        role: 'input',
        name,
        disabled,
        required,
        type,
        value
      };
      if (multiline) inputElementProps.rows = 1; // set initial height to 1
      const InputElement = React.createElement(multiline ? 'textarea' : 'input', inputElementProps);

      return (

          {InputElement}
          {icon ? <FontIcon className={theme.icon} value={icon} /> : null}

          {labelText
            ?
                {labelText}
                {required ?  *  : null}

            : null}
          {hint ? {hint} : null}
          {error ? {error} : null}
          {maxLength ? {length}/{maxLength} : null}
          {children}

      );
    }
  }

  return Input;
};

const Input = factory(InjectedFontIcon);
export default themr(INPUT, null, { withRef: true })(Input);
export { factory as inputFactory };
export { Input };
<|endoftext|>


<commit_before>// site1.js

/**
*    Copyright (C) 2008 10gen Inc.
*
*    This program is free software: you can redistribute it and/or  modify
*    it under the terms of the GNU Affero General Public License, version 3,
*    as published by the Free Software Foundation.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

// -----  Basic Structure Stuff -----------

Cloud.Environment = function( name , branch , db , pool ){
    this.name = name;
    this.branch = branch;
    this.db = db;
    this.pool = pool;

    this.id = ObjectId();
    this.aliases = [];
};

// iid is the old name - should deprecate
Cloud.Environment.prototype.__defineGetter__( "iid" , function(){ return this.id; } );
Cloud.Environment.prototype.__defineSetter__( "iid" , function( id ){ this.id = id; } );

Cloud.Environment.prototype.__defineGetter__( "aliases" , function(){ return this._aliases; } );
Cloud.Environment.prototype.__defineSetter__( "aliases" ,
                                              function( aliases ){
                                                  if ( ! aliases )
                                                      return this._aliases = [];

                                                  if ( isArray( aliases ) )
                                                      return this._aliases = aliases;

                                                  if ( isString( aliases ) )
                                                      return ( this._aliases = aliases.split( /[, ]+/ ) );

                                                  throw "what?";
                                              } )
;

Cloud.Environment.prototype.toString = function(){
    return this.name;
}

Cloud.SiteDB = function( name , server ){
    this.name = name;
    this.server = server;
    this.id = ObjectId();
};

// did is the old name - should deprecate
Cloud.SiteDB.prototype.__defineGetter__( "did" , function(){ return this.id; } );
Cloud.SiteDB.prototype.__defineSetter__( "did" , function( id ){ this.id = id; } );

Cloud.Site = function( name ){
    this.name = name;
    this.created = new Date();
    this.giturl = null;

    this.environments = [];
    this.environments._dbCons = Cloud.Environment;

    this.dbs = [];
    this.dbs._dbCons = Cloud.SiteDB;
};

Cloud.Site.prototype.toString = function(){
    return "Site: " + this.name;
};

// -----   Environment Stuff -----------

Cloud.Site.prototype.environmentNames = function(){
    return this.environments.map( function(z){ return z.name } );
}

Cloud.Site.prototype.removeEnvironment = function( identifier ){

    var e = this.findEnvironment( identifier );
    if ( ! e )
        return false;

    this.environments = this.environments.filter(
        function(z){
            return z != e;
        }
    );

    return true;
}

Cloud.Site.prototype.findEnvironment = function( identifier ){
    if ( identifier && isObject( identifier ) && identifier.id && identifier.name )
        return identifier;

    for ( var i=0; i<arguments.length; i++ ){
        var e = this.findEnvironmentByName( arguments[i] ) || this.findEnvironmentById( arguments[i] );
        if ( e )
            return e;
    }
    return null;
}

Cloud.Site.prototype.findEnvironmentByName = function( name ){
    if ( ! name )
        return null;

    var ret = null;
    var ali = null;
    this.environments.forEach( function(z){

        if ( z.name == name )
            ret = z;

        if ( z.aliases && z.aliases.contains( name ) )
            ali = z;

    } );

    return ret || ali;
};

Cloud.Site.prototype.findEnvironmentById = function( id ){
    if ( ! id )
        return null;

    if ( isString( id ) ){
        if ( ! ObjectId.isValid( id ) )
            return null;
        id = ObjectId( id );
    }

    var ret = null;
    this.environments.forEach( function(z){
        if ( z.id == id )
            ret = z;
    } );
    return ret;
};

Cloud.Site.prototype.upsertEnvironment = function( name , branch , db , pool , aliases ){
    if ( isObject( name ) && branch == null ){
        var o = name;
        var tempID = o.iid || o.id;

        var e = {};
        if ( tempID )
            e = this.findEnvironmentById( tempID ) || {};

        name = o.name || e.name;
        branch = o.branch || e.branch;
        db = o.db || e.db;
        pool = o.pool || e.pool;
        aliases = o.aliases || e.aliases;

    }

    if ( ! name )
        throw "envinroment must have a name";

    var e = this.findEnvironmentByName( name );

    if ( ! branch ){
        if ( e ) branch = e.branch;
        if ( ! branch )
            throw "envinroment must have a branch";
    }

    if ( ! db ){
        if ( e ) db = e.db;

        if ( this.findDBByName( name ) )
            db = name;

        if ( ! db )
            throw "envinroment must have a db and can't find a db called [" + name + "]";
    }

    if ( ! this.findDBByName( db ) )
        throw "no db with name [" + db + "]";

    if ( ! pool ){
        if ( e ) pool = e.pool;
        if ( ! pool )
            pool = Cloud.Balancer.getAvailablePool();
    }

    if ( ! Cloud.Pool.findByName( pool ) ){
        throw "no pool with name [" + pool + "]";
    }

    if ( e ){
        var changed = false;

        if ( e.branch != branch ){
            e.branch = branch;
            changed = true;
        }

        if ( e.db != db ){
            e.db = db;
            changed = true;
        }

        if ( e.pool != pool ){
            e.pool = pool;
            changed = true;
        }

        if ( e.aliases != aliases ){
            var old = e.aliases;
            e.aliases = aliases;
            if ( old == null || old.hashCode() != e.aliases.hashCode() )
                changed = true;
        }

        return changed;
    }

    e = new Cloud.Environment( name , branch , db , pool );
    e.aliases = aliases;
    this.environments.add( e );
    return true;
};

// -----   DB Stuff -----------

Cloud.Site.prototype.dbNames = function(){
    return this.dbs.map( function(z){ return z.name } );
}

Cloud.Site.prototype.removeDB = function( identifier ){
    var db = this.findDB( identifier );
    if ( ! db )
        return false;

    this.environments.forEach(
        function(z){
            if ( z.db == db.name )
                throw "you can't delete db[" + db.name + "] because being used by [" + z.name + "]";
        }
    );

    this.dbs = this.dbs.filter(
        function(z){
            return z != db;
        }
    );

    return true;
}

/**
* @return this returns the 10gen server name (prod1)
*/
Cloud.Site.prototype.getDBForEnvironment = function( name ){
    name = name || "www";

    var env = this.findEnvironmentByName( name );

    if ( ! env )
        throw "can't find environment [" + name + "] choices [" + this.environmentNames() + "] site:" + this.name;

    var db = this.findDBByName( env.db );
    if ( ! db )
        throw "something is wrong, can't find db [" + env.db + "] choices [" + this.dbNames() + "]";

    if ( ! db.server )
	throw "we found db [" + env.db + "] but its misconfigured";

    return db;
}

Cloud.Site.prototype.getDBUrlForEnvironment = function( envName ){
    return this.getDBUrl( this.getDBForEnvironment( envName ) );
}

Cloud.Site.prototype.getDBUrl = function( dbName ){
    var db = this.findDB( dbName );
    if ( ! db )
        throw "can't find db [" + dbName + "]";

    var url = db.server + "/" + this.name;
    if ( db.envParition )
        url += ":" + db.name;
    return url;

}

Cloud.Site.getDBConnection = function( dbName ){
    return connect( this.getDBUrl( dbName ) );
}

Cloud.Site.prototype.findDB = function( identifier ){
    if ( identifier && isObject( identifier ) && identifier.id && identifier.name )
        return identifier;

    for ( var i=0; i<arguments.length; i++ ){
        var db = this.findDBByName( arguments[i] ) || this.findDBById( arguments[i] );
        if ( db )
            return db;
    }
    return null;
}

Cloud.Site.prototype.findDBByName = function( name ){
    if ( ! name )
        return null;

    var ret = null;
    this.dbs.forEach( function(z){
        if ( z.name == name )
            ret = z;
    } );
    return ret;
};

Cloud.Site.prototype.findDBById = function( id ){
    if ( ! id )
        return null;

    if ( isString( id ) ){
        if ( ! ObjectId.isValid( id ) )
            return null;
        id = ObjectId( id );
    }

    var ret = null;
    this.dbs.forEach( function(z){
        if ( z.id == id )
            ret = z;
    } );
    return ret;
};

/**
* @return true if a change was made.  (either created or server changed)
*/
Cloud.Site.prototype.upsertDB = function( name , server , userToInsert ){

    if ( isObject( name ) && server == null && name.name ){
        var o = name;
        name = o.name;
        server = o.server;
    }

    if ( ! name )
        throw "need to specify db name";

    if ( ! server )
        server = Cloud.Balancer.getAvailableDB();

    if ( ! Cloud.findDBByName( server ) )
        throw "can't find db server [" + server + "]";

    if ( this.findDBByName( name ) ){
        var db = this.findDBByName( name );
        if ( db.server == server )
            return false;

        db.server = server;
        return true;
    }

    log( "creating new db [" + name + "] for [" + this.name + "]" );

    var db = new Cloud.SiteDB( name , server );
    db.envParition = true;

    this.dbs.add( db );

    if ( userToInsert || this.defaultUsers ){
        var conn = this.getDBConnection( db );

        if ( this.defaultUsers ){
            for each ( u in this.defaultUsers ){
                log( "storing user [" + u.email + "] in [" + conn + "]" );
                conn.users.save( u );
            }
        }

        if ( userToInsert ){
	    if ( ! db.users.findOne( { email : userToInsert.email } ) ){
	        conn.users.save( userToInsert );
            }
        }

    }

    return true;
};

// -----  Util Stuff -----------

Cloud.Site.prototype.getGitBranchNames = function( force ){

    if ( ! this.giturl || this.giturl.startsWith( "ssh://git.10gen.com/data/gitroot/" ) ){
        var g = db.git.findOne( { name : "sites/" + this.name } );
        if ( ! g ){
            g = new Cloud.Git.Repository();
            g.ensureHash( "master" , "0" );
            db.git.save( g );
        }
        return g.branches.keySet();
    }

    var base = javaCreate( "java.io.File" , "/data/tmp/externalgit/" );
    base.mkdirs();
    var root = javaCreate( "java.io.File" , base , this.name );

    if ( root.exists() ){
        var conf = javaStatic( "ed.util.GitUtils" , "readConfig" , root );
        if ( conf.remote.origin.url != this.giturl ){
            log.git.info( "giturl changed for site [" + this.name + "]  was [" + conf.remote.origin.url + "] now is [" + this.giturl + "]" );
            javaStatic( "ed.io.FileUtil" , "deleteDirectory" , root );
        }
    }

    if ( ! root.exists() ){
        var msg = "clone [" + this.giturl + "] to [" + root + "]";

        log.git.info( msg );
        if ( ! javaStatic( "ed.util.GitUtils" , "clone" , this.giturl , base , this.name ) ){
            log.git.error( "failed " + msg );
            throw "couldn't " + msg;
        }
        force = true;
    }

    var now = new Date();

    var ts = javaCreate( "java.io.File" , root , ".git/10gents" );
    if ( ! ts.exists() ){
        force = true;
        ts.createNewFile();
    }
    else {
        if ( ( ts.lastModified() + ( 1000 * 60 * 5 ) ) < now.getTime() )
            force = true;
    }

    if ( force ){
        log.git.info( " doing full update for [" + this.name + "]" );
        javaStatic( "ed.util.GitUtils" , "fullUpdate" , root );
        ts.setLastModified( now.getTime() );
    }

    return javaStatic( "ed.util.GitUtils" , "getAllBranchAndTagNames" , root );
};

Cloud.Site.prototype.updateEnvironment = function( envName , fullReset , dryRun ){
    var command = fullReset ? "reset" : "update";

    var env = this.findEnvironment( envName );
    if ( ! env )
        throw "can't find environment [" + envName + "]";

    var p = db.pools.findOne( { name : env.pool } );
    if ( ! p )
        throw "couldn't find pool [" + env.pool + "]";

    var threads = [];

    var hostName = env.name + "." + this.name + ".10gen.com";

    var res = { ok : true };
    for ( var i=0; i<p.machines.length; i++ ){
        var machine = p.machines[i];
	threads.push(
	    fork(
		function(){
		    try {
			res[machine] = Cloud.Site.resetSiteOnHost( machine , hostName , command , dryRun );
		    }
		    catch ( e ){
			res.ok = false;
			res[machine] = e;
		    }
		}
            )
        );
    }

    for ( var i=0; i<threads.length; i++ ) threads[i].start();
    for ( var i=0; i<threads.length; i++ ) threads[i].join();

    return res;
}

Cloud.Site.resetSiteOnHost = function( machine , hostName , command , dryRun ){
    command = command || "reset";
    var cmd = "ssh " + machine + " \"curl -D - -s -H 'Host: " + hostName + "'\" local.10gen.com:8080/~" + command;
    var res = dryRun ? {} : sysexec( cmd );
    res.cmd = cmd;
    return res;
}

// ---- Static Stuff -------

Cloud.Site.forName = function( name , create ){
    var s = db.sites.findOne( { name : name } );

    if ( s || ! create )
	return s;

    s = new Cloud.Site( name );
    db.sites.apply( s );
    return s;
};

db.sites.setConstructor( Cloud.Site );
if ( me.real ){
    db.sites.ensureIndex( { name : 1 } );
}
<commit_msg>threading fix for site updating<commit_after>// site1.js

/**
*    Copyright (C) 2008 10gen Inc.
*
*    This program is free software: you can redistribute it and/or  modify
*    it under the terms of the GNU Affero General Public License, version 3,
*    as published by the Free Software Foundation.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU Affero General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

// -----  Basic Structure Stuff -----------

Cloud.Environment = function( name , branch , db , pool ){
    this.name = name;
    this.branch = branch;
    this.db = db;
    this.pool = pool;

    this.id = ObjectId();
    this.aliases = [];
};

// iid is the old name - should deprecate
Cloud.Environment.prototype.__defineGetter__( "iid" , function(){ return this.id; } );
Cloud.Environment.prototype.__defineSetter__( "iid" , function( id ){ this.id = id; } );

Cloud.Environment.prototype.__defineGetter__( "aliases" , function(){ return this._aliases; } );
Cloud.Environment.prototype.__defineSetter__( "aliases" ,
                                              function( aliases ){
                                                  if ( ! aliases )
                                                      return this._aliases = [];

                                                  if ( isArray( aliases ) )
                                                      return this._aliases = aliases;

                                                  if ( isString( aliases ) )
                                                      return ( this._aliases = aliases.split( /[, ]+/ ) );

                                                  throw "what?";
                                              } )
;

Cloud.Environment.prototype.toString = function(){
    return this.name;
}

Cloud.SiteDB = function( name , server ){
    this.name = name;
    this.server = server;
    this.id = ObjectId();
};

// did is the old name - should deprecate
Cloud.SiteDB.prototype.__defineGetter__( "did" , function(){ return this.id; } );
Cloud.SiteDB.prototype.__defineSetter__( "did" , function( id ){ this.id = id; } );

Cloud.Site = function( name ){
    this.name = name;
    this.created = new Date();
    this.giturl = null;

    this.environments = [];
    this.environments._dbCons = Cloud.Environment;

    this.dbs = [];
    this.dbs._dbCons = Cloud.SiteDB;
};

Cloud.Site.prototype.toString = function(){
    return "Site: " + this.name;
};

// -----   Environment Stuff -----------

Cloud.Site.prototype.environmentNames = function(){
    return this.environments.map( function(z){ return z.name } );
}

Cloud.Site.prototype.removeEnvironment = function( identifier ){

    var e = this.findEnvironment( identifier );
    if ( ! e )
        return false;

    this.environments = this.environments.filter(
        function(z){
            return z != e;
        }
    );

    return true;
}

Cloud.Site.prototype.findEnvironment = function( identifier ){
    if ( identifier && isObject( identifier ) && identifier.id && identifier.name )
        return identifier;

    for ( var i=0; i<arguments.length; i++ ){
        var e = this.findEnvironmentByName( arguments[i] ) || this.findEnvironmentById( arguments[i] );
        if ( e )
            return e;
    }
    return null;
}

Cloud.Site.prototype.findEnvironmentByName = function( name ){
    if ( ! name )
        return null;

    var ret = null;
    var ali = null;
    this.environments.forEach( function(z){

        if ( z.name == name )
            ret = z;

        if ( z.aliases && z.aliases.contains( name ) )
            ali = z;

    } );

    return ret || ali;
};

Cloud.Site.prototype.findEnvironmentById = function( id ){
    if ( ! id )
        return null;

    if ( isString( id ) ){
        if ( ! ObjectId.isValid( id ) )
            return null;
        id = ObjectId( id );
    }

    var ret = null;
    this.environments.forEach( function(z){
        if ( z.id == id )
            ret = z;
    } );
    return ret;
};

Cloud.Site.prototype.upsertEnvironment = function( name , branch , db , pool , aliases ){
    if ( isObject( name ) && branch == null ){
        var o = name;
        var tempID = o.iid || o.id;

        var e = {};
        if ( tempID )
            e = this.findEnvironmentById( tempID ) || {};

        name = o.name || e.name;
        branch = o.branch || e.branch;
        db = o.db || e.db;
        pool = o.pool || e.pool;
        aliases = o.aliases || e.aliases;

    }

    if ( ! name )
        throw "envinroment must have a name";

    var e = this.findEnvironmentByName( name );

    if ( ! branch ){
        if ( e ) branch = e.branch;
        if ( ! branch )
            throw "envinroment must have a branch";
    }

    if ( ! db ){
        if ( e ) db = e.db;

        if ( this.findDBByName( name ) )
            db = name;

        if ( ! db )
            throw "envinroment must have a db and can't find a db called [" + name + "]";
    }

    if ( ! this.findDBByName( db ) )
        throw "no db with name [" + db + "]";

    if ( ! pool ){
        if ( e ) pool = e.pool;
        if ( ! pool )
            pool = Cloud.Balancer.getAvailablePool();
    }

    if ( ! Cloud.Pool.findByName( pool ) ){
        throw "no pool with name [" + pool + "]";
    }

    if ( e ){
        var changed = false;

        if ( e.branch != branch ){
            e.branch = branch;
            changed = true;
        }

        if ( e.db != db ){
            e.db = db;
            changed = true;
        }

        if ( e.pool != pool ){
            e.pool = pool;
            changed = true;
        }

        if ( e.aliases != aliases ){
            var old = e.aliases;
            e.aliases = aliases;
            if ( old == null || old.hashCode() != e.aliases.hashCode() )
                changed = true;
        }

        return changed;
    }

    e = new Cloud.Environment( name , branch , db , pool );
    e.aliases = aliases;
    this.environments.add( e );
    return true;
};

// -----   DB Stuff -----------

Cloud.Site.prototype.dbNames = function(){
    return this.dbs.map( function(z){ return z.name } );
}

Cloud.Site.prototype.removeDB = function( identifier ){
    var db = this.findDB( identifier );
    if ( ! db )
        return false;

    this.environments.forEach(
        function(z){
            if ( z.db == db.name )
                throw "you can't delete db[" + db.name + "] because being used by [" + z.name + "]";
        }
    );

    this.dbs = this.dbs.filter(
        function(z){
            return z != db;
        }
    );

    return true;
}

/**
* @return this returns the 10gen server name (prod1)
*/
Cloud.Site.prototype.getDBForEnvironment = function( name ){
    name = name || "www";

    var env = this.findEnvironmentByName( name );

    if ( ! env )
        throw "can't find environment [" + name + "] choices [" + this.environmentNames() + "] site:" + this.name;

    var db = this.findDBByName( env.db );
    if ( ! db )
        throw "something is wrong, can't find db [" + env.db + "] choices [" + this.dbNames() + "]";

    if ( ! db.server )
	throw "we found db [" + env.db + "] but its misconfigured";

    return db;
}

Cloud.Site.prototype.getDBUrlForEnvironment = function( envName ){
    return this.getDBUrl( this.getDBForEnvironment( envName ) );
}

Cloud.Site.prototype.getDBUrl = function( dbName ){
    var db = this.findDB( dbName );
    if ( ! db )
        throw "can't find db [" + dbName + "]";

    var url = db.server + "/" + this.name;
    if ( db.envParition )
        url += ":" + db.name;
    return url;

}

Cloud.Site.getDBConnection = function( dbName ){
    return connect( this.getDBUrl( dbName ) );
}

Cloud.Site.prototype.findDB = function( identifier ){
    if ( identifier && isObject( identifier ) && identifier.id && identifier.name )
        return identifier;

    for ( var i=0; i<arguments.length; i++ ){
        var db = this.findDBByName( arguments[i] ) || this.findDBById( arguments[i] );
        if ( db )
            return db;
    }
    return null;
}

Cloud.Site.prototype.findDBByName = function( name ){
    if ( ! name )
        return null;

    var ret = null;
    this.dbs.forEach( function(z){
        if ( z.name == name )
            ret = z;
    } );
    return ret;
};

Cloud.Site.prototype.findDBById = function( id ){
    if ( ! id )
        return null;

    if ( isString( id ) ){
        if ( ! ObjectId.isValid( id ) )
            return null;
        id = ObjectId( id );
    }

    var ret = null;
    this.dbs.forEach( function(z){
        if ( z.id == id )
            ret = z;
    } );
    return ret;
};

/**
* @return true if a change was made.  (either created or server changed)
*/
Cloud.Site.prototype.upsertDB = function( name , server , userToInsert ){

    if ( isObject( name ) && server == null && name.name ){
        var o = name;
        name = o.name;
        server = o.server;
    }

    if ( ! name )
        throw "need to specify db name";

    if ( ! server )
        server = Cloud.Balancer.getAvailableDB();

    if ( ! Cloud.findDBByName( server ) )
        throw "can't find db server [" + server + "]";

    if ( this.findDBByName( name ) ){
        var db = this.findDBByName( name );
        if ( db.server == server )
            return false;

        db.server = server;
        return true;
    }

    log( "creating new db [" + name + "] for [" + this.name + "]" );

    var db = new Cloud.SiteDB( name , server );
    db.envParition = true;

    this.dbs.add( db );

    if ( userToInsert || this.defaultUsers ){
        var conn = this.getDBConnection( db );

        if ( this.defaultUsers ){
            for each ( u in this.defaultUsers ){
                log( "storing user [" + u.email + "] in [" + conn + "]" );
                conn.users.save( u );
            }
        }

        if ( userToInsert ){
	    if ( ! db.users.findOne( { email : userToInsert.email } ) ){
	        conn.users.save( userToInsert );
            }
        }

    }

    return true;
};

// -----  Util Stuff -----------

Cloud.Site.prototype.getGitBranchNames = function( force ){

    if ( ! this.giturl || this.giturl.startsWith( "ssh://git.10gen.com/data/gitroot/" ) ){
        var g = db.git.findOne( { name : "sites/" + this.name } );
        if ( ! g ){
            g = new Cloud.Git.Repository();
            g.ensureHash( "master" , "0" );
            db.git.save( g );
        }
        return g.branches.keySet();
    }

    var base = javaCreate( "java.io.File" , "/data/tmp/externalgit/" );
    base.mkdirs();
    var root = javaCreate( "java.io.File" , base , this.name );

    if ( root.exists() ){
        var conf = javaStatic( "ed.util.GitUtils" , "readConfig" , root );
        if ( conf.remote.origin.url != this.giturl ){
            log.git.info( "giturl changed for site [" + this.name + "]  was [" + conf.remote.origin.url + "] now is [" + this.giturl + "]" );
            javaStatic( "ed.io.FileUtil" , "deleteDirectory" , root );
        }
    }

    if ( ! root.exists() ){
        var msg = "clone [" + this.giturl + "] to [" + root + "]";

        log.git.info( msg );
        if ( ! javaStatic( "ed.util.GitUtils" , "clone" , this.giturl , base , this.name ) ){
            log.git.error( "failed " + msg );
            throw "couldn't " + msg;
        }
        force = true;
    }

    var now = new Date();

    var ts = javaCreate( "java.io.File" , root , ".git/10gents" );
    if ( ! ts.exists() ){
        force = true;
        ts.createNewFile();
    }
    else {
        if ( ( ts.lastModified() + ( 1000 * 60 * 5 ) ) < now.getTime() )
            force = true;
    }

    if ( force ){
        log.git.info( " doing full update for [" + this.name + "]" );
        javaStatic( "ed.util.GitUtils" , "fullUpdate" , root );
        ts.setLastModified( now.getTime() );
    }

    return javaStatic( "ed.util.GitUtils" , "getAllBranchAndTagNames" , root );
};

Cloud.Site.prototype.updateEnvironment = function( envName , fullReset , dryRun ){
    var command = fullReset ? "reset" : "update";

    var env = this.findEnvironment( envName );
    if ( ! env )
        throw "can't find environment [" + envName + "]";

    var p = db.pools.findOne( { name : env.pool } );
    if ( ! p )
        throw "couldn't find pool [" + env.pool + "]";

    log.debug( "update site [" + this.name + "] env [" + envName + "] pool [" + p + "]" );

    var threads = [];

    var hostName = env.name + "." + this.name + ".10gen.com";

    var res = { ok : true };
    for ( var i=0; i<p.machines.length; i++ ){
        var machine = p.machines[i];
    	threads.push(
	    fork(
		function( machine ){
		    try {
			res[machine] = Cloud.Site.resetSiteOnHost( machine , hostName , command , dryRun );
		    }
		    catch ( e ){
			res.ok = false;
			res[machine] = e;
		    }
		}
                , machine
            )
        );
    }

    for ( var i=0; i<threads.length; i++ ) threads[i].start();
    for ( var i=0; i<threads.length; i++ ) threads[i].join();

    return res;
}

Cloud.Site.resetSiteOnHost = function( machine , hostName , command , dryRun ){
    command = command || "reset";
    var cmd = "ssh " + machine + " \"curl -D - -s -H 'Host: " + hostName + "'\" local.10gen.com:8080/~" + command;
    var res = dryRun ? {} : sysexec( cmd );
    res.cmd = cmd;
    return res;
}

// ---- Static Stuff -------

Cloud.Site.forName = function( name , create ){
    var s = db.sites.findOne( { name : name } );

    if ( s || ! create )
	return s;

    s = new Cloud.Site( name );
    db.sites.apply( s );
    return s;
};

db.sites.setConstructor( Cloud.Site );
if ( me.real ){
    db.sites.ensureIndex( { name : 1 } );
}
<|endoftext|>