<commit_before>/**
 * This module takes care of loading the BridgeSupport XML files for a given
 * framework, and parsing the data into the given framework object.
 */

var fs = require('fs')
  , sax = require('sax')
  , path = require('path')
  , core = require('./core')
  , types = require('./types')
  , join = path.join
  , basename = path.basename
  , exists = path.existsSync
  , DY_SUFFIX = '.dylib'
  , BS_SUFFIX = '.bridgesupport'

/**
 * Architecture-specific function that returns the Obj-C type from one of
 * these BridgeSupport XML nodes.
 */
var getType;
if (process.arch == 'x64')
  getType = function (node) {
    var a = node.attributes;
    return a.type64 || a.type;
  }
else
  getType = function (node) {
    return node.attributes.type;
  }

/**
 * Attempts to retrieve the BridgeSupport files for the given framework.
 * It synchronously reads the contents of the bridgesupport files and parses
 * them in order to add the symbols that the Obj-C runtime functions cannot
 * determine.
 */
function bridgesupport (fw, _global) {

  var bridgeSupportDir = join(fw.basePath, 'Resources', 'BridgeSupport')
    , bridgeSupportXML = join(bridgeSupportDir, fw.name + BS_SUFFIX)
    , bridgeSupportDylib = join(bridgeSupportDir, fw.name + DY_SUFFIX)

  // If there's no BridgeSupport file, then just return the empty object...
  if (!exists(bridgeSupportXML)) {
    //console.warn('No BridgeSupport files found for framework "%s" at: %s', fw.name, bridgeSupportXML);
    return;
  }

  if (exists(bridgeSupportDylib)) {
    fw.inline = core.dlopen(bridgeSupportDylib);
  }

  var contents = fs.readFileSync(bridgeSupportXML, 'utf8')
    , parser = sax.parser(true)
    , gotEnd = false
    // For processing C functions
    , curName
    , curRtnType
    , curArgTypes
    , isInline

  parser.onerror = function (e) { throw e; }
  parser.onopentag = function (node) {
    //console.error(node);
    switch (node.name) {
      case 'depends_on':
        bridgesupport.import(node.attributes.path);
        break;
      case 'class':
        break;
      case 'method':
        break;
      case 'arg':
        if (curName) {
          // class methods also have args, we only want functions though
          curArgTypes.push(getType(node));
        }
        break;
      case 'retval':
        if (curName) {
          // class methods also have retvals, we only want functions though
          curRtnType = getType(node);
        }
        break;
      case 'signatures':
        // ignore
        break;
      case 'string_constant':
        _global[node.attributes.name] = node.attributes.value;
        break;
      case 'enum':
        _global[node.attributes.name] = parseInt(node.attributes.value);
        break;
      case 'struct':
        break;
      case 'field':
        //console.error(node);
        break;
      case 'cftype':
        break;
      case 'constant':
        try {
          var ptr = fw.lib.get(node.attributes.name);
          // TODO: I'm like 99% sure I need to deref the pointer before wrapping,
          //       but I haven't tested yet...
          _global[node.attributes.name] = core.wrapValue(ptr, node.attributes.type);
        } catch (e) {
          //console.error(e);
          //console.error(node);
        }
        break;
      case 'function':
        curName = node.attributes.name;
        curRtnType = 'v';
        curArgTypes = [];
        isInline = node.attributes.inline == 'true';
        // TODO: is variadic? will require a 'function generator'
        break;
      case 'args':
        break;
      case 'opaque':
        break;
      case 'informal_protocol':
        break;
      case 'function_alias':
        break;
      default:
        throw new Error('unkown tag: '+ node.name);
        break;
    }
  };
  parser.onclosetag = function (node) {
    switch (node) {
      case 'function':
        // Binded functions will be lazy-loaded. We simply define a getter that
        // does the creation magic the first time, and replaces the getter with
        // the binded function
        (function (curName, curRtnType, curArgTypes, isInline) {
          if (isInline && !fw.inline) throw new Error('declared inline but could not find inline dylib!');
          _global.__defineGetter__(curName, function () {
            // TODO: Handle 'variadic' arg functions (NSLog), will require
            //       a "function generator" to get a Function from the passed
            //       in args (and guess at the types that were passed in...)
            var f = core.Function(curName, types.map(curRtnType), curArgTypes.map(types.map), false, isInline ? fw.inline : fw.lib);
            delete _global[curName];
            // The unwrapper function unwraps passed in arguments,
            // and wraps up the result if necessary.
            function unwrapper () {
              var args = core.unwrapValues(arguments, curArgTypes)
                , rtn = f.apply(null, args)
              return core.wrapValue(rtn, curRtnType)
            }
            // attach the rtn and arg types to the result Function, nice in the REPL
            unwrapper.func = curName;
            unwrapper.rtn = curRtnType;
            unwrapper.args = curArgTypes;
            return _global[curName] = unwrapper;
          });
        })(curName, curRtnType, curArgTypes, isInline);
        curName = null;
        break;
    }
  };
  parser.onend = function () {
    gotEnd = true;
  };

  // Parse the contents of the file. This should happen synchronously.
  parser.write(contents).close();

  if (!gotEnd) {
    throw new Error('could not parse BridgeSupport files synchronously');
  }
}
module.exports = bridgesupport;
<commit_msg>Lazy-load the <constant>s, faster load time, no try-catch.<commit_after>/**
 * This module takes care of loading the BridgeSupport XML files for a given
 * framework, and parsing the data into the given framework object.
 */

var fs = require('fs')
  , sax = require('sax')
  , path = require('path')
  , core = require('./core')
  , types = require('./types')
  , join = path.join
  , basename = path.basename
  , exists = path.existsSync
  , DY_SUFFIX = '.dylib'
  , BS_SUFFIX = '.bridgesupport'

/**
 * Architecture-specific function that returns the Obj-C type from one of
 * these BridgeSupport XML nodes.
 */
var getType;
if (process.arch == 'x64')
  getType = function (node) {
    var a = node.attributes;
    return a.type64 || a.type;
  }
else
  getType = function (node) {
    return node.attributes.type;
  }

/**
 * Attempts to retrieve the BridgeSupport files for the given framework.
 * It synchronously reads the contents of the bridgesupport files and parses
 * them in order to add the symbols that the Obj-C runtime functions cannot
 * determine.
 */
function bridgesupport (fw, _global) {

  var bridgeSupportDir = join(fw.basePath, 'Resources', 'BridgeSupport')
    , bridgeSupportXML = join(bridgeSupportDir, fw.name + BS_SUFFIX)
    , bridgeSupportDylib = join(bridgeSupportDir, fw.name + DY_SUFFIX)

  // If there's no BridgeSupport file, then just return the empty object...
  if (!exists(bridgeSupportXML)) {
    //console.warn('No BridgeSupport files found for framework "%s" at: %s', fw.name, bridgeSupportXML);
    return;
  }

  if (exists(bridgeSupportDylib)) {
    fw.inline = core.dlopen(bridgeSupportDylib);
  }

  var contents = fs.readFileSync(bridgeSupportXML, 'utf8')
    , parser = sax.parser(true)
    , gotEnd = false
    // For processing C functions
    , curName
    , curRtnType
    , curArgTypes
    , isInline

  parser.onerror = function (e) { throw e; }
  parser.onopentag = function (node) {
    //console.error(node);
    switch (node.name) {
      case 'depends_on':
        bridgesupport.import(node.attributes.path);
        break;
      case 'class':
        break;
      case 'method':
        break;
      case 'arg':
        if (curName) {
          // class methods also have args, we only want functions though
          curArgTypes.push(getType(node));
        }
        break;
      case 'retval':
        if (curName) {
          // class methods also have retvals, we only want functions though
          curRtnType = getType(node);
        }
        break;
      case 'signatures':
        // ignore
        break;
      case 'string_constant':
        _global[node.attributes.name] = node.attributes.value;
        break;
      case 'enum':
        _global[node.attributes.name] = parseInt(node.attributes.value);
        break;
      case 'struct':
        break;
      case 'field':
        //console.error(node);
        break;
      case 'cftype':
        break;
      case 'constant':
        (function (name, type) {
          _global.__defineGetter__(name, function () {
            var ptr = fw.lib.get(name);
            // TODO: I'm like 99% sure I need to deref the pointer before
            //       wrapping, but I haven't tested yet...
            delete _global[name];
            return _global[name] = core.wrapValue(ptr, type);
          });
        })(node.attributes.name, getType(node));
        break;
      case 'function':
        curName = node.attributes.name;
        curRtnType = 'v';
        curArgTypes = [];
        isInline = node.attributes.inline == 'true';
        // TODO: is variadic? will require a 'function generator'
        break;
      case 'args':
        break;
      case 'opaque':
        break;
      case 'informal_protocol':
        break;
      case 'function_alias':
        break;
      default:
        throw new Error('unkown tag: '+ node.name);
        break;
    }
  };
  parser.onclosetag = function (node) {
    switch (node) {
      case 'function':
        // Binded functions will be lazy-loaded. We simply define a getter that
        // does the creation magic the first time, and replaces the getter with
        // the binded function
        (function (curName, curRtnType, curArgTypes, isInline) {
          if (isInline && !fw.inline) throw new Error('declared inline but could not find inline dylib!');
          _global.__defineGetter__(curName, function () {
            // TODO: Handle 'variadic' arg functions (NSLog), will require
            //       a "function generator" to get a Function from the passed
            //       in args (and guess at the types that were passed in...)
            var f = core.Function(curName, types.map(curRtnType), curArgTypes.map(types.map), false, isInline ? fw.inline : fw.lib);
            delete _global[curName];
            // The unwrapper function unwraps passed in arguments,
            // and wraps up the result if necessary.
            function unwrapper () {
              var args = core.unwrapValues(arguments, curArgTypes)
                , rtn = f.apply(null, args)
              return core.wrapValue(rtn, curRtnType)
            }
            // attach the rtn and arg types to the result Function, nice in the REPL
            unwrapper.func = curName;
            unwrapper.rtn = curRtnType;
            unwrapper.args = curArgTypes;
            return _global[curName] = unwrapper;
          });
        })(curName, curRtnType, curArgTypes, isInline);
        curName = null;
        break;
    }
  };
  parser.onend = function () {
    gotEnd = true;
  };

  // Parse the contents of the file. This should happen synchronously.
  parser.write(contents).close();

  if (!gotEnd) {
    throw new Error('could not parse BridgeSupport files synchronously');
  }
}
module.exports = bridgesupport;
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var browserify = require('browserify');
var browserPack = require('browser-pack');
var exec = require('child_process').exec;
var sys = require('sys');
var puts = function(error, stdout, stderr) {
  if (error) console.log(error);
  //sys.puts(stdout);
  //sys.puts(stderr);
};

