<commit_before>var fs = require('fs'),
    async = require('async'),
    path = require('path'),
    mkdirp = require('mkdirp'),
    ncp = require('ncp').ncp;

var SUB_REGEX = /@(\w*)@/gm,
    done = null,
    grunt = null;

exports.init = function (gruntArg) {
    'use strict';

    // we tell grunt to handle things asynchronously
    done = this.async();
    // we save the grunt reference
    grunt = gruntArg;

    buildAllModules();
};

function buildAllModules() {
    var modulePath = grunt.option('module-path'),
        moduleList = grunt.option('module-list'),
        buildDir = grunt.option('build-dir'),
        processPath = process.cwd();

    if (!modulePath && !moduleList) {
        grunt.log.error('Please specify the "module-path" argument!');
        return;
    }

    if (!modulePath && !moduleList.length) {
        grunt.log.warn('No modules passed to the build task!');
        return;
    }

    if (!buildDir) {
        grunt.log.error('Please specify the "build-dir" argument!');
        return;
    }

    if (modulePath) {
        modulePath = path.resolve(processPath, modulePath);
    } else {
        modulePath = processPath;
    }

    debug('buildDir: ' + buildDir);
    debug('modulePath: ' + modulePath);
    debug('Modules to build: ' + grunt.log.wordlist(moduleList));

    if (!moduleList) {
        moduleList = [];
        moduleList.push(modulePath);
    }

    async.each(moduleList, function(module, eachCallback) {
        buildSingleModule(module, eachCallback);
    }, done);
}

function buildSingleModule(modulePath, callback) {
    // read build.json
    var buildJsonPath = path.join(modulePath, 'build.json'),
        buildJson = grunt.file.readJSON(buildJsonPath),
        builds = buildJson.builds,
        buildsArr = [],
        build;

    // get an array from the object
    for (var buildName in builds) {
        if (builds.hasOwnProperty(buildName)) {
            build = builds[buildName];
            // save the build name, and the module path
            build['$moduleName'] = buildName;
            build['$modulePath'] = modulePath;

            buildsArr.push(build);
        }
    }

    async.each(buildsArr, performBuild, callback);
}

function performBuild(buildDefinition, callback) {
    grunt.log.writeln('Building YUI module: ' + buildDefinition['$moduleName']['green']);

    async.parallel([
        async.apply(wrapJsFiles, buildDefinition),
        async.apply(generateLanguageFiles, buildDefinition),
        async.apply(copyAssets, buildDefinition),
        async.apply(buildSkins, buildDefinition)
    ], callback);
}

function wrapJsFiles(buildDefinition, callback) {
    var buildDir = grunt.option('build-dir'),
        templatePath = path.resolve(__dirname, '../templates/module.tpl'),
        templateContents = grunt.file.read(templatePath),
        moduleContents = substitute(templateContents, {
            MODULE_NAME : buildDefinition['$moduleName'],
            VERSION : '0.1',
            CONTENT : concatenateJsFiles(buildDefinition),
            REQUIRES : determineRequires(buildDefinition)
        }),
        moduleName = buildDefinition['$moduleName'],
        moduleOutputFolder = path.join(buildDir, moduleName),
        moduleFile = path.join(moduleOutputFolder, moduleName + '.js');

    mkdirp(moduleOutputFolder, function(err) {
        if (err) {
            grunt.log.error('Could not create the module output folder!');
        } else {
            grunt.file.write(moduleFile, moduleContents);
        }
        callback();
    });
}

function concatenateJsFiles(buildDefinition) {
    var modulePath = buildDefinition['$modulePath'],
        jsFiles = buildDefinition['jsfiles'],
        jsFilePaths = jsFiles.map(function(fileName) {
            return path.join(modulePath, 'js', fileName);
        }),
        result = '';

    debug(jsFilePaths);

    jsFilePaths.forEach(function(jsFilePath) {
        result += grunt.file.read(jsFilePath) + '\n';
    });

    return result;
}

function determineRequires(buildDefinition) {
    var requiresArr = null,
        requiresStr = '';

    if (buildDefinition['config']) {
        requiresArr = buildDefinition['config']['requires'];

        if (requiresArr) {
            requiresStr = requiresArr.map(function(item) {
                return '"' + item + '"';
            }).join(',');
        }
    }

    debug('Requires: ' + requiresStr);

    return requiresStr;
}

function generateLanguageFiles(buildDefinition, callback) {
    var buildDir = grunt.option('build-dir'),
        templatePath = path.resolve(__dirname, '../templates/language.tpl'),
        templateContents = grunt.file.read(templatePath),
        config = buildDefinition['config'],
        languages,
        moduleName = buildDefinition['$moduleName'],
        modulePath = buildDefinition['$modulePath'],
        languageOutputFolder = path.join(buildDir, moduleName, 'lang');

    if (!config || !config['lang']) {
        debug('No language configured!');
        callback();
        return;
    }

    languages = config['lang'];
    languages.push(''); // added the default language

    mkdirp.sync(languageOutputFolder);

    async.each(languages, function(language, eachCallback) {
        var languageModule = language ? moduleName + '_' + language : moduleName,
            languageFilePath = path.join(modulePath, 'lang', languageModule + '.js'),
            stringsContent = grunt.file.read(languageFilePath),
            languageFileContents = substitute(templateContents, {
                LANG_MODULE : 'lang/' + languageModule,
                MODULE_NAME : moduleName,
                VERSION : '0.1',
                LANG : language,
                STRINGS : stringsContent
            }),
            languageFileOutput = path.join(languageOutputFolder, languageModule + '.js');

        grunt.file.write(languageFileOutput, languageFileContents);
        eachCallback();
    }, callback);
}

function copyAssets(buildDefinition, callback) {
    var buildDir = grunt.option('build-dir'),
        moduleName = buildDefinition['$moduleName'],
        modulePath = buildDefinition['$modulePath'],
        assetsSource = path.join(modulePath, 'assets'),
        assetsDestination = path.join(buildDir, moduleName, 'assets');

    if (!fs.existsSync(assetsSource)) {
        callback();
        return;
    }

    mkdirp.sync(assetsDestination);
    ncp(assetsSource, assetsDestination, function(err) {
        if (err) {
            grunt.log.error('Failed to copy the "assets" folder!');
        }
        callback();
    });
}

function buildSkins(buildDefinition, callback) {
    var modulePath = buildDefinition['$modulePath'],
        skinsFolder = path.join(modulePath, 'assets', 'skins');

    // first we make sure the skins folder exists
    if (!fs.existsSync(skinsFolder)) {
        callback();
        return;
    }

    debug('Found an assets/skins folder!');

    fs.readdir(skinsFolder, function(err, list) {
        if (err) {
            grunt.log.error('Failed to read the "skins" folder!');
            callback();
            return;
        }

        if (list) {
            async.each(list, function(item, eachCallback) {
                var itemPath = path.join(skinsFolder, item);

                fs.stat(itemPath, function(err, stats) {
                    if (stats && stats.isDirectory()) {
                        buildSingleSkin(buildDefinition, item, eachCallback);
                    }
                });
            }, callback);
        } else {
            callback();
        }
    });
}

function buildSingleSkin(buildDefinition, skinName, callback) {
    var buildDir = grunt.option('build-dir'),
        moduleName = buildDefinition['$moduleName'],
        modulePath = buildDefinition['$modulePath'],
        skinFile = path.join(modulePath, 'assets', 'skins', skinName, moduleName + '-skin.css'),
        skinDestinationFolder = path.join(buildDir, moduleName, 'assets', 'skins', skinName),
        skinDestinationFile = path.join(skinDestinationFolder, moduleName + '.css'),
        coreCssFile = path.join(modulePath, 'assets', moduleName + '-core.css'),
        skinFileContents = '',
        coreCssFileContents = '';

    grunt.verbose.writeln('Building skin ' + skinName);

    if (fs.existsSync(coreCssFile)) {
        coreCssFileContents = grunt.file.read(coreCssFile);
    }

    if (fs.existsSync(skinFile)) {
        skinFileContents = grunt.file.read(skinFile);
    }

    if (skinFileContents || coreCssFileContents) {
        mkdirp(skinDestinationFolder, function(err) {
            if (err) {
                grunt.log.error('Could not create the skins output folder!');
                callback();
                return;
            }

            grunt.file.write(skinDestinationFile, skinFileContents + coreCssFileContents);
            callback();
        });
    } else {
        callback();
    }
}

function debug(msg) {
    var isDebug = grunt.option('debug');

    if (isDebug) {
        grunt.verbose.writeln(msg);
    }
}

/**
 * Simple template method similar to YUI 3 Y.Lang.sub.
 * @param template A string representing the template.
 * @param obj The object with key values.
 * @returns {string|void}
 */
function substitute(template, obj) {
    return template.replace(SUB_REGEX, function (match, key) {
        return !obj[key] ? '' : obj[key];
    });
}<commit_msg>Skip concatenation step if there is no 'jsfiles' section in build.json.<commit_after>var fs = require('fs'),
    async = require('async'),
    path = require('path'),
    mkdirp = require('mkdirp'),
    ncp = require('ncp').ncp;

var SUB_REGEX = /@(\w*)@/gm,
    done = null,
    grunt = null;

exports.init = function (gruntArg) {
    'use strict';

    // we tell grunt to handle things asynchronously
    done = this.async();
    // we save the grunt reference
    grunt = gruntArg;

    buildAllModules();
};

function buildAllModules() {
    var modulePath = grunt.option('module-path'),
        moduleList = grunt.option('module-list'),
        buildDir = grunt.option('build-dir'),
        processPath = process.cwd();

    if (!modulePath && !moduleList) {
        grunt.log.error('Please specify the "module-path" argument!');
        return;
    }

    if (!modulePath && !moduleList.length) {
        grunt.log.warn('No modules passed to the build task!');
        return;
    }

    if (!buildDir) {
        grunt.log.error('Please specify the "build-dir" argument!');
        return;
    }

    if (modulePath) {
        modulePath = path.resolve(processPath, modulePath);
    } else {
        modulePath = processPath;
    }

    debug('buildDir: ' + buildDir);
    debug('modulePath: ' + modulePath);
    debug('Modules to build: ' + grunt.log.wordlist(moduleList));

    if (!moduleList) {
        moduleList = [];
        moduleList.push(modulePath);
    }

    async.each(moduleList, function(module, eachCallback) {
        buildSingleModule(module, eachCallback);
    }, done);
}