var pack = function (params) {
  var file = require.resolve('soop');
  var dir = file.substr(0, file.length - String('soop.js').length);
  var preludePath = dir + 'example/custom_prelude.js';
  params.raw = true;
  params.sourceMapPrefix = '//#';
  params.prelude = fs.readFileSync(preludePath, 'utf8');
  params.preludePath = preludePath;
  return browserPack(params);
};

var modules = [
  'Address',
  'Block',
  'Bloom',
  'Buffers.monkey',
  'Connection',
  'Deserialize',
  'Gruntfile',
  'Number.monkey',
  'Opcode',
  'Peer',
  'PeerManager',
  'PrivateKey',
  'RpcClient',
  'Key',
  'SIN',
  'SINKey',
  'Script',
  'ScriptInterpreter',
  'Sign',
  'Transaction',
  'Wallet',
  'WalletKey',
  'config',
  'const',
  'networks',
  'util/log',
  'util/util',
  'util/EncodedData',
  'util/VersionedData',
];

var createBitcore = function(opts) {

  opts.dir = opts.dir || '';

  // concat browser vendor files
  exec('cd ' + opts.dir + 'browser; sh concat.sh', puts);

  if (!opts.includeall && (!opts.submodules || opts.submodules.length === 0)) {
    if (!opts.stdout) console.log('Must use either -s or -a option. For more info use the --help option');
    process.exit(1);
  }

  if (opts.submodules) {
    for (var i = 0; i < opts.submodules.length; i++) {
      var sm = opts.submodules[i];
      if (modules.indexOf(sm) === -1) throw new Error('Unknown submodule ' + sm);
    }
  }

  var bopts = {
    pack: pack,
    debug: true,
    standalone: 'bitcore',
    insertGlobals: true
  };
  var b = browserify(bopts);

  b.require(opts.dir + 'browserify-bignum/bignumber.js', {
    expose: 'bignum'
  });
  b.require(opts.dir + 'browserify-buffertools/buffertools.js', {
    expose: 'buffertools'
  });
  b.require(opts.dir + 'base58-native', {
    expose: 'base58-native'
  });
  b.require('./' + opts.dir + 'bitcore', {
    expose: 'bitcore'
  });
  modules.forEach(function(m) {
    if (opts.includeall || opts.submodules.indexOf(m) > -1) {
      if (!opts.stdout) console.log('Including ' + m + ' in the browser bundle');
      b.require('./' + opts.dir + m + '.js', {
        expose: './' + m
      });
    }
  });

  if (!opts.dontminify) {
    b.transform({
      global: true
    }, 'uglifyify');
  }

  var bundle = b.bundle();
  return bundle;
};

var createTestData = function() {
  var bopts = {
    pack: pack,
    debug: true,
    standalone: 'testdata',
    insertGlobals: true
  };
  var tb = browserify(bopts);
  tb.require('./test/testdata', {
    expose: 'testdata'
  });
  tb.transform('brfs');

  return tb.bundle();
};

if (require.main === module) {
  var list = function(val) {
    return val.split(',');
  };
  var program = require('commander');
  program
    .version('0.0.1')
    .option('-a, --includeall', 'Include all submodules.')
    .option('-d, --dontminify', 'Don\'t minify the code.')
    .option('-o, --stdout', 'Specify output as stdout')
    .option('-s, --submodules <items>', 'Include the listed comma-separated submodules.', list)
    .parse(process.argv);
  if (!program.stdout) {
    var testBundle = createTestData(program);
    testBundle.pipe(fs.createWriteStream('browser/testdata.js'));
  }
  var bitcoreBundle = createBitcore(program);
  bitcoreBundle.pipe(program.stdout ? process.stdout : fs.createWriteStream('browser/bundle.js'));
}

module.exports.createBitcore = createBitcore;
module.exports.createTestData = createTestData;
<commit_msg>base dir<commit_after>'use strict';

var fs = require('fs');
var browserify = require('browserify');
var browserPack = require('browser-pack');
var exec = require('child_process').exec;
var sys = require('sys');
var puts = function(error, stdout, stderr) {
  if (error) console.log(error);
  //sys.puts(stdout);
  //sys.puts(stderr);
};

var pack = function (params) {
  var file = require.resolve('soop');
  var dir = file.substr(0, file.length - String('soop.js').length);
  var preludePath = dir + 'example/custom_prelude.js';
  params.raw = true;
  params.sourceMapPrefix = '//#';
  params.prelude = fs.readFileSync(preludePath, 'utf8');
  params.preludePath = preludePath;
  return browserPack(params);
};

var modules = [
  'Address',
  'Block',
  'Bloom',
  'Buffers.monkey',
  'Connection',
  'Deserialize',
  'Gruntfile',
  'Number.monkey',
  'Opcode',
  'Peer',
  'PeerManager',
  'PrivateKey',
  'RpcClient',
  'Key',
  'SIN',
  'SINKey',
  'Script',
  'ScriptInterpreter',
  'Sign',
  'Transaction',
  'Wallet',
  'WalletKey',
  'config',
  'const',
  'networks',
  'util/log',
  'util/util',
  'util/EncodedData',
  'util/VersionedData',
];

var createBitcore = function(opts) {

  opts.dir = opts.dir || '';

  // concat browser vendor files
  exec('cd ' + opts.dir + 'browser; sh concat.sh', puts);

  if (!opts.includeall && (!opts.submodules || opts.submodules.length === 0)) {
    if (!opts.stdout) console.log('Must use either -s or -a option. For more info use the --help option');
    process.exit(1);
  }

  if (opts.submodules) {
    for (var i = 0; i < opts.submodules.length; i++) {
      var sm = opts.submodules[i];
      if (modules.indexOf(sm) === -1) throw new Error('Unknown submodule ' + sm);
    }
  }

  var bopts = {
    pack: pack,
    debug: true,
    standalone: 'bitcore',
    insertGlobals: true
  };
  var b = browserify(bopts);

  b.require(opts.dir + 'browserify-bignum/bignumber.js', {
    expose: 'bignum'
  });
  b.require(opts.dir + 'browserify-buffertools/buffertools.js', {
    expose: 'buffertools'
  });
  b.require(opts.dir + 'base58-native', {
    expose: 'base58-native'
  });
  b.require('./' + opts.dir + 'bitcore', {
    expose: 'bitcore'
  });
  modules.forEach(function(m) {
    if (opts.includeall || opts.submodules.indexOf(m) > -1) {
      if (!opts.stdout) console.log('Including ' + m + ' in the browser bundle');
      b.require('./' + opts.dir + m + '.js', {
        expose: './' + m
      });
    }
  });

  if (!opts.dontminify) {
    b.transform({
      global: true
    }, 'uglifyify');
  }

  var bundle = b.bundle();
  return bundle;
};

var createTestData = function() {
  var bopts = {
    pack: pack,
    debug: true,
    standalone: 'testdata',
    insertGlobals: true
  };
  var tb = browserify(bopts);
  tb.require('./test/testdata', {
    expose: 'testdata'
  });
  tb.transform('brfs');

  return tb.bundle();
};

if (require.main === module) {
  var list = function(val) {
    return val.split(',');
  };
  var program = require('commander');
  program
    .version('0.0.1')
    .option('-a, --includeall', 'Include all submodules.')
    .option('-d, --dontminify', 'Don\'t minify the code.')
    .option('-o, --stdout', 'Specify output as stdout')
    .option('-D, --dir', 'Specify a base directory')
    .option('-s, --submodules <items>', 'Include the listed comma-separated submodules.', list)
    .parse(process.argv);
  if (!program.stdout) {
    var testBundle = createTestData(program);
    testBundle.pipe(fs.createWriteStream('browser/testdata.js'));
  }
  var bitcoreBundle = createBitcore(program);
  bitcoreBundle.pipe(program.stdout ? process.stdout : fs.createWriteStream('browser/bundle.js'));
}

module.exports.createBitcore = createBitcore;
module.exports.createTestData = createTestData;
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var Promise = require('es6-promise').Promise;

function buildFilter(filters) {
  var filters = (filters instanceof Array) ? filters.slice() : [filters];
  var filterArray = [];

  if (filters.length === 0) return null;

  while(filters.length > 0) {
    var filter = filters.shift();
    filterArray.push('\\/?' + filter.replace(/\./g, '\\.')
       .replace(/(\*?)(\*)(?!\*)/g, function(match, prefix) {
          if(prefix == '*') {
             return match;
          }
          return '[^\\/]*';
       })
       .replace(/\?/g, '[^\\/]?')
       .replace(/\*\*/g, '\.*')
       .replace(/([\-\+\|])/g, '\\$1')
      );
  }
  return new RegExp('^' + filterArray.join('|') + '$', 'i');
}

function readfiles(dir, options, callback) {
  if (typeof options === 'function' || options === null) {
    callback = options;
    options = {};
  }
  options = options || {};
  callback = typeof callback === 'function' ? callback : function () {};

  return new Promise(function (resolve, reject) {

    var files = [];
    var subdirs = [];
    var filterRegExp = options.filter && buildFilter(options.filter);

    (function traverseDir(dirpath, done) {
      fs.readdir(dirpath, function (err, fileList) {
        if (err) {
          // if rejectOnError is not false, reject the promise
          if (options.rejectOnError !== false) {
            return reject(err);
          }
          return done(files);
        }

        // reverse the order of the files if the reverse option is true
        if (options.reverse === true) {
          fileList = fileList.reverse();
        }

        (function next() {

          // if the file list is empty then call done
          if (fileList.length === 0) {
            done(files);
            return;
          }

          var filename = fileList.shift();
          var relFilename = path.join(subdirs.join('/'), filename);
          var fullpath = path.join(dirpath, filename);

          // skip file if it's a hidden file and the hidden option is not set
          if (options.hidden !== true && /^\./.test(filename)) {
            return next();
          }

          // stat the full path
          fs.stat(fullpath, function (err, stat) {

            if (err) {
              // call callback with the error
              var result = callback(err, relFilename, null, stat);

              // if callback result is a function then call the result with next as a parameter
              if (typeof result === 'function' && !err) {
                return result(next);
              }

              // if rejectOnError is not false, reject the promise
              if (options.rejectOnError !== false) {
                return reject(err);
              }

              return next();
            }

            if (stat.isDirectory()) {

              // limit the depth of the traversal if depth is defined
              if (!isNaN(options.depth) && options.depth >= 0 && (subdirs.length + 1) > options.depth) {
                return next();
              }

              // traverse the sub-directory
              subdirs.push(filename);
              traverseDir(fullpath, function () {
                subdirs.pop();
                next();
              });

            } else if (stat.isFile()) {

              // test filters, if it does not match move to next file
              if (filterRegExp && !filterRegExp.test('/' + relFilename)) {
                return next();
              }

              // set the format of the output filename
              var outputName = relFilename;
              if (options.filenameFormat === readfiles.FULL_PATH) {
                outputName = fullpath;
              }else if (options.filenameFormat === readfiles.FILENAME) {
                outputName = filename;
              }
              files.push(outputName);

              // promise to handle file reading (if not disabled)
              new Promise(function (resolve) {
                if (options.readContents === false) {
                  return resolve(null);
                }
                // read the file
                fs.readFile(fullpath, options.encoding || 'utf8', function (err, content) {
                  if (err) throw err;
                  resolve(content);
                });
              }).then(function (content) {
                // call the callback with the content
                var result = callback(err, outputName, content, stat);

                // if callback result is a function then call the result with next as a parameter
                if (typeof result === 'function' && !err) {
                  return result(next);
                }
                // call the next if async is not true
                options.async !== true && next();
              }).catch(function (err) {
                if (options.rejectOnError !== false) {
                  return reject(err);
                }

                next();
              });

            } else {
              next();
            }

          });
        })();
      });
    })(dir, resolve);
  });
}

readfiles.RELATIVE = 0;
readfiles.FULL_PATH = 1;
readfiles.FILENAME = 2;

module.exports = readfiles;<commit_msg>Update readfiles.js<commit_after>var fs = require('fs');
var path = require('path');
var Promise = require('es6-promise').Promise;

function buildFilter(filters) {
  var filters = (filters instanceof Array) ? filters.slice() : [filters];
  var filterArray = [];

  if (filters.length === 0) return null;

  while(filters.length > 0) {
    var filter = filters.shift();
    filterArray.push('\\/?' + filter.replace(/\./g, '\\.')
       .replace(/(\*?)(\*)(?!\*)/g, function(match, prefix) {
          if(prefix == '*') {
             return match;
          }
          return '[^\\/]*';
       })
       .replace(/\?/g, '[^\\/]?')
       .replace(/\*\*/g, '.*')
       .replace(/([\-\+\|])/g, '\\$1')
      );
  }
  return new RegExp('^' + filterArray.join('|') + '$', 'i');
}

function readfiles(dir, options, callback) {
  if (typeof options === 'function' || options === null) {
    callback = options;
    options = {};
  }
  options = options || {};
  callback = typeof callback === 'function' ? callback : function () {};

  return new Promise(function (resolve, reject) {

    var files = [];
    var subdirs = [];
    var filterRegExp = options.filter && buildFilter(options.filter);

    (function traverseDir(dirpath, done) {
      fs.readdir(dirpath, function (err, fileList) {
        if (err) {
          // if rejectOnError is not false, reject the promise
          if (options.rejectOnError !== false) {
            return reject(err);
          }
          return done(files);
        }

        // reverse the order of the files if the reverse option is true
        if (options.reverse === true) {
          fileList = fileList.reverse();
        }

        (function next() {

          // if the file list is empty then call done
          if (fileList.length === 0) {
            done(files);
            return;
          }

          var filename = fileList.shift();
          var relFilename = path.join(subdirs.join('/'), filename);
          var fullpath = path.join(dirpath, filename);

          // skip file if it's a hidden file and the hidden option is not set
          if (options.hidden !== true && /^\./.test(filename)) {
            return next();
          }

          // stat the full path
          fs.stat(fullpath, function (err, stat) {

            if (err) {
              // call callback with the error
              var result = callback(err, relFilename, null, stat);

              // if callback result is a function then call the result with next as a parameter
              if (typeof result === 'function' && !err) {
                return result(next);
              }

              // if rejectOnError is not false, reject the promise
              if (options.rejectOnError !== false) {
                return reject(err);
              }

              return next();
            }

            if (stat.isDirectory()) {

              // limit the depth of the traversal if depth is defined
              if (!isNaN(options.depth) && options.depth >= 0 && (subdirs.length + 1) > options.depth) {
                return next();
              }

              // traverse the sub-directory
              subdirs.push(filename);
              traverseDir(fullpath, function () {
                subdirs.pop();
                next();
              });

            } else if (stat.isFile()) {

              // test filters, if it does not match move to next file
              if (filterRegExp && !filterRegExp.test('/' + relFilename)) {
                return next();
              }

              // set the format of the output filename
              var outputName = relFilename;
              if (options.filenameFormat === readfiles.FULL_PATH) {
                outputName = fullpath;
              }else if (options.filenameFormat === readfiles.FILENAME) {
                outputName = filename;
              }
              files.push(outputName);

              // promise to handle file reading (if not disabled)
              new Promise(function (resolve) {
                if (options.readContents === false) {
                  return resolve(null);
                }
                // read the file
                fs.readFile(fullpath, options.encoding || 'utf8', function (err, content) {
                  if (err) throw err;
                  resolve(content);
                });
              }).then(function (content) {
                // call the callback with the content
                var result = callback(err, outputName, content, stat);

                // if callback result is a function then call the result with next as a parameter
                if (typeof result === 'function' && !err) {
                  return result(next);
                }
                // call the next if async is not true
                options.async !== true && next();
              }).catch(function (err) {
                if (options.rejectOnError !== false) {
                  return reject(err);
                }

                next();
              });

            } else {
              next();
            }

          });
        })();
      });
    })(dir, resolve);
  });
}

readfiles.RELATIVE = 0;
readfiles.FULL_PATH = 1;
readfiles.FILENAME = 2;

module.exports = readfiles;
<|endoftext|>


<commit_before>if (typeof module === "object" && typeof require === "function") {
    module.exports = {
        specification: require("./reporters/specification"),
        jsonProxy: require("./reporters/json-proxy"),
        xml: require("./reporters/xml"),
        tap: require("./reporters/tap"),
        brief: require("./reporters/brief"),
        html: require("./reporters/html"),
        teamcity: require("./reporters/teamcity"),

        load: function (reporter) {
            if (module.exports[reporter]) {
                return module.exports[reporter];
            }

            return require(reporter);
        }
    };
} else if (typeof define === "function") {
    define(["./reporters/json-proxy",
            "./reporters/xml",
            "./reporters/html"], function (jsonProxy, xml, html) {
        var reporters = {
            jsonProxy: jsonProxy,
            xml: xml,
            html: html,
            load: function (reporter) {
                return reporters[reporter];
            }
        };

        return reporters;
    });
} else {
    buster.reporters = buster.reporters || {};
    buster.reporters.load = function (reporter) {
        return buster.reporters[reporter];
    };
}
<commit_msg>Expose default reporter<commit_after>if (typeof module === "object" && typeof require === "function") {
    module.exports = {
        specification: require("./reporters/specification"),
        jsonProxy: require("./reporters/json-proxy"),
        xml: require("./reporters/xml"),
        tap: require("./reporters/tap"),
        brief: require("./reporters/brief"),
        html: require("./reporters/html"),
        teamcity: require("./reporters/teamcity"),

        load: function (reporter) {
            if (module.exports[reporter]) {
                return module.exports[reporter];
            }

            return require(reporter);
        }
    };

    module.exports.defaultReporter = module.exports.brief;
} else if (typeof define === "function") {
    define(["./reporters/json-proxy",
            "./reporters/xml",
            "./reporters/html"], function (jsonProxy, xml, html) {
        var reporters = {
            jsonProxy: jsonProxy,
            xml: xml,
            html: html,
            load: function (reporter) {
                return reporters[reporter];
            }
        };

        reporters.defaultReporter = reporters.brief;
        return reporters;
    });
} else {
    buster.reporters = buster.reporters || {};
    buster.reporters.defaultReporter = buster.reporters.brief;
    buster.reporters.load = function (reporter) {
        return buster.reporters[reporter];
    };
}
<|endoftext|>


<commit_before>// @flow

import {performance, isResourceTimingAvailable} from './performance';
import type {PageLoadBeacon} from './types';
import {createTrie} from './trie';
import {win} from './browser';
import {info} from './debug';
import vars from './vars';

// See https://w3c.github.io/resource-timing/
// See https://www.w3.org/TR/hr-time/

const urlMaxLength = 255;

const initiatorTypes = {
  'other': 0,
  'img': 1,
  'link': 2,
  'script': 3,
  'css': 4,
  'xmlhttprequest': 5,
  'html': 6,
  // IMAGE element inside a SVG
  'image': 7
};

const cachingTypes = {
  unknown: 0,
  cached: 1,
  validated: 2,
  fullLoad: 3
};

export function addResourceTimings(beacon: PageLoadBeacon) {
  if (isResourceTimingAvailable && win.JSON) {
    const entries = getEntriesTransferFormat(performance.getEntriesByType('resource'));
    beacon['res'] = win.JSON.stringify(entries);
  } else if (DEBUG) {
    info('Resource timing not supported.');
  }
}