function buildSingleModule(modulePath, callback) {
    // read build.json
    var buildJsonPath = path.join(modulePath, 'build.json'),
        buildJson = grunt.file.readJSON(buildJsonPath),
        builds = buildJson.builds,
        buildsArr = [],
        build;

    // get an array from the object
    for (var buildName in builds) {
        if (builds.hasOwnProperty(buildName)) {
            build = builds[buildName];
            // save the build name, and the module path
            build['$moduleName'] = buildName;
            build['$modulePath'] = modulePath;

            buildsArr.push(build);
        }
    }

    async.each(buildsArr, performBuild, callback);
}

function performBuild(buildDefinition, callback) {
    grunt.log.writeln('Building YUI module: ' + buildDefinition['$moduleName']['green']);

    async.parallel([
        async.apply(wrapJsFiles, buildDefinition),
        async.apply(generateLanguageFiles, buildDefinition),
        async.apply(copyAssets, buildDefinition),
        async.apply(buildSkins, buildDefinition)
    ], callback);
}

function wrapJsFiles(buildDefinition, callback) {
    var buildDir = grunt.option('build-dir'),
        templatePath = path.resolve(__dirname, '../templates/module.tpl'),
        templateContents = grunt.file.read(templatePath),
        moduleContents = substitute(templateContents, {
            MODULE_NAME : buildDefinition['$moduleName'],
            VERSION : '0.1',
            CONTENT : concatenateJsFiles(buildDefinition),
            REQUIRES : determineRequires(buildDefinition)
        }),
        moduleName = buildDefinition['$moduleName'],
        moduleOutputFolder = path.join(buildDir, moduleName),
        moduleFile = path.join(moduleOutputFolder, moduleName + '.js');

    mkdirp(moduleOutputFolder, function(err) {
        if (err) {
            grunt.log.error('Could not create the module output folder!');
        } else {
            grunt.file.write(moduleFile, moduleContents);
        }
        callback();
    });
}

function concatenateJsFiles(buildDefinition) {
    var modulePath = buildDefinition['$modulePath'],
        jsFiles = buildDefinition['jsfiles'],
        jsFilePaths,
        result = '';

    if (!jsFiles) {
        return;
    }

    jsFilePaths = jsFiles.map(function(fileName) {
        return path.join(modulePath, 'js', fileName);
    });

    debug(jsFilePaths);

    jsFilePaths.forEach(function(jsFilePath) {
        result += grunt.file.read(jsFilePath) + '\n';
    });

    return result;
}

function determineRequires(buildDefinition) {
    var requiresArr = null,
        requiresStr = '';

    if (buildDefinition['config']) {
        requiresArr = buildDefinition['config']['requires'];

        if (requiresArr) {
            requiresStr = requiresArr.map(function(item) {
                return '"' + item + '"';
            }).join(',');
        }
    }

    debug('Requires: ' + requiresStr);

    return requiresStr;
}

function generateLanguageFiles(buildDefinition, callback) {
    var buildDir = grunt.option('build-dir'),
        templatePath = path.resolve(__dirname, '../templates/language.tpl'),
        templateContents = grunt.file.read(templatePath),
        config = buildDefinition['config'],
        languages,
        moduleName = buildDefinition['$moduleName'],
        modulePath = buildDefinition['$modulePath'],
        languageOutputFolder = path.join(buildDir, moduleName, 'lang');

    if (!config || !config['lang']) {
        debug('No language configured!');
        callback();
        return;
    }

    languages = config['lang'];
    languages.push(''); // added the default language

    mkdirp.sync(languageOutputFolder);

    async.each(languages, function(language, eachCallback) {
        var languageModule = language ? moduleName + '_' + language : moduleName,
            languageFilePath = path.join(modulePath, 'lang', languageModule + '.js'),
            stringsContent = grunt.file.read(languageFilePath),
            languageFileContents = substitute(templateContents, {
                LANG_MODULE : 'lang/' + languageModule,
                MODULE_NAME : moduleName,
                VERSION : '0.1',
                LANG : language,
                STRINGS : stringsContent
            }),
            languageFileOutput = path.join(languageOutputFolder, languageModule + '.js');

        grunt.file.write(languageFileOutput, languageFileContents);
        eachCallback();
    }, callback);
}

function copyAssets(buildDefinition, callback) {
    var buildDir = grunt.option('build-dir'),
        moduleName = buildDefinition['$moduleName'],
        modulePath = buildDefinition['$modulePath'],
        assetsSource = path.join(modulePath, 'assets'),
        assetsDestination = path.join(buildDir, moduleName, 'assets');

    if (!fs.existsSync(assetsSource)) {
        callback();
        return;
    }

    mkdirp.sync(assetsDestination);
    ncp(assetsSource, assetsDestination, function(err) {
        if (err) {
            grunt.log.error('Failed to copy the "assets" folder!');
        }
        callback();
    });
}

function buildSkins(buildDefinition, callback) {
    var modulePath = buildDefinition['$modulePath'],
        skinsFolder = path.join(modulePath, 'assets', 'skins');

    // first we make sure the skins folder exists
    if (!fs.existsSync(skinsFolder)) {
        callback();
        return;
    }

    debug('Found an assets/skins folder!');

    fs.readdir(skinsFolder, function(err, list) {
        if (err) {
            grunt.log.error('Failed to read the "skins" folder!');
            callback();
            return;
        }

        if (list) {
            async.each(list, function(item, eachCallback) {
                var itemPath = path.join(skinsFolder, item);

                fs.stat(itemPath, function(err, stats) {
                    if (stats && stats.isDirectory()) {
                        buildSingleSkin(buildDefinition, item, eachCallback);
                    }
                });
            }, callback);
        } else {
            callback();
        }
    });
}

function buildSingleSkin(buildDefinition, skinName, callback) {
    var buildDir = grunt.option('build-dir'),
        moduleName = buildDefinition['$moduleName'],
        modulePath = buildDefinition['$modulePath'],
        skinFile = path.join(modulePath, 'assets', 'skins', skinName, moduleName + '-skin.css'),
        skinDestinationFolder = path.join(buildDir, moduleName, 'assets', 'skins', skinName),
        skinDestinationFile = path.join(skinDestinationFolder, moduleName + '.css'),
        coreCssFile = path.join(modulePath, 'assets', moduleName + '-core.css'),
        skinFileContents = '',
        coreCssFileContents = '';

    grunt.verbose.writeln('Building skin ' + skinName);

    if (fs.existsSync(coreCssFile)) {
        coreCssFileContents = grunt.file.read(coreCssFile);
    }

    if (fs.existsSync(skinFile)) {
        skinFileContents = grunt.file.read(skinFile);
    }

    if (skinFileContents || coreCssFileContents) {
        mkdirp(skinDestinationFolder, function(err) {
            if (err) {
                grunt.log.error('Could not create the skins output folder!');
                callback();
                return;
            }

            grunt.file.write(skinDestinationFile, skinFileContents + coreCssFileContents);
            callback();
        });
    } else {
        callback();
    }
}

function debug(msg) {
    var isDebug = grunt.option('debug');

    if (isDebug) {
        grunt.verbose.writeln(msg);
    }
}

/**
 * Simple template method similar to YUI 3 Y.Lang.sub.
 * @param template A string representing the template.
 * @param obj The object with key values.
 * @returns {string|void}
 */
function substitute(template, obj) {
    return template.replace(SUB_REGEX, function (match, key) {
        return !obj[key] ? '' : obj[key];
    });
}<|endoftext|>


<commit_before>var path            = require('path');
var through         = require('through2');
var trackFilenames  = require('gulp-track-filenames');
var transformTools  = require('browserify-transform-tools');
var browserify      = require('browserify');
var gutil           = require('gulp-util');
var es6ify          = require('es6ify');
var moldSourceMap   = require('mold-source-map');

/**
 * @param {number} [bannerWidth] The width of banner comment, zero or omitted for none
 */