export function getEntriesTransferFormat(performanceEntries: Array<Object>) {
  const trie = createTrie();

  for (let i = 0, len = performanceEntries.length; i < len; i++) {
    const entry = performanceEntries[i];

    let url = entry.name;
    if (url.length > urlMaxLength) {
      url = url.substring(0, urlMaxLength);
    }
    trie.addItem(url, serializeEntry(entry));
  }

  return trie.toJs();
}

function serializeEntry(entry: Object) {
  const result = [
    Math.round(entry['startTime'] - vars.highResTimestampReference),
    Math.round(entry['duration']),
    initiatorTypes[entry['initiatorType']] || initiatorTypes['other']
  ];

  // When timing data is available, we can provide additional information about
  // caching and resource sizes.
  if (typeof entry['transferSize'] === 'number' &&
      typeof entry['encodedBodySize'] === 'number' &&
      // All this information may not be available due to cross-origin.
      entry['encodedBodySize'] > 0) {
    if (entry['transferSize'] === 0) {
      result.push(cachingTypes.cached);
    } else if (entry['transferSize'] < entry['encodedBodySize']) {
      result.push(cachingTypes.validated);
    } else {
      result.push(cachingTypes.fullLoad);
    }

    result.push(entry['encodedBodySize']);
  }

  return result.join(',');
}
<commit_msg>Exclude XHR resource timings from page load beacon after XHR instrumentation<commit_after>// @flow

import {performance, isResourceTimingAvailable} from './performance';
import type {PageLoadBeacon} from './types';
import {createTrie} from './trie';
import {win} from './browser';
import {info} from './debug';
import vars from './vars';

// See https://w3c.github.io/resource-timing/
// See https://www.w3.org/TR/hr-time/

const urlMaxLength = 255;

const initiatorTypes = {
  'other': 0,
  'img': 1,
  'link': 2,
  'script': 3,
  'css': 4,
  'xmlhttprequest': 5,
  'html': 6,
  // IMAGE element inside a SVG
  'image': 7
};

const cachingTypes = {
  unknown: 0,
  cached: 1,
  validated: 2,
  fullLoad: 3
};

export function addResourceTimings(beacon: PageLoadBeacon) {
  if (isResourceTimingAvailable && win.JSON) {
    const entries = getEntriesTransferFormat(performance.getEntriesByType('resource'));
    beacon['res'] = win.JSON.stringify(entries);
  } else if (DEBUG) {
    info('Resource timing not supported.');
  }
}

export function getEntriesTransferFormat(performanceEntries: Array<Object>) {
  const trie = createTrie();

  for (let i = 0, len = performanceEntries.length; i < len; i++) {
    const entry = performanceEntries[i];

    let url = entry.name;
    if (url.length > urlMaxLength) {
      url = url.substring(0, urlMaxLength);
    }

    // We provide more detailed XHR insights via our XHR instrumentation.
    // The XHR instrumentation is available once the initialization was executed
    // (which is completely synchronous).
    if (entry['initiatorType'] !== 'xmlhttprequest' || entry['startTime'] < vars.highResTimestampReference) {
      trie.addItem(url, serializeEntry(entry));
    }
  }

  return trie.toJs();
}

function serializeEntry(entry: Object) {
  const result = [
    Math.round(entry['startTime'] - vars.highResTimestampReference),
    Math.round(entry['duration']),
    initiatorTypes[entry['initiatorType']] || initiatorTypes['other']
  ];

  // When timing data is available, we can provide additional information about
  // caching and resource sizes.
  if (typeof entry['transferSize'] === 'number' &&
      typeof entry['encodedBodySize'] === 'number' &&
      // All this information may not be available due to cross-origin.
      entry['encodedBodySize'] > 0) {
    if (entry['transferSize'] === 0) {
      result.push(cachingTypes.cached);
    } else if (entry['transferSize'] < entry['encodedBodySize']) {
      result.push(cachingTypes.validated);
    } else {
      result.push(cachingTypes.fullLoad);
    }

    result.push(entry['encodedBodySize']);
  }

  return result.join(',');
}
<|endoftext|>


<commit_before>var logger          = require('./logger.js').getLogger('Resource')
    , mod_util      = require('util')
    , mod_events    = require('events')
    , mod_http      = require('http')
    , mod_fs        = require('fs')
    , mod_url       = require('url')

function uuid() {
    return new Date().getTime() + '-' + Math.round(Math.random()*10000);
}

function Resource(url, data) {
    this._state = Resource.STATE.INIT;
    if (typeof url !== 'undefined' && typeof data !== 'undefined') {
        this.url = url;
        this.data = new Buffer(data);
    } else {
        this.data = null;
    }

    this.uuid = uuid();
};
mod_util.inherits(Resource, mod_events.EventEmitter);

Object.defineProperty(Resource.prototype, 'state', {
    get : function () {
        return this._state;
    },
    set : function (val) {
        if ('number' !== typeof val) throw Error('number expected, got ' + val);
        if (val !== this._state) {
            this._state = val;
            this.emit('stateChanged', this);
        }
    }
});

Resource.prototype.addDependency = function (res) {
    this._requiredResources[res.uuid] = res;
    var self = this;
    res.addListener('stateChanged', function () {
        //logger.debug('state changed from sub ' + this.uuid);
        self._onDepStateChange.call(self, res);
    });
};

Resource.prototype._onDepStateChange = function (resource) {
    //logger.debug('_onDepStateChange from ' + resource.uuid + '@' + this.uuid);
    var state = Resource.STATE.READY;
    for (rn in this._requiredResources) {
        state = Math.min(this._requiredResources[rn].state, state);
    }
    this.state = state;
};

Resource.prototype.load = function (type) {
    throw new Error('not implemented');
}

Resource.STATE = {
    INIT        : 0
    , LOADING     : 2
    , WAITING     : 4
    , READY       : 6
};

exports.Resource = Resource;

function FileResource() {
    Resource.apply(this, arguments);
}
mod_util.inherits(FileResource, Resource);

FileResource.prototype.load = function (file) {
    if ('undefined' === typeof file || file.indexOf('file://') !== 0) {
        throw new Error('missing or faulty argument');
    }
    this.url = file;
    this.state = Resource.STATE.LOADING;
    var self = this,
        file = file.substring(7);
    mod_fs.readFile(file, function (err, data) {
        if (err) { throw err; }
        self.data = data;
        self.state = Resource.STATE.READY;
    });
};

function HttpResource() {
    Resource.apply(this);
}
mod_util.inherits(HttpResource, Resource);

HttpResource.prototype.load =  function (url) {
    if ('undefined' === typeof url || url.indexOf('http://') !== 0) {
        throw new Error('missing or faulty argument');
    }
    var self = this,
        req;
    this.url = url;
    this.state = Resource.STATE.LOADING;
    this.content = '';
    this._options = mod_url.parse(url);

    req = mod_http.get(this._options, function (res) {
        if (res.statusCode >= 400 && res.statusCode <= 500) {
            throw new Error('URL could not be loaded, code ' + res.statusCode
                + ', url ' + self._options.host + ':' + self._options.port + self._options.path);
        }
        res.on('data', function (data) {
            self.data = data;
        });
        res.on('end', function () {
            self.state = Resource.STATE.READY;
        });
    });
};

exports.FileResource = FileResource;
exports.HttpResource = HttpResource;<commit_msg>added RenderedViewResource for parsed view templates. Ugly name, find better, hugh<commit_after>var logger          = require('./logger.js').getLogger('Resource')
    , mod_util      = require('util')
    , mod_events    = require('events')
    , mod_http      = require('http')
    , mod_fs        = require('fs')
    , mod_url       = require('url')

function uuid() {
    return new Date().getTime() + '-' + Math.round(Math.random()*10000);
}

function Resource(url, data) {
    this._state = Resource.STATE.INIT;
    if (typeof url !== 'undefined' && typeof data !== 'undefined') {
        this.url = url;
        this.data = new Buffer(data);
        this._state = Resource.STATE.READY;
    } else {
        this.data = null;
    }

    this.uuid = uuid();
};
mod_util.inherits(Resource, mod_events.EventEmitter);

Object.defineProperty(Resource.prototype, 'state', {
    get : function () {
        return this._state;
    },
    set : function (val) {
        if ('number' !== typeof val) throw Error('number expected, got ' + val);
        if (val !== this._state) {
            this._state = val;
            this.emit('stateChanged', this);
        }
    }
});

Resource.prototype.addDependency = function (res) {
    this._requiredResources[res.uuid] = res;
    var self = this;
    res.addListener('stateChanged', function () {
        //logger.debug('state changed from sub ' + this.uuid);
        self._onDepStateChange.call(self, res);
    });
};

Resource.prototype._onDepStateChange = function (resource) {
    //logger.debug('_onDepStateChange from ' + resource.uuid + '@' + this.uuid);
    var state = Resource.STATE.READY;
    for (rn in this._requiredResources) {
        state = Math.min(this._requiredResources[rn].state, state);
    }
    this.state = state;
};

Resource.prototype.load = function (type) {
    throw new Error('not implemented');
}

Resource.STATE = {
    INIT        : 0
    , LOADING     : 2
    , WAITING     : 4
    , READY       : 6
};

exports.Resource = Resource;

function FileResource() {
    Resource.apply(this, arguments);
}
mod_util.inherits(FileResource, Resource);

FileResource.prototype.load = function (file) {
    if ('undefined' === typeof file || file.indexOf('file://') !== 0) {
        throw new Error('missing or faulty argument');
    }
    this.url = file;
    this.state = Resource.STATE.LOADING;
    var self = this,
        file = file.substring(7);
    mod_fs.readFile(file, function (err, data) {
        if (err) { throw err; }
        self.data = data;
        self.state = Resource.STATE.READY;
    });
};

function HttpResource() {
    Resource.apply(this);
}
mod_util.inherits(HttpResource, Resource);

HttpResource.prototype.load =  function (url) {
    if ('undefined' === typeof url || url.indexOf('http://') !== 0) {
        throw new Error('missing or faulty argument');
    }
    var self = this,
        req;
    this.url = url;
    this.state = Resource.STATE.LOADING;
    this.content = '';
    this._options = mod_url.parse(url);

    req = mod_http.get(this._options, function (res) {
        if (res.statusCode >= 400 && res.statusCode <= 500) {
            throw new Error('URL could not be loaded, code ' + res.statusCode
                + ', url ' + self._options.host + ':' + self._options.port + self._options.path);
        }
        res.on('data', function (data) {
            self.data = data;
        });
        res.on('end', function () {
            self.state = Resource.STATE.READY;
        });
    });
};

function RenderedViewResource(url, data, elements, cssdeps, scriptdeps) {
    Resource.call(this, url, data);
    this.elements = elements;
    this.cssdeps = cssdeps;
    this.scriptdeps = scriptdeps;
}
mod_util.inherits(RenderedViewResource, Resource);

exports.FileResource = FileResource;
exports.HttpResource = HttpResource;
exports.RenderedViewResource = RenderedViewResource;<|endoftext|>


<commit_before>var request = require("needle"),
    async = require("async"),
    _ = require("lodash"),
    needle = require("needle"),
    util = require("util"),
    cfg = require("./cfg"),
    torrentStream = require("torrent-stream"),
    bencode = require("parse-torrent/node_modules/parse-torrent-file/node_modules/bencode"),
    parseTorrent = require("parse-torrent");

var downloadSources = cfg.retrieverSources || [];

var defaultHeaders = {
    "accept-charset" : "ISO-8859-1,utf-8;q=0.7,*;q=0.3",
    "accept-language" : "en-US,en;q=0.8",
    "accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36"
};

var downloader = async.queue(function(task, cb)
{
    setTimeout(cb, 500); /* This async queue is simply a rate limiter */

    var result, errors = [], sources = (task.url ? [{ formatted:task.url }] : []).concat(downloadSources);

    async.whilst(function() { return !result && sources.length }, function(innerCb)
    {
        var source = sources.shift(),
            innerCb = _.once(innerCb),
            url = source.formatted ? source.formatted : util.format(source.url, [ task.infoHash.toUpperCase() ]);

        needle.get(url, {
            open_timeout: 3500, read_timeout: 3500,
            agent: module.exports.getAgent(),
            follow_max: 3, compressed: true,
            headers: _.extend({ referer: source.url || source.formatted }, defaultHeaders)
        }, function(err, res, body) {
            if (err) { err.source = url; errors.push(err); return innerCb(); }
            else if (res && res.statusCode != 200) { errors.push(_.extend(new Error("status code "+res.statusCode), { source: url })); return innerCb() }

            if (!body) return innerCb();

            try {
                if (typeof(body) == "string") body = JSON.parse(body);
                body = body["piece length"] ? bencode.encode({ info: _.extend({ pieces: [] }, body) }) : body;
                result = parseTorrent(body);
                result.infoHash = task.infoHash;
                if (! result.files) throw new Error("no files found in torrent");
            } catch(e) { e.source = url; errors.push(e) };
            innerCb();
        });
    }, function()
    {
        if (! (result && result.infoHash)) return task.callback(errors.concat([new Error("Did not manage to download parsable torrent")]));
        task.callback(null, result);
    });
}, 2);

// TODO: ability to rate-limit that section of the code
// OR just use a rate-limited peer-search instead of torrent-stream's peer searching
function fetchTorrent(infoHash, opts, cb) {
    var engine = new torrentStream(infoHash, {
        connections: 30,
        trackers: cfg.fetchTorrentTrackers,
    });
    var cb = _.once(cb);

    engine.ready(function() {
        cb(null, engine.torrent);
        engine.destroy();
    });
    setTimeout(function() {
        cb(new Error("fetchTorrent timed out"));
        engine.destroy();
    }, 15 * 1000);
};

function downloadTorrent(infoHash, opts, cb)
{
    if (typeof(opts) == "function") cb = opts;
    if (! (opts && typeof(opts) == "object")) opts = {};

    downloader[opts.important ? "unshift" : "push"]({ infoHash: infoHash, callback: function(err, torrent) {
        if (err && opts.important) return fetchTorrent(infoHash, opts, cb);
        if (err) return cb(err);
        cb(null, torrent);
    }, url: opts.url })
}

module.exports = { retrieve: downloadTorrent };
module.exports.getAgent = function() { return undefined }; // dummy, to replace if you want your own agent
<commit_msg>simple require() for bencode<commit_after>var request = require("needle"),
    async = require("async"),
    _ = require("lodash"),
    needle = require("needle"),
    util = require("util"),
    cfg = require("./cfg"),
    torrentStream = require("torrent-stream"),
    bencode = require("bencode"),
    parseTorrent = require("parse-torrent");

var downloadSources = cfg.retrieverSources || [];

var defaultHeaders = {
    "accept-charset" : "ISO-8859-1,utf-8;q=0.7,*;q=0.3",
    "accept-language" : "en-US,en;q=0.8",
    "accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36"
};

var downloader = async.queue(function(task, cb)
{
    setTimeout(cb, 500); /* This async queue is simply a rate limiter */

    var result, errors = [], sources = (task.url ? [{ formatted:task.url }] : []).concat(downloadSources);

    async.whilst(function() { return !result && sources.length }, function(innerCb)
    {
        var source = sources.shift(),
            innerCb = _.once(innerCb),
            url = source.formatted ? source.formatted : util.format(source.url, [ task.infoHash.toUpperCase() ]);

        needle.get(url, {
            open_timeout: 3500, read_timeout: 3500,
            agent: module.exports.getAgent(),
            follow_max: 3, compressed: true,
            headers: _.extend({ referer: source.url || source.formatted }, defaultHeaders)
        }, function(err, res, body) {
            if (err) { err.source = url; errors.push(err); return innerCb(); }
            else if (res && res.statusCode != 200) { errors.push(_.extend(new Error("status code "+res.statusCode), { source: url })); return innerCb() }

            if (!body) return innerCb();

            try {
                if (typeof(body) == "string") body = JSON.parse(body);
                body = body["piece length"] ? bencode.encode({ info: _.extend({ pieces: [] }, body) }) : body;
                result = parseTorrent(body);
                result.infoHash = task.infoHash;
                if (! result.files) throw new Error("no files found in torrent");
            } catch(e) { e.source = url; errors.push(e) };
            innerCb();
        });
    }, function()
    {
        if (! (result && result.infoHash)) return task.callback(errors.concat([new Error("Did not manage to download parsable torrent")]));
        task.callback(null, result);
    });
}, 2);

// TODO: ability to rate-limit that section of the code
// OR just use a rate-limited peer-search instead of torrent-stream's peer searching
function fetchTorrent(infoHash, opts, cb) {
    var engine = new torrentStream(infoHash, {
        connections: 30,
        trackers: cfg.fetchTorrentTrackers,
    });
    var cb = _.once(cb);

    engine.ready(function() {
        cb(null, engine.torrent);
        engine.destroy();
    });
    setTimeout(function() {
        cb(new Error("fetchTorrent timed out"));
        engine.destroy();
    }, 15 * 1000);
};

function downloadTorrent(infoHash, opts, cb)
{
    if (typeof(opts) == "function") cb = opts;
    if (! (opts && typeof(opts) == "object")) opts = {};

    downloader[opts.important ? "unshift" : "push"]({ infoHash: infoHash, callback: function(err, torrent) {
        if (err && opts.important) return fetchTorrent(infoHash, opts, cb);
        if (err) return cb(err);
        cb(null, torrent);
    }, url: opts.url })
}

module.exports = { retrieve: downloadTorrent };
module.exports.getAgent = function() { return undefined }; // dummy, to replace if you want your own agent
<|endoftext|>


<commit_before>var fs     = require('fs'),
    path   = require('path'),
    assert = require('assert');
var heads = require('./heads');
var utils              = require('./utils.js'),
    serveStaticFile    = utils.serveStaticFile,
    proxyRequest       = utils.proxyRequest,
    Request            = utils.Request,
    Response           = utils.Response;
var exceptions         = require('./exceptions.js'),
    RoboHydraException = exceptions.RoboHydraException,
    DuplicateRoboHydraHeadNameException =
        exceptions.DuplicateRoboHydraHeadNameException,
    DuplicateRoboHydraPluginException =
        exceptions.DuplicateRoboHydraPluginException,
    InvalidRoboHydraPluginException =
        exceptions.InvalidRoboHydraPluginException,
    RoboHydraPluginNotFoundException =
        exceptions.RoboHydraPluginNotFoundException,
    InvalidRoboHydraNextParametersException =
        exceptions.InvalidRoboHydraNextParametersException,
    RoboHydraHeadNotFoundException =
        exceptions.RoboHydraHeadNotFoundException,
    InvalidRoboHydraTestException =
        exceptions.InvalidRoboHydraTestException;