module.exports = function (bannerWidth) {
  'use strict';
  var sourcesFwd = trackFilenames();
  var sourcesInt = trackFilenames();
  var reserved   = [ ];
  var count      = 0;
  var self       = {

    /**
     * Mark source files in preparation for transpile.
     * Outputs a stream of the same files.
     * @returns {stream.Through} A through stream that performs the operation of a gulp stream
     */
    sources: function () {
      var sessionFwd = sourcesFwd.create();
      var sessionInt = sourcesInt.create();
      return through.obj(function (file, encoding, done) {
        var importName = file.relative.replace(path.extname(file.path), '');
        var zeroPadded = ((new Array(file.path.length)).join('0') + String(count++)).slice(file.path.length * -1);
        sessionFwd.define(file.path, importName);
        sessionInt.define(zeroPadded, file.path);
        this.push(file);
        done();
      });
    },

    /**
     * Detect @ngAnnotate comments immediately preceding methods and reserve their parameters
     * @returns {stream.Through} A through stream that performs the operation of a gulp stream
     */
    reserve: function() {
      var logging = [ ];

      // detect @ngInject tags and reserve function parameters
      return through.obj(function(file, encoding, done) {
        var regexp  = /\/\*{2}[^]*@ngInject[^\/]*\*\/\n+.*\w+\s*\(\s*(.*)\s*\)\s*\{/gm;
        var text    = file.contents.toString();
        var pending = [ ];
        var analysis;
        do {
          analysis = regexp.exec(text);
          if (analysis) {
            analysis[1].split(/\s*,\s*/).forEach(function (candidate) {
              if (pending.indexOf(candidate) < 0) {
                pending.push(candidate);
              }
            });
          }
        } while(analysis);
        if (pending.length) {
          pending.sort();
          var filename = file.relative.replace(path.extname(file.path), '');
          logging.push([ '@ngInject', filename, pending.join(', ') ]);
        }
        pending.forEach(function(candidate) {
          if (reserved.indexOf(candidate) < 0) {
            reserved.push(candidate);
          }
        });
        done(null, file);

      // report to console last so that we can equalise column widths
      }, function(done) {
        var columnWidths = [ ];
        logging.forEach(function(line) {
          line.forEach(function(column, i) {
            columnWidths[i] = Math.max(column.length, (columnWidths[i] || 0));
          });
        });
        logging.forEach(function(line) {
          line.forEach(function(column, i, array) {
            while (array[i].length < columnWidths[i]) {
              array[i] += ' ';
            }
          });
          gutil.log.apply(gutil, line);
        });
        done();
      });
    },

    /**
     * Create a transform that makes the given replacements in jasmine files
     * @param {object} replacements Replacement text keyed by the jasmine string to match
     * @returns {Function} A browserify transform
     */
    getJasmineTransform: function (replacements) {
      var expressions = { };
      if (typeof replacements === 'object') {
        for (var key in replacements) {
          var source = '((?:describe|module)\\s*\\(\\s*)(?:\'' + key + '\'|"' + key + '")';
          expressions[source] = replacements[key];
        }
      }
      return function(filename) {
        var text = '';
        return through.obj(function(contents, encoding, done) {
          text += contents.toString();
          done();
        }, function(done) {
          var lines = text.split('\n');
          for (var source in expressions) {
            var expression = new RegExp(source, 'g');
            var target     = expressions[source];
            for (var i = 0; i < lines.length; i++) {
              var analysis;
              do {
                analysis = expression.exec(lines[i]);
                if (analysis) {
                  var line     = i + 1;
                  var char     = expression.lastIndex - analysis[0].length;
                  var isMethod = (typeof target === 'function');
                  var value    = isMethod ? target(filename, line, char) : target;
                  lines[i] =
                    lines[i].slice(0, char) + analysis[1] +
                    '\'' + String(value).replace(/\\/g, '\\\\') + '\'' +
                    lines[i].slice(expression.lastIndex);
                }
              } while (analysis);
              expression.lastIndex = 0;
            }
          }
          this.push(new Buffer(lines.join('\n')));
          done();
        });
      };
    },

    /**
     * ES6ify transform
     */
    es6ifyTransform: require('es6ify'),

    /**
     * Convert import paths to absolute file paths
     */
    requireTransform: transformTools.makeRequireTransform("requireTransform", null, function(args, opts, done) {
      return done(null, 'require("' + sourcesFwd.replace(args[0], '^', '$') + '")');
    }),

    /**
     * Use es6ify to compile the files of the input stream.
     * Use the sources previously identified to satisfy any module imports.
     * @param {...string|function} transforms Any number of browserify transforms
     * @returns {stream.Through} A through stream that performs the operation of a gulp stream
     */
    compile: function () {
      var transforms = Array.prototype.slice.call(arguments);
      var output     = [ ];

      /**
       * Flush the error queue to stdout
       */
      function flushErrors() {
        if (output.length > 0) {
          var width = Number(bannerWidth) || 0;
          var hr    = new Array(width + 1);   // this is a good trick to repeat a character N times
          var start = (width > 0) ? (hr.join('\u25BC') + '\n') : '';
          var stop  = (width > 0) ? (hr.join('\u25B2') + '\n') : '';
          process.stdout.write(start + '\n' + output.join('\n\n') + '\n' + stop);
        }
      }

      /**
       * Compile any number of files into a bundle
       * @param {stream.Through} stream A stream to push files to
       * @param {Array.<string>|string} files Any number of files to bundle
       * @param {string} bundlename The name for the output file
       * @param {function|boolean} [minifiy] Determines whether minification is performed
       * @param {function} done Callback for completion
       */
      function bundle(stream, files, bundlename, minifiy, done) {

        // setup
        var cwd      = process.cwd();
        var outPath  = path.join(cwd, bundlename);
        var mapPath  = path.basename(bundlename) + '.map';
        var isMinify = (minifiy) && ((typeof minifiy !== 'function') || minifiy(bundlename));
        var bundler  = browserify({
          debug: true
        });

        // error handler
        function errorHandler(error) {
          var REGEXP   = /^\s*Error\:\s*(.*\:\d+:\d+\:\s*[^:]*).*\s*$/;
          var analysis = REGEXP.exec(error.toString());
          var message  = analysis ? (analysis[1] + '\n') : ('TODO parse this error\n' + error + '\n');
          if (output.indexOf(message) < 0) {
            output.push(message);
          }
          done();
        }

        // stream output
        function pushFileToStream(path, text) {
          stream.push(new gutil.File({
            cwd: cwd,
            base: cwd,
            path: path,
            contents: new Buffer(text)
          }));
        }

        // transforms
        transforms.concat(self.requireTransform).forEach(function (item) {
          bundler.transform(item);
        });

        // require statements
        [ ].concat(files).forEach(function (item) {
          bundler.require(item, { entry: true });
        });

        // minify requires callback style
        if (isMinify) {
          require('minifyify')(bundler, {
            map:    mapPath,
            uglify: {
              mangle: {
                toplevel: true,
                except:   reserved.join(',')
              }
            }
          });
          bundler.bundle(function (error, code, map) {
            if (!error) {
              var anonymised = sourcesInt.replace(code, '"', '"');  // anonymise module paths
              var sourcemap  = JSON.parse(map);
              sourcemap.sources.forEach(function (file, i, array) {
                array[i] = '/' + path.relative(process.cwd(), file);
              });
              delete sourcemap.file;
              delete sourcemap.sourcesContent;
              pushFileToStream(outPath + '.map', JSON.stringify(sourcemap, null, 2));
              pushFileToStream(outPath, anonymised);
            }
            done(); // complete overall
          })
            .on('error', errorHandler);

        // non-minify requires stream style
        } else {
          bundler.bundle()
            .on('error', errorHandler)
            .pipe(moldSourceMap.transform(function (molder, complete) {
              molder.mapSources(function map(file) {
                return '/' + path.relative(process.cwd(), file);
              });
              molder.sourcemap.setProperty('file');
              molder.sourcemap.setProperty('sourcesContent');
              molder.sourcemap.setProperty('sourceRoot');
              pushFileToStream(outPath + '.map', molder.sourcemap.toJSON(2));
              complete('//# sourceMappingURL=' + mapPath);
            }))
            .on('data', function (contents) {
              pushFileToStream(outPath, contents);
              done(); // complete overall
            });
        }
      }

      // return a set of streams
      return {

        /**
         * A stream that produces a bundle for each file in the stream
         * @param {function|boolean} [isMinify] Determines whether minification is performed
         * @returns {stream.Through}
         */
        each: function (isMinify) {
          return through.obj(function (file, encoding, done) {
            bundle(this, [ file.path ], file.relative, isMinify, done);
          }, function(done) {
            flushErrors();
            done();
          });
        },

        /**
         * A stream that produces a bundle containing all files in the stream
         * @param {string} outPath A relative path for the output file
         * @param {function|boolean} [isMinify] Determines whether minification is performed
         * @returns {stream.Through}
         */
        all: function (outPath, isMinify) {
          var pending = [ ];
          return through.obj(function (file, encoding, done) {
            pending.push(file.path);
            done();
          }, function (done) {
            bundle(this, pending, outPath, isMinify, function() {
              flushErrors();
              done();
            });
          });
        }
      };
    }
  };
  return self;
};

/**
 * The relative path to the traceur runtime
 * @type {string}
 */
module.exports.RUNTIME = es6ify.runtime.replace(process.cwd(), '').slice(1);
<commit_msg>fixes @ngInject annotation for windows platform<commit_after>var path            = require('path');
var through         = require('through2');
var trackFilenames  = require('gulp-track-filenames');
var transformTools  = require('browserify-transform-tools');
var browserify      = require('browserify');
var gutil           = require('gulp-util');
var es6ify          = require('es6ify');
var moldSourceMap   = require('mold-source-map');

/**
 *
Find a unique list of parameters of functions immediately preceded by annotation

 */
function getAnnotatedParameters(annotation, text) {
  'use strict';
  var SPLIT       = /(\/\*|\*\/)/g; // split by and capture comments
  var FUNCTION    = /^[\r\n\s]*(?:(?:return|export|default|function)\s+)*(?:[\w\$]+\s*)?\(\s*(.*)\s*\)[\r\n\s]*\{/m;
  var result      = [ ];
  var isComment   = false;
  var isAnnotated = false;
  text.split(SPLIT).forEach(function(value) {
    switch(value) {

      // start comment block (or commented comment, which will split the comment text)
      case '/*':
        isComment = true;
        break;

      // end comment block
      case '*/':
        isComment = false;
        break;

      // text between
      default:

        // where comment text is split any annotation is accepted
        if (isComment) {
          isAnnotated = isAnnotated || (value.indexOf(annotation) >= 0);

        // code text will not be split
        } else if (isAnnotated) {
          var analysis = FUNCTION.exec(value);
          if (analysis) {

            // add function parameters uniquely to the pending list
            analysis[1].split(/\s*,\s*/).forEach(function (candidate) {
              if (result.indexOf(candidate) < 0) {
                result.push(candidate);
              }
            });
          }
          isAnnotated = false;
        }
    }
  });
  return result;
}

/**
 * @param {number} [bannerWidth] The width of banner comment, zero or omitted for none
 */
module.exports = function (bannerWidth) {
  'use strict';
  var sourcesFwd = trackFilenames();
  var sourcesInt = trackFilenames();
  var reserved   = [ ];
  var count      = 0;
  var self       = {

    /**
     * Mark source files in preparation for transpile.
     * Outputs a stream of the same files.
     * @returns {stream.Through} A through stream that performs the operation of a gulp stream
     */
    sources: function () {
      var sessionFwd = sourcesFwd.create();
      var sessionInt = sourcesInt.create();
      return through.obj(function (file, encoding, done) {
        var importName = file.relative.replace(path.extname(file.path), '');
        var zeroPadded = ((new Array(file.path.length)).join('0') + String(count++)).slice(file.path.length * -1);
        sessionFwd.define(file.path, importName);
        sessionInt.define(zeroPadded, file.path);
        this.push(file);
        done();
      });
    },

    /**
     * Detect @ngAnnotate comments immediately preceding methods and reserve their parameters
     * @returns {stream.Through} A through stream that performs the operation of a gulp stream
     */
    reserve: function() {
      var logging = [ ];

      // detect @ngInject tags and reserve function parameters
      return through.obj(function(file, encoding, done) {
        var ANNOTATION = '@ngInject';
        var pending = getAnnotatedParameters(ANNOTATION, file.contents.toString());
        if (pending.length) {
          pending.sort();
          var importName = file.relative.replace(path.extname(file.path), '');
          logging.push([ ANNOTATION, importName, pending.join(', ') ]);
        }
        pending.forEach(function(candidate) {
          if (reserved.indexOf(candidate) < 0) {
            reserved.push(candidate);
          }
        });
        done(null, file);

      // report to console last so that we can equalise column widths
      }, function(done) {
        var columnWidths = [ ];
        logging.forEach(function(line) {
          line.forEach(function(column, i) {
            columnWidths[i] = Math.max(column.length, (columnWidths[i] || 0));
          });
        });
        logging.forEach(function(line) {
          line.forEach(function(column, i, array) {
            while (array[i].length < columnWidths[i]) {
              array[i] += ' ';
            }
          });
          gutil.log.apply(gutil, line);
        });
        done();
      });
    },

    /**
     * Create a transform that makes the given replacements in jasmine files
     * @param {object} replacements Replacement text keyed by the jasmine string to match
     * @returns {Function} A browserify transform
     */
    getJasmineTransform: function (replacements) {
      var expressions = { };
      if (typeof replacements === 'object') {
        for (var key in replacements) {
          var source = '((?:describe|module)\\s*\\(\\s*)(?:\'' + key + '\'|"' + key + '")';
          expressions[source] = replacements[key];
        }
      }
      return function(filename) {
        var text = '';
        return through.obj(function(contents, encoding, done) {
          text += contents.toString();
          done();
        }, function(done) {
          var lines = text.split('\n');
          for (var source in expressions) {
            var expression = new RegExp(source, 'g');
            var target     = expressions[source];
            for (var i = 0; i < lines.length; i++) {
              var analysis;
              do {
                analysis = expression.exec(lines[i]);
                if (analysis) {
                  var line     = i + 1;
                  var char     = expression.lastIndex - analysis[0].length;
                  var isMethod = (typeof target === 'function');
                  var value    = isMethod ? target(filename, line, char) : target;
                  lines[i] =
                    lines[i].slice(0, char) + analysis[1] +
                    '\'' + String(value).replace(/\\/g, '\\\\') + '\'' +
                    lines[i].slice(expression.lastIndex);
                }
              } while (analysis);
              expression.lastIndex = 0;
            }
          }
          this.push(new Buffer(lines.join('\n')));
          done();
        });
      };
    },

    /**
     * ES6ify transform
     */
    es6ifyTransform: require('es6ify'),

    /**
     * Convert import paths to absolute file paths
     */
    requireTransform: transformTools.makeRequireTransform('requireTransform', null, function(args, opts, done) {
      return done(null, 'require("' + sourcesFwd.replace(args[0], '^', '$') + '")');
    }),

    /**
     * Use es6ify to compile the files of the input stream.
     * Use the sources previously identified to satisfy any module imports.
     * @param {...string|function} transforms Any number of browserify transforms
     * @returns {stream.Through} A through stream that performs the operation of a gulp stream
     */
    compile: function () {
      var transforms = Array.prototype.slice.call(arguments);
      var output     = [ ];

      /**
       * Flush the error queue to stdout
       */
      function flushErrors() {
        if (output.length > 0) {
          var width = Number(bannerWidth) || 0;
          var hr    = new Array(width + 1);   // this is a good trick to repeat a character N times
          var start = (width > 0) ? (hr.join('\u25BC') + '\n') : '';
          var stop  = (width > 0) ? (hr.join('\u25B2') + '\n') : '';
          process.stdout.write(start + '\n' + output.join('\n\n') + '\n' + stop);
        }
      }

      /**
       * Compile any number of files into a bundle
       * @param {stream.Through} stream A stream to push files to
       * @param {Array.<string>|string} files Any number of files to bundle
       * @param {string} bundlename The name for the output file
       * @param {function|boolean} [minifiy] Determines whether minification is performed
       * @param {function} done Callback for completion
       */
      function bundle(stream, files, bundlename, minifiy, done) {

        // setup
        var cwd      = process.cwd();
        var outPath  = path.join(cwd, bundlename);
        var mapPath  = path.basename(bundlename) + '.map';
        var isMinify = (minifiy) && ((typeof minifiy !== 'function') || minifiy(bundlename));
        var bundler  = browserify({
          debug: true
        });

        // error handler
        function errorHandler(error) {
          var REGEXP   = /^\s*Error\:\s*(.*\:\d+:\d+\:\s*[^:]*).*\s*$/;
          var analysis = REGEXP.exec(error.toString());
          var message  = analysis ? (analysis[1] + '\n') : ('TODO parse this error\n' + error + '\n');
          if (output.indexOf(message) < 0) {
            output.push(message);
          }
          done();
        }

        // stream output
        function pushFileToStream(path, text) {
          stream.push(new gutil.File({
            cwd: cwd,
            base: cwd,
            path: path,
            contents: new Buffer(text)
          }));
        }

        // transforms
        transforms.concat(self.requireTransform).forEach(function (item) {
          bundler.transform(item);
        });

        // require statements
        [ ].concat(files).forEach(function (item) {
          bundler.require(item, { entry: true });
        });

        // minify requires callback style
        if (isMinify) {
          require('minifyify')(bundler, {
            map:    mapPath,
            uglify: {
              mangle: {
                toplevel: true,
                except:   reserved.join(',')
              }
            }
          });
          bundler.bundle(function (error, code, map) {
            if (!error) {
              var anonymised = sourcesInt.replace(code, '"', '"');  // anonymise module paths
              var sourcemap  = JSON.parse(map);
              sourcemap.sources.forEach(function (file, i, array) {
                array[i] = '/' + path.relative(process.cwd(), file);
              });
              delete sourcemap.file;
              delete sourcemap.sourcesContent;
              pushFileToStream(outPath + '.map', JSON.stringify(sourcemap, null, 2));
              pushFileToStream(outPath, anonymised);
            }
            done(); // complete overall
          })
            .on('error', errorHandler);

        // non-minify requires stream style
        } else {
          bundler.bundle()
            .on('error', errorHandler)
            .pipe(moldSourceMap.transform(function (molder, complete) {
              molder.mapSources(function map(file) {
                return '/' + path.relative(process.cwd(), file);
              });
              molder.sourcemap.setProperty('file');
              molder.sourcemap.setProperty('sourcesContent');
              molder.sourcemap.setProperty('sourceRoot');
              pushFileToStream(outPath + '.map', molder.sourcemap.toJSON(2));
              complete('//# sourceMappingURL=' + mapPath);
            }))
            .on('data', function (contents) {
              pushFileToStream(outPath, contents);
              done(); // complete overall
            });
        }
      }

      // return a set of streams
      return {

        /**
         * A stream that produces a bundle for each file in the stream
         * @param {function|boolean} [isMinify] Determines whether minification is performed
         * @returns {stream.Through}
         */
        each: function (isMinify) {
          return through.obj(function (file, encoding, done) {
            bundle(this, [ file.path ], file.relative, isMinify, done);
          }, function(done) {
            flushErrors();
            done();
          });
        },

        /**
         * A stream that produces a bundle containing all files in the stream
         * @param {string} outPath A relative path for the output file
         * @param {function|boolean} [isMinify] Determines whether minification is performed
         * @returns {stream.Through}
         */
        all: function (outPath, isMinify) {
          var pending = [ ];
          return through.obj(function (file, encoding, done) {
            pending.push(file.path);
            done();
          }, function (done) {
            bundle(this, pending, outPath, isMinify, function() {
              flushErrors();
              done();
            });
          });
        }
      };
    }
  };
  return self;
};

/**
 * The relative path to the traceur runtime
 * @type {string}
 */
module.exports.RUNTIME = es6ify.runtime.replace(process.cwd(), '').slice(1);
<|endoftext|>


<commit_before>(function(tree) {
//
// RGB Colors - #ff0014, #eee
//
tree.Color = function Color(rgb, a) {
    // The end goal here, is to parse the arguments
    // into an integer triplet, such as `128, 255, 0`
    //
    // This facilitates operations and conversions.
    if (Array.isArray(rgb)) {
        this.rgb = rgb;
    } else if (rgb.length == 6) {
        this.rgb = rgb.match(/.{2}/g).map(function(c) {
            return parseInt(c, 16);
        });
    } else {
        this.rgb = rgb.split('').map(function(c) {
            return parseInt(c + c, 16);
        });
    }
    this.alpha = typeof(a) === 'number' ? a : 1;
};

tree.Color.prototype = {
    is: 'color',
    'ev': function() { return this; },

    // If we have some transparency, the only way to represent it
    // is via `rgba`. Otherwise, we use the hex representation,
    // which has better compatibility with older browsers.
    // Values are capped between `0` and `255`, rounded and zero-padded.
    toString: function() {
        if (this.alpha < 1.0) {
            return 'rgba(' + this.rgb.map(function(c) {
                return Math.round(c);
            }).concat(this.alpha).join(', ') + ')';
        } else {
            return '#' + this.rgb.map(function(i) {
                i = Math.round(i);
                i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
                return i.length === 1 ? '0' + i : i;
            }).join('');
        }
    },

    // Operations have to be done per-channel, if not,
    // channels will spill onto each other. Once we have
    // our result, in the form of an integer triplet,
    // we create a new Color node to hold the result.
    operate: function(op, other) {
        var result = [];

        if (! (other instanceof tree.Color)) {
            other = other.toColor();
        }

        for (var c = 0; c < 3; c++) {
            result[c] = tree.operate(op, this.rgb[c], other.rgb[c]);
        }
        return new tree.Color(result);
    },

    toHSL: function() {
        var r = this.rgb[0] / 255,
            g = this.rgb[1] / 255,
            b = this.rgb[2] / 255,
            a = this.alpha;

        var max = Math.max(r, g, b), min = Math.min(r, g, b);
        var h, s, l = (max + min) / 2, d = max - min;

        if (max === min) {
            h = s = 0;
        } else {
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

            switch (max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        return { h: h * 360, s: s, l: l, a: a };
    }
};

})(require('../tree'));
<commit_msg>fixed regression introduced in last commit<commit_after>(function(tree) {
//
// RGB Colors - #ff0014, #eee
//
tree.Color = function Color(rgb, a) {
    // The end goal here, is to parse the arguments
    // into an integer triplet, such as `128, 255, 0`
    //
    // This facilitates operations and conversions.
    if (Array.isArray(rgb)) {
        this.rgb = rgb;
    } else if (rgb.length == 6) {
        this.rgb = rgb.match(/.{2}/g).map(function(c) {
            return parseInt(c, 16);
        });
    } else {
        this.rgb = rgb.split('').map(function(c) {
            return parseInt(c + c, 16);
        });
    }
    this.alpha = typeof(a) === 'number' ? a : 1;
};

tree.Color.prototype = {
    is: 'color',
    'ev': function() { return this; },

    // If we have some transparency, the only way to represent it
    // is via `rgba`. Otherwise, we use the hex representation,
    // which has better compatibility with older browsers.
    // Values are capped between `0` and `255`, rounded and zero-padded.
    toString: function() {
        if (this.alpha < 1.0) {
            return 'rgba(' + this.rgb.map(function(c) {
                return Math.round(c);
            }).concat(this.alpha).join(', ') + ')';
        } else {
            return '#' + this.rgb.map(function(i) {
                i = Math.round(i);
                i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
                return i.length === 1 ? '0' + i : i;
            }).join('');
        }
    },

    // Operations have to be done per-channel, if not,
    // channels will spill onto each other. Once we have
    // our result, in the form of an integer triplet,
    // we create a new Color node to hold the result.
    operate: function(env, op, other) {
        var result = [];

        if (! (other instanceof tree.Color)) {
            other = other.toColor();
        }

        for (var c = 0; c < 3; c++) {
            result[c] = tree.operate(op, this.rgb[c], other.rgb[c]);
        }
        return new tree.Color(result);
    },

    toHSL: function() {
        var r = this.rgb[0] / 255,
            g = this.rgb[1] / 255,
            b = this.rgb[2] / 255,
            a = this.alpha;

        var max = Math.max(r, g, b), min = Math.min(r, g, b);
        var h, s, l = (max + min) / 2, d = max - min;

        if (max === min) {
            h = s = 0;
        } else {
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

            switch (max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        return { h: h * 360, s: s, l: l, a: a };
    }
};

})(require('../tree'));
<|endoftext|>


<commit_before>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var sys = require("sys");
var log = require('util/log');
var version = require('util/version');
var ps = require('util/pubsub');
var config = require('util/config');
var http = require('services/http');
var getopt = require('util/getopt');

exports.run = function() {
  var called_stop = false;

  var p = getopt.parser();
  p.banner = "Usage: cast-agent [options]";
  p.parse(process.argv);

  ps.once(ps.AGENT_STATE_STOP, function() {
    called_stop = true;
  });

  ps.once(ps.AGENT_STATE_EXIT, function() {
    if (called_stop === false) {
      ps.emit(ps.AGENT_STATE_STOP);
      called_stop = true;
    }
  });

  ps.once(ps.AGENT_CONFIG_DONE, function() {
    process.addListener('SIGINT', function () {
      log.debug("Caught SIGINT, exiting....");
      ps.emit(ps.AGENT_STATE_EXIT, {'why': 'signal', 'value': "SIGINT"});
      process.exit();
    });

    http.load();

    ps.emit(ps.AGENT_STATE_START);
  });

  config.init(function(err) {
    if (err) {
      ps.emit(ps.AGENT_STATE_EXIT, {'why': 'config', 'value': err});
    }
    else {
      ps.emit(ps.AGENT_CONFIG_DONE);
    }
  });
};
<commit_msg>Update cast-agent to use the new config parsing<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var sys = require("sys");
var log = require('util/log');
var version = require('util/version');
var ps = require('util/pubsub');
var config = require('util/config');
var http = require('services/http');
var getopt = require('util/getopt');

exports.run = function() {
  var called_stop = false;

  var p = getopt.parser();
  p.banner = "Usage: cast-agent [options]";
  p.parse(process.argv);

  ps.once(ps.AGENT_STATE_STOP, function() {
    called_stop = true;
  });

  ps.once(ps.AGENT_STATE_EXIT, function() {
    if (called_stop === false) {
      ps.emit(ps.AGENT_STATE_STOP);
      called_stop = true;
    }
  });

  ps.once(ps.AGENT_CONFIG_DONE, function() {
    process.addListener('SIGINT', function () {
      log.debug("Caught SIGINT, exiting....");
      ps.emit(ps.AGENT_STATE_EXIT, {'why': 'signal', 'value': "SIGINT"});
      process.exit();
    });

    http.load();

    ps.emit(ps.AGENT_STATE_START);
  });

  config.setup(function(err) {
    if (err) {
      ps.emit(ps.AGENT_STATE_EXIT, {'why': 'config', 'value': err});
    }
    else {
      ps.emit(ps.AGENT_CONFIG_DONE);
    }
  });
};
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var assign      = require('lodash/object/assign');
var path        = require('path');
var Command     = require('ember-cli/lib/models/command');
var Promise     = require('ember-cli/lib/ext/promise');
var SilentError = require('silent-error');
var PortFinder  = require('portfinder');
var win         = require('ember-cli/lib/utilities/windows-admin');
var EOL         = require('os').EOL;
var CaptureTask = require('../tasks/capture');

PortFinder.basePort = 49152;

var getPort = Promise.denodeify(PortFinder.getPort);
var defaultPort = process.env.PORT || 4200;
var defaultCapturePort = process.env.CAPTUREPORT || 3000;

module.exports = Command.extend({
  name: 'capture',
  description: 'Captures all states of your application.',

  availableOptions: [
    // generic
    { name: 'environment',         type: String,  default: 'development', aliases: ['e', { 'dev': 'development' }, { 'prod': 'production' }] },

    // ember serve options
    { name: 'port',                type: Number,  default: defaultPort,   aliases: ['p'] },
    { name: 'host',                type: String,                          aliases: ['H'],     description: 'Listens on all interfaces by default' },
    { name: 'proxy',               type: String,                          aliases: ['pr', 'pxy'] },
    { name: 'insecure-proxy',      type: Boolean, default: false,         aliases: ['inspr'], description: 'Set false to proxy self-signed SSL certificates' },
    { name: 'output-path',         type: path,    default: 'dist/',       aliases: ['op', 'out'] },
    { name: 'ssl',                 type: Boolean, default: false },
    { name: 'ssl-key',             type: String,  default: 'ssl/server.key' },
    { name: 'ssl-cert',            type: String,  default: 'ssl/server.crt' },

    // ember test options
    { name: 'filter',              type: String,  default: 'acceptance',  aliases: ['f'],  description: 'A string to filter tests to run' },
    { name: 'module',              type: String,                          aliases: ['m'],  description: 'The name of a test module to run' },
    { name: 'test-page',           type: String,  default: 'tests/',                       description: 'Test page to invoke' },

    // ember capture options
    { name: 'capture-port',        type: Number,  default: defaultCapturePort,     description: 'The port on which to run the capture server' },
    { name: 'capture-host',        type: String,  description: 'Listens on all interfaces by default' },
    { name: 'capture-output-path', type: path,    default: 'capture/',       aliases: ['capture-output'] },
    { name: 'capture-config-file', type: String,  default: './capture.json', aliases: ['c', 'cf'] }
  ],

  run: function(commandOptions) {
    var port = commandOptions.port ? Promise.resolve(commandOptions.port) : getPort({ host: commandOptions.host });

    return port.then(function(port) {
      commandOptions = assign({}, commandOptions, {
        port: port,
        baseURL: this.project.config(commandOptions.environment).baseURL || '/'
      });

      if (commandOptions.proxy) {
        if (!commandOptions.proxy.match(/^(http:|https:)/)) {
          var message = 'You need to include a protocol with the proxy URL.' + EOL + 'Try --proxy http://' + commandOptions.proxy;

          return Promise.reject(new SilentError(message));
        }
      }

      var capture = new CaptureTask({
        ui: this.ui,
        analytics: this.analytics,
        project: this.project
      });

      return win.checkWindowsElevation(this.ui).then(function() {
        return capture.run(commandOptions);
      });
    }.bind(this));
  }
});
<commit_msg>Add back configuration for watching.<commit_after>/* jshint node: true */
'use strict';

var assign      = require('lodash/object/assign');
var path        = require('path');
var Command     = require('ember-cli/lib/models/command');
var Promise     = require('ember-cli/lib/ext/promise');
var SilentError = require('silent-error');
var PortFinder  = require('portfinder');
var win         = require('ember-cli/lib/utilities/windows-admin');
var EOL         = require('os').EOL;
var CaptureTask = require('../tasks/capture');

PortFinder.basePort = 49152;

var getPort = Promise.denodeify(PortFinder.getPort);
var defaultPort = process.env.PORT || 4200;
var defaultCapturePort = process.env.CAPTUREPORT || 3000;

module.exports = Command.extend({
  name: 'capture',
  description: 'Captures all states of your application.',

  availableOptions: [
    // generic
    { name: 'environment',         type: String,  default: 'development', aliases: ['e', { 'dev': 'development' }, { 'prod': 'production' }] },

    // ember serve options
    { name: 'port',                type: Number,  default: defaultPort,   aliases: ['p'] },
    { name: 'host',                type: String,                          aliases: ['H'],     description: 'Listens on all interfaces by default' },
    { name: 'proxy',               type: String,                          aliases: ['pr', 'pxy'] },
    { name: 'insecure-proxy',      type: Boolean, default: false,         aliases: ['inspr'], description: 'Set false to proxy self-signed SSL certificates' },
    { name: 'watcher',             type: String,  default: 'events',      aliases: ['w'] },
    { name: 'output-path',         type: path,    default: 'dist/',       aliases: ['op', 'out'] },
    { name: 'ssl',                 type: Boolean, default: false },
    { name: 'ssl-key',             type: String,  default: 'ssl/server.key' },
    { name: 'ssl-cert',            type: String,  default: 'ssl/server.crt' },

    // ember test options
    { name: 'filter',              type: String,  default: 'acceptance',  aliases: ['f'],  description: 'A string to filter tests to run' },
    { name: 'module',              type: String,                          aliases: ['m'],  description: 'The name of a test module to run' },
    { name: 'test-page',           type: String,  default: 'tests/',                       description: 'Test page to invoke' },

    // ember capture options
    { name: 'capture-port',        type: Number,  default: defaultCapturePort,     description: 'The port on which to run the capture server' },
    { name: 'capture-host',        type: String,  description: 'Listens on all interfaces by default' },
    { name: 'capture-output-path', type: path,    default: 'capture/',       aliases: ['capture-output'] },
    { name: 'capture-config-file', type: String,  default: './capture.json', aliases: ['c', 'cf'] }
  ],

  run: function(commandOptions) {
    var port = commandOptions.port ? Promise.resolve(commandOptions.port) : getPort({ host: commandOptions.host });

    return port.then(function(port) {
      commandOptions = assign({}, commandOptions, {
        port: port,
        baseURL: this.project.config(commandOptions.environment).baseURL || '/'
      });

      if (commandOptions.proxy) {
        if (!commandOptions.proxy.match(/^(http:|https:)/)) {
          var message = 'You need to include a protocol with the proxy URL.' + EOL + 'Try --proxy http://' + commandOptions.proxy;

          return Promise.reject(new SilentError(message));
        }
      }

      var capture = new CaptureTask({
        ui: this.ui,
        analytics: this.analytics,
        project: this.project
      });

      return win.checkWindowsElevation(this.ui).then(function() {
        return capture.run(commandOptions);
      });
    }.bind(this));
  }
});
<|endoftext|>


<commit_before>// Copyright & License details are available under JXCORE_LICENSE file

var fs = require('fs');
var path = require('path');
var jxtools = require('jxtools');
var fname = 'io.jxcore.node.jx';
var dname = 'io.jxcore.node';
var common = require('../common.js');
var config = require('./config.js');

var localFile = path.join(process.cwd(), fname);
var folder = path.join(process.cwd(), dname);

var unpack = function (cb) {

  var commands = [];

  if (fs.existsSync(folder)) {
    commands.push({
      name: 'remove_plugin',
      command: 'cordova plugins remove ' + dname,
      caption: 'Removing plugin from project...',
      skip_error: true
    });
    commands.push({
      name: 'remove_dir',
      command: jxtools.fs.getRmdirCommand(folder),
      caption: 'Removing previous plugin\'s folder...'
    });
  }

  // extract package
  commands.push({
    name: 'extract',
    command: '"' + process.execPath + '" ' + fname,
    caption: 'Extracting plugin package...'
  });

  // add plugin
  commands.push({
    name: 'add_plugin',
    command: 'cordova plugins add ' + dname,
    caption: 'Adding plugin to project...'
  });

  commands.push({
    name: 'remove_dir_after',
    command: jxtools.fs.getRmdirCommand(folder),
    caption: 'Cleaning up...'
  });

  jxtools.fs.execMultiple(commands, function (ret) {
    if (ret.errors)
      return cb(ret.errors);
    else {
      var sampleName = jxcore.utils.argv.getValue('sample');
      if (sampleName) {
        var sample = require('./sample.js');
        sample.useSample(sampleName, function (err) {
          if (!err)
            jxcore.utils.console.info("Done.");

          cb(err);
        });
      }
    }
  });
};

var download = function (version, cb) {

  //var url = 'https://raw.githubusercontent.com/jxcore/jxcore-cordova-release/master/' + version + '/' + fname;
  var url = 'http://jxcordova.cloudapp.net/' + version + '/' + fname;
  var download = jxtools.http.download(url, fname, {attempts: 3, timeout: 10000});
  download.on('end', function (err) {
    if (!err)
      unpack(cb);
  });
};

var install = function(version, cb) {

  var offFile = checkOfflinePackage(version);
  var copied = false;
  if (offFile) {
    try {
      fs.writeFileSync(localFile, fs.readFileSync(offFile));
      copied = true;
    } catch (ex) {
      jxcore.utils.console.warn('Cannot use offline file: ' + ex);
    }

    if (copied) {
      jxtools.console.logPair('Using offline file:', offFile);
      return unpack(cb);
    }
  }

  // downloading if offline file is not used
  download(version, cb);
};

var checkOfflinePackage = function(version) {
  var cfg = config.read();
  if (cfg.err)
    return false;

  var offDir = cfg['offline-dir'];
  var offFile = path.join(offDir, version, fname);
  return fs.existsSync(offFile) ? offFile : false;
};

var getLatestCordovaVersion = function (cb) {

  var _url = 'https://raw.githubusercontent.com/jxcore/jxcore-cordova/master/package.json';
  jxtools.http.downloadString(_url, {silent: true}, function (err, json_str) {
    if (!err) {
      var version = 'unknown';
      try {
        var json = JSON.parse(json_str);
        version = json.version;
      } catch (ex) {
        return cb("Cannot parse package.json: " + ex);
      }

      cb(false, version);
    } else {
      cb(err);
    }
  });
};

exports.run = function (cb) {

  var parsedArgv = jxcore.utils.argv.parse();

  if (fs.existsSync(localFile)) {
    var stat = fs.statSync(localFile);
    if (stat.size < 1024 * 1024)
      fs.unlinkSync(localFile);
  }

  if (fs.existsSync(localFile) && !parsedArgv.force) {
    jxcore.utils.console.warn('Skipping the download, since file', fname, 'already exists.');
    jxcore.utils.console.log('If you want to force downloading, use --force option.');
    unpack(cb);
    return;
  }

  if (fs.existsSync(folder) && !parsedArgv.force) {
    jxcore.utils.console.warn('Skipping the installation, since folder', dname, 'already exists.');
    jxcore.utils.console.log('If you want to force installing, use --force option.');
    return;
  }

  var plugin_installed_folder = path.join(process.cwd(), 'plugins', dname);
  if (fs.existsSync(plugin_installed_folder) && !parsedArgv.force) {
    jxcore.utils.console.warn('Skipping the installation, since plugin is already added.');
    jxcore.utils.console.log('If you want to force installing, use --force option or remove the plugin:');
    jxcore.utils.console.log('    > cordova plugins remove ' + dname);
    return;
  }

  var argv3 = process.argv[3];
  if (argv3 && argv3.slice(0, 1) === '-')
    argv3 = null;

  if (argv3) {
    install(argv3, cb);
  } else {
    getLatestCordovaVersion(function(err, version) {
      if (err)
        jxcore.utils.console.error(err);
      else {
        jxtools.console.logPair('Latest jxcore-cordova version:', version);
        install(version, cb);
      }
    });
  }

};

<commit_msg>offline dir can be undefined<commit_after>// Copyright & License details are available under JXCORE_LICENSE file

var fs = require('fs');
var path = require('path');
var jxtools = require('jxtools');
var fname = 'io.jxcore.node.jx';
var dname = 'io.jxcore.node';
var common = require('../common.js');
var config = require('./config.js');

var localFile = path.join(process.cwd(), fname);
var folder = path.join(process.cwd(), dname);

var unpack = function (cb) {

  var commands = [];

  if (fs.existsSync(folder)) {
    commands.push({
      name: 'remove_plugin',
      command: 'cordova plugins remove ' + dname,
      caption: 'Removing plugin from project...',
      skip_error: true
    });
    commands.push({
      name: 'remove_dir',
      command: jxtools.fs.getRmdirCommand(folder),
      caption: 'Removing previous plugin\'s folder...'
    });
  }

  // extract package
  commands.push({
    name: 'extract',
    command: '"' + process.execPath + '" ' + fname,
    caption: 'Extracting plugin package...'
  });

  // add plugin
  commands.push({
    name: 'add_plugin',
    command: 'cordova plugins add ' + dname,
    caption: 'Adding plugin to project...'
  });

  commands.push({
    name: 'remove_dir_after',
    command: jxtools.fs.getRmdirCommand(folder),
    caption: 'Cleaning up...'
  });

  jxtools.fs.execMultiple(commands, function (ret) {
    if (ret.errors)
      return cb(ret.errors);
    else {
      var sampleName = jxcore.utils.argv.getValue('sample');
      if (sampleName) {
        var sample = require('./sample.js');
        sample.useSample(sampleName, function (err) {
          if (!err)
            jxcore.utils.console.info("Done.");

          cb(err);
        });
      }
    }
  });
};

var download = function (version, cb) {

  //var url = 'https://raw.githubusercontent.com/jxcore/jxcore-cordova-release/master/' + version + '/' + fname;
  var url = 'http://jxcordova.cloudapp.net/' + version + '/' + fname;
  var download = jxtools.http.download(url, fname, {attempts: 3, timeout: 10000});
  download.on('end', function (err) {
    if (!err)
      unpack(cb);
  });
};

var install = function(version, cb) {

  var offFile = checkOfflinePackage(version);
  var copied = false;
  if (offFile) {
    try {
      fs.writeFileSync(localFile, fs.readFileSync(offFile));
      copied = true;
    } catch (ex) {
      jxcore.utils.console.warn('Cannot use offline file: ' + ex);
    }

    if (copied) {
      jxtools.console.logPair('Using offline file:', offFile);
      return unpack(cb);
    }
  }

  // downloading if offline file is not used
  download(version, cb);
};

var checkOfflinePackage = function(version) {
  var cfg = config.read();
  if (cfg.err)
    return false;

  var offDir = cfg['offline-dir'] || process.cwd();
  var offFile = path.join(offDir, version, fname);
  return fs.existsSync(offFile) ? offFile : false;
};

var getLatestCordovaVersion = function (cb) {

  var _url = 'https://raw.githubusercontent.com/jxcore/jxcore-cordova/master/package.json';
  jxtools.http.downloadString(_url, {silent: true}, function (err, json_str) {
    if (!err) {
      var version = 'unknown';
      try {
        var json = JSON.parse(json_str);
        version = json.version;
      } catch (ex) {
        return cb("Cannot parse package.json: " + ex);
      }

      cb(false, version);
    } else {
      cb(err);
    }
  });
};

exports.run = function (cb) {

  var parsedArgv = jxcore.utils.argv.parse();

  if (fs.existsSync(localFile)) {
    var stat = fs.statSync(localFile);
    if (stat.size < 1024 * 1024)
      fs.unlinkSync(localFile);
  }

  if (fs.existsSync(localFile) && !parsedArgv.force) {
    jxcore.utils.console.warn('Skipping the download, since file', fname, 'already exists.');
    jxcore.utils.console.log('If you want to force downloading, use --force option.');
    unpack(cb);
    return;
  }

  if (fs.existsSync(folder) && !parsedArgv.force) {
    jxcore.utils.console.warn('Skipping the installation, since folder', dname, 'already exists.');
    jxcore.utils.console.log('If you want to force installing, use --force option.');
    return;
  }

  var plugin_installed_folder = path.join(process.cwd(), 'plugins', dname);
  if (fs.existsSync(plugin_installed_folder) && !parsedArgv.force) {
    jxcore.utils.console.warn('Skipping the installation, since plugin is already added.');
    jxcore.utils.console.log('If you want to force installing, use --force option or remove the plugin:');
    jxcore.utils.console.log('    > cordova plugins remove ' + dname);
    return;
  }

  var argv3 = process.argv[3];
  if (argv3 && argv3.slice(0, 1) === '-')
    argv3 = null;

  if (argv3) {
    install(argv3, cb);
  } else {
    getLatestCordovaVersion(function(err, version) {
      if (err)
        jxcore.utils.console.error(err);
      else {
        jxtools.console.logPair('Latest jxcore-cordova version:', version);
        install(version, cb);
      }
    });
  }

};

<|endoftext|>


<commit_before>// Copyright © 2015-2017 Dell Inc. or its subsidiaries.  All Rights Reserved.

'use strict';

module.exports = constantsFactory;

constantsFactory.$provide = 'Constants';
constantsFactory.$inject = [
    'path'
];

function constantsFactory (path) {
    var constants = Object.freeze({
        WorkingDirectory: process.cwd(),
        Name: process.cwd().split(path.sep).reverse()[0],
        Host: require('os').hostname().split(/\./)[0],
        Events: {
            Log: 'log',
            Unhandled: 'errors.unhandled',
            Ignored: 'errors.ignored',
            Blocked: 'errors.blocked'
        },
        Logging: {
            Colors: {
              critical: 'red',
              error: 'red',
              warning: 'yellow',
              info: 'green',
              debug: 'cyan',
            },
            Levels: {
                critical: 5,
                error: 4,
                warning: 3,
                info: 2,
                debug: 1
            },
            Context: {
                Length: 6
            },
            Sanitizations: ['id', 'mac', 'ip'],
            Redactions: [ /password/i, /^community$/i ]
        },
        Configuration: {
            Files: {
                Global: process.env.MONORAIL_CONFIG || '/opt/monorail/config.json',
                OnRack: '/opt/onrack/etc/monorail.json',
                Dell: '/opt/dell/wsmanConfig.json'
            }
        },
        WorkItems: {
            Pollers: {
                IPMI: 'Pollers.IPMI',
                SNMP: 'Pollers.SNMP',
                REDFISH: 'Pollers.Redfish',
				WSMAN: 'Pollers.WSMAN',
                Metrics: {
                    SnmpInterfaceBandwidthUtilization: 'snmp-interface-bandwidth-utilization',
                    SnmpInterfaceState: 'snmp-interface-state',
                    SnmpProcessorLoad: 'snmp-processor-load',
                    SnmpMemoryUsage: 'snmp-memory-usage',
                    SnmpPduPowerStatus: 'snmp-pdu-power-status',
                    SnmpPduSensorStatus: 'snmp-pdu-sensor-status',
                    SnmpTxRxCounters: 'snmp-txrx-counters',
                    SnmpSwitchSensorStatus: 'snmp-switch-sensor-status'
                }
            },
        },
        Protocol: {
             Exchanges: {
                Configuration: {
                    Name: 'on.configuration',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Dhcp: {
                    Name: 'on.dhcp',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Events: {
                    Name: 'on.events',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Http: {
                    Name: 'on.http',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Logging: {
                    Name: 'on.logging',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                TaskGraphRunner: {
                    Name: 'on.task-graph-runner',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Scheduler: {
                    Name: 'on.scheduler',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Task: {
                    Name: 'on.task',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Tftp: {
                    Name: 'on.tftp',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Waterline: {
                    Name: 'on.waterline',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Test: {
                    Name: 'on.test',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                SSDP: {
                    Name: 'on.ssdp',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Heartbeat: {
                    Name: 'on.heartbeat',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                }
            }
        },
        Profiles: {
             Directory: process.cwd() + '/data/profiles'
        },
        Templates: {
             Directory: process.cwd() + '/data/templates'
        },
        Views: {
             Directory: process.cwd() + '/data/views'
        },
        Task: {
            FinishedStates: [
                'succeeded',
                'timeout',
                'cancelled',
                'failed'
            ],
            FailedStates: [
                'failed',
                'timeout',
                'cancelled'
            ],
            ActiveStates: [
                'pending',
                'running'
            ],
            States: {
                Running: 'running',
                Succeeded: 'succeeded',
                Failed: 'failed',
                Cancelled: 'cancelled',
                Timeout: 'timeout',
                Pending: 'pending',
                Finished: 'finished'
            },
            DefaultDomain: 'default',
            DefaultLeaseAdjust: 20000,
        },
        Regex: {
            Base64: /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i,
            Encrypted: /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})\.(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i, // jshint ignore:line
            MacAddress: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/,
            IpAddress: /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/,
            uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
        },
        ChildProcess: {
            maxBuffer: 200 * 1024
        },
        ObmSettings: {
            'noop-obm-service': [
                {
                    type: 'compute'
                },
            ],
            'ipmi-obm-service': [
                {
                    type: 'compute'
                }
            ],
            'panduit-obm-service': [
                {
                    type: 'enclosure'
                },
                {
                    type: 'compute',
                    sku: 'noop' // Example for multi-item rule
                }
            ],
            'vbox-obm-service': [
                {
                    type: 'compute'
                }
            ],
            'redfish-obm-service': [
                {
                    type: 'compute'
                },
                {
                    type: 'enclosure'
                }
            ]
        },
        NodeRelations: {
            /* There are two classes about the pair of relations:
             * component: one node is a component of the other
             *     e.g.  compute node vs. enclosure node
             *     expect behavior:
             *         the "By" in the relationType is used to tell component from its parent
             *         delete a node as well as its components;
             *         delete a component and update its parenet node
             * link: two nodes is linked to each other
             *     e.g.  compute node vs pdu node (TODO)
             *     expect behavior:
             *         delete one node and update the other
            */
            encloses: {
                mapping: 'enclosedBy',
                relationClass: 'component'
            },
            enclosedBy: {
                mapping: 'encloses',
                relationClass: 'component'
            },
            /* Below are an example used to verify function
             * currently used in unit test
             compute node:
             "relations": [
                 {
                     "relationType": "poweredBy",
                     "targets": [
                         "567b8f478b7444e407bb0729"
                     ]
                 }
             ],
             pdu node:
             "relations": [
                 {
                     "relationType": "powers",
                     "targets": [
                         "567b8f478b7444e407bb072a"
                         "567b8f478b7444e407bb072b"
                     ]
                 }
             ],
             If either of them is removed, the other node will only be updated without deletion
            */
            powers: {
                mapping: 'poweredBy',
                relationClass: 'link'
            },
            poweredBy: {
                mapping: 'powers',
                relationClass: 'link'
            },
            /* end example */
            contains: {
                mapping: 'containedBy',
                relationClass: 'link'
            },
            containedBy: {
                mapping: 'contains',
                relationClass: 'link'
            }
        },
        Scope: {
            Global: 'global'
        },
        NodeTypes: {
            ComputerContainer: 'compute-container',
            Compute: 'compute',
            Switch: 'switch',
            Dae: 'dae',
            Pdu: 'pdu',
            Mgmt: 'mgmt',
            Enclosure: 'enclosure',
            Rack: 'rack',
            Storage: 'storage',
            Iom: 'iom'
        },
        Redfish: {
            EventTypes: {
                StatusChange: 'StatusChange',
                ResourceUpdated: 'ResourceUpdated',
                ResourceAdded: 'ResourceAdded',
                ResourceRemoved: 'ResourceRemoved',
                Alert: 'Alert'
            }
        },
        HttpHeaders: {
            ApiProxyIp: 'X-RackHD-API-proxy-ip',
            ApiProxyPort: 'X-RackHD-API-proxy-port'
        },
        Heartbeat: {
            defaultIntervalSec: 10
        },
        HttpStaticDir: {
            systemDefault: 'static/http',
            userDefault: '/opt/monorail/static/http',
            skupack: 'skupack.d',
            upnp: 'static/upnp'
        },
        Progress: {
            DefaultTaskProgressMaximum: 100
        }
    });

    return constants;
}
<commit_msg>Modifying name and location of smi config json used by the smi discovery and dell wsman inventory microservices.<commit_after>// Copyright © 2015-2017 Dell Inc. or its subsidiaries.  All Rights Reserved.

'use strict';

module.exports = constantsFactory;

constantsFactory.$provide = 'Constants';
constantsFactory.$inject = [
    'path'
];

function constantsFactory (path) {
    var constants = Object.freeze({
        WorkingDirectory: process.cwd(),
        Name: process.cwd().split(path.sep).reverse()[0],
        Host: require('os').hostname().split(/\./)[0],
        Events: {
            Log: 'log',
            Unhandled: 'errors.unhandled',
            Ignored: 'errors.ignored',
            Blocked: 'errors.blocked'
        },
        Logging: {
            Colors: {
              critical: 'red',
              error: 'red',
              warning: 'yellow',
              info: 'green',
              debug: 'cyan',
            },
            Levels: {
                critical: 5,
                error: 4,
                warning: 3,
                info: 2,
                debug: 1
            },
            Context: {
                Length: 6
            },
            Sanitizations: ['id', 'mac', 'ip'],
            Redactions: [ /password/i, /^community$/i ]
        },
        Configuration: {
            Files: {
                Global: process.env.MONORAIL_CONFIG || '/opt/monorail/config.json',
                OnRack: '/opt/onrack/etc/monorail.json',
                Dell: '/opt/monorail/smiConfig.json'
            }
        },
        WorkItems: {
            Pollers: {
                IPMI: 'Pollers.IPMI',
                SNMP: 'Pollers.SNMP',
                REDFISH: 'Pollers.Redfish',
				WSMAN: 'Pollers.WSMAN',
                Metrics: {
                    SnmpInterfaceBandwidthUtilization: 'snmp-interface-bandwidth-utilization',
                    SnmpInterfaceState: 'snmp-interface-state',
                    SnmpProcessorLoad: 'snmp-processor-load',
                    SnmpMemoryUsage: 'snmp-memory-usage',
                    SnmpPduPowerStatus: 'snmp-pdu-power-status',
                    SnmpPduSensorStatus: 'snmp-pdu-sensor-status',
                    SnmpTxRxCounters: 'snmp-txrx-counters',
                    SnmpSwitchSensorStatus: 'snmp-switch-sensor-status'
                }
            },
        },
        Protocol: {
             Exchanges: {
                Configuration: {
                    Name: 'on.configuration',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Dhcp: {
                    Name: 'on.dhcp',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Events: {
                    Name: 'on.events',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Http: {
                    Name: 'on.http',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Logging: {
                    Name: 'on.logging',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                TaskGraphRunner: {
                    Name: 'on.task-graph-runner',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Scheduler: {
                    Name: 'on.scheduler',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Task: {
                    Name: 'on.task',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Tftp: {
                    Name: 'on.tftp',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Waterline: {
                    Name: 'on.waterline',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Test: {
                    Name: 'on.test',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                SSDP: {
                    Name: 'on.ssdp',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                },
                Heartbeat: {
                    Name: 'on.heartbeat',
                    Options: {
                        type: 'topic',
                        durable: true,
                        autoDelete: false
                    }
                }
            }
        },
        Profiles: {
             Directory: process.cwd() + '/data/profiles'
        },
        Templates: {
             Directory: process.cwd() + '/data/templates'
        },
        Views: {
             Directory: process.cwd() + '/data/views'
        },
        Task: {
            FinishedStates: [
                'succeeded',
                'timeout',
                'cancelled',
                'failed'
            ],
            FailedStates: [
                'failed',
                'timeout',
                'cancelled'
            ],
            ActiveStates: [
                'pending',
                'running'
            ],
            States: {
                Running: 'running',
                Succeeded: 'succeeded',
                Failed: 'failed',
                Cancelled: 'cancelled',
                Timeout: 'timeout',
                Pending: 'pending',
                Finished: 'finished'
            },
            DefaultDomain: 'default',
            DefaultLeaseAdjust: 20000,
        },
        Regex: {
            Base64: /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i,
            Encrypted: /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})\.(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i, // jshint ignore:line
            MacAddress: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/,
            IpAddress: /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/,
            uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
        },
        ChildProcess: {
            maxBuffer: 200 * 1024
        },
        ObmSettings: {
            'noop-obm-service': [
                {
                    type: 'compute'
                },
            ],
            'ipmi-obm-service': [
                {
                    type: 'compute'
                }
            ],
            'panduit-obm-service': [
                {
                    type: 'enclosure'
                },
                {
                    type: 'compute',
                    sku: 'noop' // Example for multi-item rule
                }
            ],
            'vbox-obm-service': [
                {
                    type: 'compute'
                }
            ],
            'redfish-obm-service': [
                {
                    type: 'compute'
                },
                {
                    type: 'enclosure'
                }
            ]
        },
        NodeRelations: {
            /* There are two classes about the pair of relations:
             * component: one node is a component of the other
             *     e.g.  compute node vs. enclosure node
             *     expect behavior:
             *         the "By" in the relationType is used to tell component from its parent
             *         delete a node as well as its components;
             *         delete a component and update its parenet node
             * link: two nodes is linked to each other
             *     e.g.  compute node vs pdu node (TODO)
             *     expect behavior:
             *         delete one node and update the other
            */
            encloses: {
                mapping: 'enclosedBy',
                relationClass: 'component'
            },
            enclosedBy: {
                mapping: 'encloses',
                relationClass: 'component'
            },
            /* Below are an example used to verify function
             * currently used in unit test
             compute node:
             "relations": [
                 {
                     "relationType": "poweredBy",
                     "targets": [
                         "567b8f478b7444e407bb0729"
                     ]
                 }
             ],
             pdu node:
             "relations": [
                 {
                     "relationType": "powers",
                     "targets": [
                         "567b8f478b7444e407bb072a"
                         "567b8f478b7444e407bb072b"
                     ]
                 }
             ],
             If either of them is removed, the other node will only be updated without deletion
            */
            powers: {
                mapping: 'poweredBy',
                relationClass: 'link'
            },
            poweredBy: {
                mapping: 'powers',
                relationClass: 'link'
            },
            /* end example */
            contains: {
                mapping: 'containedBy',
                relationClass: 'link'
            },
            containedBy: {
                mapping: 'contains',
                relationClass: 'link'
            }
        },
        Scope: {
            Global: 'global'
        },
        NodeTypes: {
            ComputerContainer: 'compute-container',
            Compute: 'compute',
            Switch: 'switch',
            Dae: 'dae',
            Pdu: 'pdu',
            Mgmt: 'mgmt',
            Enclosure: 'enclosure',
            Rack: 'rack',
            Storage: 'storage',
            Iom: 'iom'
        },
        Redfish: {
            EventTypes: {
                StatusChange: 'StatusChange',
                ResourceUpdated: 'ResourceUpdated',
                ResourceAdded: 'ResourceAdded',
                ResourceRemoved: 'ResourceRemoved',
                Alert: 'Alert'
            }
        },
        HttpHeaders: {
            ApiProxyIp: 'X-RackHD-API-proxy-ip',
            ApiProxyPort: 'X-RackHD-API-proxy-port'
        },
        Heartbeat: {
            defaultIntervalSec: 10
        },
        HttpStaticDir: {
            systemDefault: 'static/http',
            userDefault: '/opt/monorail/static/http',
            skupack: 'skupack.d',
            upnp: 'static/upnp'
        },
        Progress: {
            DefaultTaskProgressMaximum: 100
        }
    });

    return constants;
}
<|endoftext|>


<commit_before>'use strict';

var co = require('co');
var Queue = require('co-priority-queue');
var proto = exports;

/**
 * use parallel operations pools
 * @param thunks
 * @param parallel  concurrent number
 * @returns {Promise | Promise<any>}
 * @private
 */
proto._thunkPool = function thunkPool(thunks, parallel) {
  var that = this;
  var _Promise = require('any-promise');
  var _done = 0;
  var _errs = [];

  function checkFinish(thunks, resolve) {
    _done++;
    if (_done === thunks.length) {
      resolve(_errs);
    }
  }

  function Limiter(concurrency, resolve) {
    var queue = new Queue();
    var endQueueSum = 0;
    // Create consumers
    for (var i = 0; i < concurrency; i++) {
      co(function *() {
        var yieldable;
        while (!that.isCancel()) {
          yieldable = yield queue.next();
          yield yieldable();
        }
        endQueueSum += 1;
        if (endQueueSum === concurrency) {
          queue.fns = [];
          queue.buffer = [];
          resolve();
        }
      }).catch(function (err) {
        console.error(err.stack);
      });
    }

    var limit = function(generator, priority) {
      return function(cb) {
        queue.push(function *() {
          try {
            cb(null, yield generator);
          } catch (err) {
            cb(err);
          }
        }, priority);
      };
    };

    return limit;
  }

  return new _Promise(function (resolve) {
    var _limit = new Limiter(parallel, resolve);
    for (var i = 0; i < thunks.length; i++) {
      co(function *() {
        yield _limit(thunks[i]);
        checkFinish(thunks, resolve);
      }).catch(function (err) {
        _errs.push(err);
        checkFinish(thunks, resolve);
      });
    }
  });
};

/**
 * cancel operation, now can use with multipartUpload
 */
proto.cancel = function () {
  this.options.cancelFlag = true;
}

proto.isCancel = function () {
  return this.options.cancelFlag;
}

proto.resetCancelFlag = function () {
  this.options.cancelFlag = false;
}<commit_msg>refactor(thunkpool): job function out of loops (#372)<commit_after>'use strict';

var co = require('co');
var Queue = require('co-priority-queue');
var proto = exports;

/**
 * use parallel operations pools
 * @param thunks
 * @param parallel  concurrent number
 * @returns {Promise | Promise<any>}
 * @private
 */
proto._thunkPool = function thunkPool(thunks, parallel) {
  var that = this;
  var _Promise = require('any-promise');
  var _done = 0;
  var _errs = [];

  function checkFinish(thunks, resolve) {
    _done++;
    if (_done === thunks.length) {
      resolve(_errs);
    }
  }

  function Limiter(concurrency, resolve) {
    var queue = new Queue();
    var endQueueSum = 0;
    function* concurrencyJob() {
      var yieldable;
      while (!that.isCancel()) {
        yieldable = yield queue.next();
        yield yieldable();
      }
      endQueueSum += 1;
      if (endQueueSum === concurrency) {
        queue.fns = [];
        queue.buffer = [];
        resolve();
      }
    }

    function catchError(err) {
      console.error(err.stack);
    }
    // Create consumers
    for (var i = 0; i < concurrency; i++) {
      co(concurrencyJob).catch(catchError);
    }

    var limit = function(generator, priority) {
      return function(cb) {
        queue.push(function *() {
          try {
            cb(null, yield generator);
          } catch (err) {
            cb(err);
          }
        }, priority);
      };
    };

    return limit;
  }

  return new _Promise(function (resolve) {
    var _limit = new Limiter(parallel, resolve);
    function* job() {
      yield _limit(thunks[i]);
      checkFinish(thunks, resolve);
    }

    function catchError(err) {
      _errs.push(err);
      checkFinish(thunks, resolve);
    }
    for (var i = 0; i < thunks.length; i++) {
      co(job).catch(catchError);
    }
  });
};

/**
 * cancel operation, now can use with multipartUpload
 */
proto.cancel = function () {
  this.options.cancelFlag = true;
}

proto.isCancel = function () {
  return this.options.cancelFlag;
}

proto.resetCancelFlag = function () {
  this.options.cancelFlag = false;
}<|endoftext|>