var RoboHydra = function(config) {
    this._plugins    = [];
    this._headMap    = {};
    this.currentTest = {plugin: '*default*',
                        test:   '*default*'};
    this._pluginLoadPath = ['robohydra/plugins',
                            'node_modules/robohydra/plugins',
                            '/usr/local/share/robohydra/plugins',
                            '/usr/share/robohydra/plugins'];
    this.testResults = {'*default*': {'*default*': {result: undefined,
                                                    passes: [],
                                                    failures: []}}};

    // Register special plugins
    // Admin
    var adminPlugin = require('./plugins/admin.js');
    var adminPluginConfig = {};
    for (var p in config) { adminPluginConfig[p] = config[p]; }
    adminPluginConfig.robohydra = this;
    adminPlugin.heads = adminPlugin.getBodyParts(adminPluginConfig);
    this._registerPluginObject(adminPlugin);
    // Dynamic heads
    this._registerPluginObject({name: '*dynamic*', heads: []});
    // Current test heads
    this._registerPluginObject({name: '*current-test*', heads: []});
};
RoboHydra.prototype._validatePluginName = function(pluginName) {
    return (typeof(pluginName) === 'string' &&
                pluginName.match(new RegExp('^[a-z0-9_-]+$', 'i')));
};
RoboHydra.prototype._addHeadsToPluginStructure = function(heads, pluginStructure) {
    var anonymousHeadCount = 0;
    heads.forEach(function(head) {
        // Calculate head name if not specified
        if (head.name === undefined) {
            head.name = 'anonymousHead' + anonymousHeadCount;
            anonymousHeadCount++;
            while (pluginStructure.headMap.hasOwnProperty(head.name)) {
                head.name = 'anonymousHead' + anonymousHeadCount;
                anonymousHeadCount++;
            }
        }

        if (pluginStructure.headMap.hasOwnProperty(head.name)) {
            throw new DuplicateRoboHydraHeadNameException(head.name);
        }
        pluginStructure.headMap[head.name] = head;
    });
};
RoboHydra.prototype._registerPluginObject = function(plugin) {
    var name = plugin.name;
    if (this._plugins.some(function(v) { return v.plugin.name === name; })) {
        throw new DuplicateRoboHydraPluginException();
    }

    var pluginToRegister = {
        name:  plugin.name,
        heads: plugin.heads || [],
        tests: plugin.tests || {}
    };

    var pluginInternalStructure = {headMap: {}, plugin: pluginToRegister};
    this._addHeadsToPluginStructure(pluginToRegister.heads,
                                    pluginInternalStructure);
    this._plugins.push(pluginInternalStructure);
};
RoboHydra.prototype.registerPluginObject = function(plugin) {
    if (! this._validatePluginName(plugin.name)) {
        throw new InvalidRoboHydraPluginException("Invalid plugin name '" +
                                                      plugin.name + "'");
    }
    var hasHeads = (typeof plugin.heads === 'object') && plugin.heads.length;
    var hasTests = false;
    if (typeof(plugin.tests) === 'object') {
        for (var t in plugin.tests) {
            if (plugin.tests.hasOwnProperty(t)) { hasTests = true; }
        }
    }
    if (!hasHeads && !hasTests) {
        throw new InvalidRoboHydraPluginException("Plugin doesn't have any heads or tests");
    }

    this._registerPluginObject(plugin);
};
RoboHydra.prototype.registerDynamicHead = function(head) {
    var done = false;
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === '*dynamic*') {
            this._addHeadsToPluginStructure([head], this._plugins[i]);
            this._plugins[i].plugin.heads.push(head);
            done = true;
        }
    }
    if (! done) {
        throw "Internal error: couldn't find the dynamic head plugin";
    }
};
RoboHydra.prototype.getPluginNames = function() {
    return this.getPlugins().map(function(p) { return p.name; });
};
RoboHydra.prototype.getPlugins = function() {
    return this._plugins.map(function(v) { return v.plugin; });
};
RoboHydra.prototype.getPlugin = function(pluginName) {
    var pluginList = this._plugins.filter(function(p) {
                         return p.plugin.name === pluginName;
                     });
    if (pluginList.length) {
        return pluginList[0].plugin;
    }
    throw new RoboHydraPluginNotFoundException(pluginName);
};
RoboHydra.prototype.headForPath = function(url, afterHead) {
    var canMatch = !afterHead;
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        var plugin = this._plugins[i].plugin;
        for (var j = 0, len2 = plugin.heads.length; j < len2; j++) {
            if (canMatch && plugin.heads[j].canHandle(url)) {
                return {plugin: plugin, head: plugin.heads[j]};
            }

            if (typeof afterHead === 'object' &&
                    this._plugins[i].plugin.name === afterHead.plugin.name &&
                    plugin.heads[j].name  === afterHead.head.name) {
                canMatch = true;
            }
        }
    }
    return undefined;
};
RoboHydra.prototype.handle = function(req, res, afterHead) {
    var r = this.headForPath(req.url, afterHead);
    if (r !== undefined) {
        res.statusCode = 200;
        var self = this;
        r.head.handle(req, res, function(req2, res2) {
            if (arguments.length !== 2) {
                throw new InvalidRoboHydraNextParametersException(
                    r.plugin,
                    r.head,
                    arguments
                );
            }
            self.handle(req2, res2, r);
        });
    } else {
        res.statusCode = 404;
        res.send("Not Found");
    }
};
RoboHydra.prototype.findHead = function(pluginName, headName) {
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === pluginName) {
            var head = this._plugins[i].headMap[headName];
            if (head === undefined) {
                throw new RoboHydraHeadNotFoundException(pluginName, headName);
            } else {
                return head;
            }
        }
    }
    throw new RoboHydraHeadNotFoundException(pluginName, headName);
};
RoboHydra.prototype.isHeadAttached = function(pluginName, headName) {
    // This will throw an exception if the head is not found
    var head = this.findHead(pluginName, headName);
    return head.attached();
};
RoboHydra.prototype.detachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).detach();
};
RoboHydra.prototype.attachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).attach();
};
RoboHydra.prototype.addPluginLoadPath = function(path) {
    this._pluginLoadPath.unshift(path);
};
RoboHydra.prototype._jsFilesIn = function(testDir) {
    var testFiles = [];
    try {
        testFiles = fs.readdirSync(testDir).filter(function(fname) {
            return (/\.js/).test(fname);
        });
    } catch(e) {
        if (e.code !== 'ENOENT') {
            throw e;
        }
    }
    return testFiles;
};
RoboHydra.prototype.requirePlugin = function(name, config, opts) {
    var plugin = this._requirePluginModule(name, config, opts);
    var moduleObject = this.getModulesObject(plugin.config);
    var pluginObject = plugin.module.getBodyParts(
        plugin.config,
        moduleObject
    );
    pluginObject.name = name;

    // Loads any external test files
    var testDir = path.join(plugin.config.path, 'tests');
    this._jsFilesIn(testDir).forEach(function(testFile) {
        var testModule = require(path.join(testDir, testFile));
        var testDefinition = testModule.getBodyParts(plugin.config,
                                                     moduleObject);
        var testName = testFile.replace(/\.js$/, '');
        pluginObject.tests = pluginObject.tests || {};
        if (testName in pluginObject.tests) {
            throw new InvalidRoboHydraPluginException("Test '" +
                                                          testName +
                                                          "' is duplicated");
        }
        pluginObject.tests[testName] = testDefinition;
    });

    return pluginObject;
};
// Return an object with keys 'module', 'config' and 'name'. The
// 'config' value is another object with keys 'path', 'robohydra' and
// any other values from the configuration. It throws an exception
// RoboHydraPluginNotFoundException if the plugin could not be found
RoboHydra.prototype._requirePluginModule = function(name, config, opts) {
    opts = opts || {};
    var rootDir = opts.rootDir ? fs.realpathSync(opts.rootDir) : '';
    var plugin = {};
    var stat, fullPath;
    for (var i = 0, len = this._pluginLoadPath.length; i < len; i++) {
        try {
            fullPath = rootDir +
                (this._pluginLoadPath[i].indexOf('/') !== 0 ?
                     fs.realpathSync('.') + '/' : '') +
                this._pluginLoadPath[i] + '/' + name;
            stat = fs.statSync(fullPath);
        } catch (e) {
            // It's ok if the plugin is not in this directory
            if (e.code !== 'ENOENT') {
                throw e;
            }
        }
        if (stat && stat.isDirectory()) {
            plugin.module = require(fullPath);
            break;
        }
    }
    if (plugin.module) {
        plugin.config = {robohydra: this, path: fullPath};
        for (var p in config) { plugin.config[p] = config[p]; }
        return plugin;
    } else {
        throw new RoboHydraPluginNotFoundException(name);
    }
};
RoboHydra.prototype.startTest = function(pluginName, testName) {
    this.stopTest();

    var found = false;
    var testPlugin, i, len;
    for (i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === pluginName) {
            if (this._plugins[i].plugin.tests.hasOwnProperty(testName)) {
                testPlugin = this._plugins[i].plugin;
                this.currentTest = {plugin: pluginName, test: testName};
                found = true;
            }
        }
    }

    if (found) {
        var done = false;
        for (i = 0, len = this._plugins.length; i < len; i++) {
            if (this._plugins[i].plugin.name === '*current-test*') {
                var heads = testPlugin.tests[testName].heads;
                this._addHeadsToPluginStructure(heads, this._plugins[i]);
                Array.prototype.push.apply(this._plugins[i].plugin.heads,
                                           heads);
                done = true;
            }
        }
        if (done) {
            this.testResults[pluginName] = this.testResults[pluginName] || {};
            this.testResults[pluginName][testName] = {result: undefined,
                                                      passes: [],
                                                      failures: []};
        } else {
            throw "Internal error: couldn't find the current test plugin";
        }
    } else {
        throw new InvalidRoboHydraTestException(pluginName, testName);
    }
};
RoboHydra.prototype.stopTest = function() {
    this.currentTest = {plugin: '*default*', test: '*default*'};

    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === '*current-test*') {
            this._plugins[i] = {headMap: {},
                                plugin: {name: '*current-test*', heads: []}};
        }
    }
};
RoboHydra.prototype.getAssertionFunction = function(assertion) {
    var thisRoboHydra = this;
    return function() {
        var currentTestPlugin = thisRoboHydra.currentTest.plugin,
            currentTestName   = thisRoboHydra.currentTest.test;
        var result =
            thisRoboHydra.testResults[currentTestPlugin][currentTestName];

        var assertionFunction = assert[assertion];
        var message = arguments[assertionFunction.length-1] ||
            "*unnamed-assertion*";

        try {
            assertionFunction.apply(assert, arguments);

            result.passes.push(message);
            result.result = result.result || 'pass';
        }
        catch (e) {
            if (e instanceof assert.AssertionError) {
                result.failures.push(message);
                result.result = 'fail';
                return false;
            } else {
                throw e;
            }
        }
        return true;
    };
};
RoboHydra.prototype.getModulesObject = function(conf) {
    var utilsObject = {assert: {}, fixtures: {}};

    // Assertions
    for (var assertion in assert) {
        if (assert.hasOwnProperty(assertion) && typeof assert[assertion] === 'function') {
            utilsObject.assert[assertion] =
                this.getAssertionFunction(assertion);
        }
    }

    // Fixture loading (add caching?)
    utilsObject.fixtures.load = function(fixturePath) {
        var normalizedFixturePath = path.normalize(fixturePath);
        var sanitizedFixturePath =
                normalizedFixturePath.replace(new RegExp("\\.\\.", "g"), "");
        var stringPath = path.join(conf.path, "fixtures", sanitizedFixturePath);
        return fs.readFileSync(stringPath);
    };

    return utilsObject;
};

exports.RoboHydra          = RoboHydra;
exports.Request            = Request;
exports.Response           = Response;
exports.serveStaticFile    = serveStaticFile;
exports.proxyRequest       = proxyRequest;
exports.heads              = heads;
exports.roboHydraHeadType  = heads.roboHydraHeadType;
exports.RoboHydraException = RoboHydraException;
for (var exception in exceptions) {
    exports[exception] = exceptions[exception];
}
<commit_msg>Small, incomplete refactoring for plugin search<commit_after>var fs     = require('fs'),
    path   = require('path'),
    assert = require('assert');
var heads = require('./heads');
var utils              = require('./utils.js'),
    serveStaticFile    = utils.serveStaticFile,
    proxyRequest       = utils.proxyRequest,
    Request            = utils.Request,
    Response           = utils.Response;
var exceptions         = require('./exceptions.js'),
    RoboHydraException = exceptions.RoboHydraException,
    DuplicateRoboHydraHeadNameException =
        exceptions.DuplicateRoboHydraHeadNameException,
    DuplicateRoboHydraPluginException =
        exceptions.DuplicateRoboHydraPluginException,
    InvalidRoboHydraPluginException =
        exceptions.InvalidRoboHydraPluginException,
    RoboHydraPluginNotFoundException =
        exceptions.RoboHydraPluginNotFoundException,
    InvalidRoboHydraNextParametersException =
        exceptions.InvalidRoboHydraNextParametersException,
    RoboHydraHeadNotFoundException =
        exceptions.RoboHydraHeadNotFoundException,
    InvalidRoboHydraTestException =
        exceptions.InvalidRoboHydraTestException;

var RoboHydra = function(config) {
    this._plugins    = [];
    this._headMap    = {};
    this.currentTest = {plugin: '*default*',
                        test:   '*default*'};
    this._pluginLoadPath = ['robohydra/plugins',
                            'node_modules/robohydra/plugins',
                            '/usr/local/share/robohydra/plugins',
                            '/usr/share/robohydra/plugins'];
    this.testResults = {'*default*': {'*default*': {result: undefined,
                                                    passes: [],
                                                    failures: []}}};

    // Register special plugins
    // Admin
    var adminPlugin = require('./plugins/admin.js');
    var adminPluginConfig = {};
    for (var p in config) { adminPluginConfig[p] = config[p]; }
    adminPluginConfig.robohydra = this;
    adminPlugin.heads = adminPlugin.getBodyParts(adminPluginConfig);
    this._registerPluginObject(adminPlugin);
    // Dynamic heads
    this._registerPluginObject({name: '*dynamic*', heads: []});
    // Current test heads
    this._registerPluginObject({name: '*current-test*', heads: []});
};
RoboHydra.prototype._validatePluginName = function(pluginName) {
    return (typeof(pluginName) === 'string' &&
                pluginName.match(new RegExp('^[a-z0-9_-]+$', 'i')));
};
RoboHydra.prototype._addHeadsToPluginStructure = function(heads, pluginStructure) {
    var anonymousHeadCount = 0;
    heads.forEach(function(head) {
        // Calculate head name if not specified
        if (head.name === undefined) {
            head.name = 'anonymousHead' + anonymousHeadCount;
            anonymousHeadCount++;
            while (pluginStructure.headMap.hasOwnProperty(head.name)) {
                head.name = 'anonymousHead' + anonymousHeadCount;
                anonymousHeadCount++;
            }
        }

        if (pluginStructure.headMap.hasOwnProperty(head.name)) {
            throw new DuplicateRoboHydraHeadNameException(head.name);
        }
        pluginStructure.headMap[head.name] = head;
    });
};
RoboHydra.prototype._registerPluginObject = function(plugin) {
    var name = plugin.name;
    if (this._plugins.some(function(v) { return v.plugin.name === name; })) {
        throw new DuplicateRoboHydraPluginException();
    }

    var pluginToRegister = {
        name:  plugin.name,
        heads: plugin.heads || [],
        tests: plugin.tests || {}
    };

    var pluginInternalStructure = {headMap: {}, plugin: pluginToRegister};
    this._addHeadsToPluginStructure(pluginToRegister.heads,
                                    pluginInternalStructure);
    this._plugins.push(pluginInternalStructure);
};
RoboHydra.prototype.registerPluginObject = function(plugin) {
    if (! this._validatePluginName(plugin.name)) {
        throw new InvalidRoboHydraPluginException("Invalid plugin name '" +
                                                      plugin.name + "'");
    }
    var hasHeads = (typeof plugin.heads === 'object') && plugin.heads.length;
    var hasTests = false;
    if (typeof(plugin.tests) === 'object') {
        for (var t in plugin.tests) {
            if (plugin.tests.hasOwnProperty(t)) { hasTests = true; }
        }
    }
    if (!hasHeads && !hasTests) {
        throw new InvalidRoboHydraPluginException("Plugin doesn't have any heads or tests");
    }

    this._registerPluginObject(plugin);
};
RoboHydra.prototype.registerDynamicHead = function(head) {
    var done = false;
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === '*dynamic*') {
            this._addHeadsToPluginStructure([head], this._plugins[i]);
            this._plugins[i].plugin.heads.push(head);
            done = true;
        }
    }
    if (! done) {
        throw "Internal error: couldn't find the dynamic head plugin";
    }
};
RoboHydra.prototype.getPluginNames = function() {
    return this.getPlugins().map(function(p) { return p.name; });
};
RoboHydra.prototype.getPlugins = function() {
    return this._plugins.map(function(v) { return v.plugin; });
};
RoboHydra.prototype._getPluginInfo = function(pluginName) {
    var pluginList = this._plugins.filter(function(p) {
                         return p.plugin.name === pluginName;
                     });
    return pluginList.length ? pluginList[0] : undefined;
};
RoboHydra.prototype.getPlugin = function(pluginName) {
    var pluginInfo = this._getPluginInfo(pluginName);
    if (pluginInfo === undefined) {
        throw new RoboHydraPluginNotFoundException(pluginName);
    } else {
        return pluginInfo.plugin;
    }
};
RoboHydra.prototype.headForPath = function(url, afterHead) {
    var canMatch = !afterHead;
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        var plugin = this._plugins[i].plugin;
        for (var j = 0, len2 = plugin.heads.length; j < len2; j++) {
            if (canMatch && plugin.heads[j].canHandle(url)) {
                return {plugin: plugin, head: plugin.heads[j]};
            }

            if (typeof afterHead === 'object' &&
                    this._plugins[i].plugin.name === afterHead.plugin.name &&
                    plugin.heads[j].name  === afterHead.head.name) {
                canMatch = true;
            }
        }
    }
    return undefined;
};
RoboHydra.prototype.handle = function(req, res, afterHead) {
    var r = this.headForPath(req.url, afterHead);
    if (r !== undefined) {
        res.statusCode = 200;
        var self = this;
        r.head.handle(req, res, function(req2, res2) {
            if (arguments.length !== 2) {
                throw new InvalidRoboHydraNextParametersException(
                    r.plugin,
                    r.head,
                    arguments
                );
            }
            self.handle(req2, res2, r);
        });
    } else {
        res.statusCode = 404;
        res.send("Not Found");
    }
};
RoboHydra.prototype.findHead = function(pluginName, headName) {
    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === pluginName) {
            var head = this._plugins[i].headMap[headName];
            if (head === undefined) {
                throw new RoboHydraHeadNotFoundException(pluginName, headName);
            } else {
                return head;
            }
        }
    }
    throw new RoboHydraHeadNotFoundException(pluginName, headName);
};
RoboHydra.prototype.isHeadAttached = function(pluginName, headName) {
    // This will throw an exception if the head is not found
    var head = this.findHead(pluginName, headName);
    return head.attached();
};
RoboHydra.prototype.detachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).detach();
};
RoboHydra.prototype.attachHead = function(pluginName, headName) {
    this.findHead(pluginName, headName).attach();
};
RoboHydra.prototype.addPluginLoadPath = function(path) {
    this._pluginLoadPath.unshift(path);
};
RoboHydra.prototype._jsFilesIn = function(testDir) {
    var testFiles = [];
    try {
        testFiles = fs.readdirSync(testDir).filter(function(fname) {
            return (/\.js/).test(fname);
        });
    } catch(e) {
        if (e.code !== 'ENOENT') {
            throw e;
        }
    }
    return testFiles;
};
RoboHydra.prototype.requirePlugin = function(name, config, opts) {
    var plugin = this._requirePluginModule(name, config, opts);
    var moduleObject = this.getModulesObject(plugin.config);
    var pluginObject = plugin.module.getBodyParts(
        plugin.config,
        moduleObject
    );
    pluginObject.name = name;

    // Loads any external test files
    var testDir = path.join(plugin.config.path, 'tests');
    this._jsFilesIn(testDir).forEach(function(testFile) {
        var testModule = require(path.join(testDir, testFile));
        var testDefinition = testModule.getBodyParts(plugin.config,
                                                     moduleObject);
        var testName = testFile.replace(/\.js$/, '');
        pluginObject.tests = pluginObject.tests || {};
        if (testName in pluginObject.tests) {
            throw new InvalidRoboHydraPluginException("Test '" +
                                                          testName +
                                                          "' is duplicated");
        }
        pluginObject.tests[testName] = testDefinition;
    });

    return pluginObject;
};
// Return an object with keys 'module', 'config' and 'name'. The
// 'config' value is another object with keys 'path', 'robohydra' and
// any other values from the configuration. It throws an exception
// RoboHydraPluginNotFoundException if the plugin could not be found
RoboHydra.prototype._requirePluginModule = function(name, config, opts) {
    opts = opts || {};
    var rootDir = opts.rootDir ? fs.realpathSync(opts.rootDir) : '';
    var plugin = {};
    var stat, fullPath;
    for (var i = 0, len = this._pluginLoadPath.length; i < len; i++) {
        try {
            fullPath = rootDir +
                (this._pluginLoadPath[i].indexOf('/') !== 0 ?
                     fs.realpathSync('.') + '/' : '') +
                this._pluginLoadPath[i] + '/' + name;
            stat = fs.statSync(fullPath);
        } catch (e) {
            // It's ok if the plugin is not in this directory
            if (e.code !== 'ENOENT') {
                throw e;
            }
        }
        if (stat && stat.isDirectory()) {
            plugin.module = require(fullPath);
            break;
        }
    }
    if (plugin.module) {
        plugin.config = {robohydra: this, path: fullPath};
        for (var p in config) { plugin.config[p] = config[p]; }
        return plugin;
    } else {
        throw new RoboHydraPluginNotFoundException(name);
    }
};
RoboHydra.prototype.startTest = function(pluginName, testName) {
    this.stopTest();

    var found = false;
    var testPlugin;
    var pluginInfo = this._getPluginInfo(pluginName);
    if (pluginInfo !== undefined) {
        if (pluginInfo.plugin.tests.hasOwnProperty(testName)) {
            testPlugin = pluginInfo.plugin;
            this.currentTest = {plugin: pluginName, test: testName};
            found = true;
        }
    }

    if (found) {
        var done = false;
        var currentTestInfo = this._getPluginInfo('*current-test*');
        if (currentTestInfo !== undefined) {
            var heads = testPlugin.tests[testName].heads;
            this._addHeadsToPluginStructure(heads, currentTestInfo);
            Array.prototype.push.apply(currentTestInfo.plugin.heads, heads);
            done = true;
        }

        if (done) {
            this.testResults[pluginName] = this.testResults[pluginName] || {};
            this.testResults[pluginName][testName] = {result: undefined,
                                                      passes: [],
                                                      failures: []};
        } else {
            throw "Internal error: couldn't find the current test plugin";
        }
    } else {
        throw new InvalidRoboHydraTestException(pluginName, testName);
    }
};
RoboHydra.prototype.stopTest = function() {
    this.currentTest = {plugin: '*default*', test: '*default*'};

    for (var i = 0, len = this._plugins.length; i < len; i++) {
        if (this._plugins[i].plugin.name === '*current-test*') {
            this._plugins[i] = {headMap: {},
                                plugin: {name: '*current-test*', heads: []}};
        }
    }
};
RoboHydra.prototype.getAssertionFunction = function(assertion) {
    var thisRoboHydra = this;
    return function() {
        var currentTestPlugin = thisRoboHydra.currentTest.plugin,
            currentTestName   = thisRoboHydra.currentTest.test;
        var result =
            thisRoboHydra.testResults[currentTestPlugin][currentTestName];

        var assertionFunction = assert[assertion];
        var message = arguments[assertionFunction.length-1] ||
            "*unnamed-assertion*";

        try {
            assertionFunction.apply(assert, arguments);

            result.passes.push(message);
            result.result = result.result || 'pass';
        }
        catch (e) {
            if (e instanceof assert.AssertionError) {
                result.failures.push(message);
                result.result = 'fail';
                return false;
            } else {
                throw e;
            }
        }
        return true;
    };
};
RoboHydra.prototype.getModulesObject = function(conf) {
    var utilsObject = {assert: {}, fixtures: {}};

    // Assertions
    for (var assertion in assert) {
        if (assert.hasOwnProperty(assertion) && typeof assert[assertion] === 'function') {
            utilsObject.assert[assertion] =
                this.getAssertionFunction(assertion);
        }
    }

    // Fixture loading (add caching?)
    utilsObject.fixtures.load = function(fixturePath) {
        var normalizedFixturePath = path.normalize(fixturePath);
        var sanitizedFixturePath =
                normalizedFixturePath.replace(new RegExp("\\.\\.", "g"), "");
        var stringPath = path.join(conf.path, "fixtures", sanitizedFixturePath);
        return fs.readFileSync(stringPath);
    };

    return utilsObject;
};

exports.RoboHydra          = RoboHydra;
exports.Request            = Request;
exports.Response           = Response;
exports.serveStaticFile    = serveStaticFile;
exports.proxyRequest       = proxyRequest;
exports.heads              = heads;
exports.roboHydraHeadType  = heads.roboHydraHeadType;
exports.RoboHydraException = RoboHydraException;
for (var exception in exceptions) {
    exports[exception] = exceptions[exception];
}
<|endoftext|>


<commit_before>// 'use strict';

var schedule = require('node-schedule');
// var c = require('./channels.js');
// var d = require('./daily.js');
// var date = require('./date.js');
// var slack = require('./slack.js');
var glob = require('glob');
var path = require('path');

module.exports = scheduler;

function scheduler() {

  var events = [];

  glob(path.resolve('./schedules/**/*.js'), function(err, files) {
    files.forEach(function (file) {
      console.log(file);
      events = events.concat(require(file));
    });

    events.forEach(function (event) {
      schedule.scheduleJob(event.when, function () {
        if(Array.isArray(event.who)) {
          event.who.forEach(function (channel) {
            channel.send(event.message);
          });
        } else {
          event.who.send(event.message);
        }
      }.bind(this));
    });
    console.log(events);
  });

  // events = events.concat(require('../schedules/_juniors_daily.js'));
  // events = events.concat(require('../schedules/_seniors_daily.js'));
  // events = events.concat(require('../schedules/_students_daily.js'));
  //
  // events = events.concat(require('../schedules/W1D4.js');
  // events = events.concat(require('../schedules/W7D4.js');

}
<commit_msg>debugging<commit_after>// 'use strict';

var schedule = require('node-schedule');
// var c = require('./channels.js');
// var d = require('./daily.js');
// var date = require('./date.js');
// var slack = require('./slack.js');
var glob = require('glob');
var path = require('path');

module.exports = scheduler;

function scheduler() {

  var events = [];

  glob(path.resolve('./schedules/**/*.js'), function(err, files) {
    files.forEach(function (file) {
      console.log(file);
      events = events.concat(require(file));
    });

    events.forEach(function (event) {
      schedule.scheduleJob(event.when, function () {
        if(Array.isArray(event.who)) {
          event.who.forEach(function (channel) {
            channel.send(event.message);
          });
        } else {
          event.who.send(event.message);
        }
      }.bind(this));
    });
  });

}
<|endoftext|>


<commit_before>export { assert_Pool_issuedCount };
export { assert_Pool_issuedCount_same_after_as_before };
export { assert_Pool_issuedCount_zero };

import * as Pool from "../../util/Pool.js";

/**
 *
 *
 * @param {Pool.Base} pool
 *   The pool object to be asserted.
 *
 */
function assert_Pool_issuedCount( prefixMsg, pool, issuedCount_shouldBe ) {
  if ( pool.issuedCount != issuedCount_shouldBe )
    throw Error( `${prefixMsg}: memory leak: `
      + `pool ( ${pool.poolName} )'s issuedCount ( ${pool.issuedCount} ) should be ( ${issuedCount_shouldBe} ).` );
}

/**
 * Assert all pool's .issuedCount before and after calling pfn() are the same.
 *
 * @param (Function} pfn
 *   The function to be called.
 */
function assert_Pool_issuedCount_same_after_as_before( prefixMsg, pfn ) {

  let issuedCount_array_before;
  try {
    issuedCount_array_before = Pool.Array.Singleton.get_or_create_by( Pool.All.registeredPoolArray.length );
    for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
      let pool = Pool.All.registeredPoolArray[ i ];
      issuedCount_array_before[ i ] = pool.issuedCount;
    }

    pfn.call();

    for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
      let pool = Pool.All.registeredPoolArray[ i ];
      assert_Pool_issuedCount( prefixMsg, pool, issuedCount_array_before[ i ] );
    }

  } finally {
    Pool.Array.Singleton.recycle( issuedCount_array_before );
    issuedCount_array_before = null;
  }
}

/**
 *
 */
function assert_Pool_issuedCount_zero( prefixMsg ) {
  for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
    let pool = Pool.All.registeredPoolArray[ i ];
    assert_Pool_issuedCount( prefixMsg, pool, 0 );
  }
}
<commit_msg>Update Pool_Asserter.js<commit_after>export { assert_Pool_issuedCount };
export { assert_Pool_issuedCount_same_after_as_before };
export { assert_Pool_issuedCount_zero };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";

/**
 *
 *
 * @param {Pool.Base} pool
 *   The pool object to be asserted.
 *
 */
function assert_Pool_issuedCount( prefixMsg, pool, issuedCount_shouldBe ) {
  if ( pool.issuedCount != issuedCount_shouldBe )
    throw Error( `${prefixMsg}: memory leak: `
      + `pool ( ${pool.poolName} )'s issuedCount ( ${pool.issuedCount} ) should be ( ${issuedCount_shouldBe} ).` );
}

/**
 * Assert all pool's .issuedCount before and after calling pfn() are the same.
 *
 * @param (Function} pfn
 *   The function to be called.
 */
function assert_Pool_issuedCount_same_after_as_before( prefixMsg, pfn ) {

  let issuedCount_array_before;
  try {
    issuedCount_array_before = Recyclable.Array.Pool.get_or_create_by( Pool.All.registeredPoolArray.length );
    for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
      let pool = Pool.All.registeredPoolArray[ i ];
      issuedCount_array_before[ i ] = pool.issuedCount;
    }

    pfn.call();

    for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
      let pool = Pool.All.registeredPoolArray[ i ];
      assert_Pool_issuedCount( prefixMsg, pool, issuedCount_array_before[ i ] );
    }

  } finally {
    issuedCount_array_before.disposeResources_and_recycleToPool();
    issuedCount_array_before = null;
  }
}

/**
 *
 */
function assert_Pool_issuedCount_zero( prefixMsg ) {
  for ( let i = 0; i < Pool.All.registeredPoolArray.length; ++i ) {
    let pool = Pool.All.registeredPoolArray[ i ];
    assert_Pool_issuedCount( prefixMsg, pool, 0 );
  }
}
<|endoftext|>