<commit_before>/*
 * grunt-release-bower
 * https://github.com/jkorona/grunt-release-bower
 *
 * Copyright (c) 2014 Jan Korona
 * Licensed under the MIT license.
 */
module.exports = function (grunt) {
  'use strict';

  var path = require('path');
  var inquirer = require('inquirer');
  var q = require('q');

  // a default options for release task
  var DEFAULT_OPTIONS = {
    // this option indicates root folder that should be used for components scanning.
    scanPath: 'dist',
    // this option specified name of the temporary directory used by task to get bower component
    tmpDir: 'tmp',
    // default message used to commit git changes
    commitMessage: 'Release <%= name %>, version <%= version %>.'
  };

  // import lo-dash
  var _ = grunt.util._;
  var fs = grunt.file;

  grunt.registerTask('release-bower', 'Release multiple Bower components.', function () {
    var options = this.options(DEFAULT_OPTIONS);
    var components = this.args;
    var bowerComponents;

    // scan given path in search for bower json files
    var bowerFiles = fs.expand({cwd: options.scanPath, matchBase: true}, 'bower.json');
    if (_.isEmpty(bowerFiles)) {
      grunt.fatal('Did not find any bower.json file in scan path \'' + options.scanPath + '\'.');
    } else {
      grunt.log.debug(grunt.log.wordlist(bowerFiles));
      bowerComponents = readBowerFiles(options.scanPath, bowerFiles);
    }

    // prepare asynchronous handling
    var done = this.async();

    var finalize = function (success) {
      fs.delete(options.tmpDir);
      done(success);
    };

    // create temp directory for task workspace
    fs.mkdir(options.tmpDir);

    function releaseAll(componentNames) {
      var promises = [];

      _.each(componentNames, function (componentName) {
        // match component with bower file
        if (bowerComponents.hasOwnProperty(componentName)) {
          this.push(release(bowerComponents[componentName]));
        } else {
          grunt.fatal('Couldn\'t match component \'' + componentName + '\' with corresponding bower.json file.');
        }
      }, promises);
      return q.all(promises);
    }

    function release(bowerComponent) {
      var version = grunt.option('version') || bowerComponent.version,
          increment = Semver.verifyIncrement(grunt.option('increment')),
          cwd = path.join(options.tmpDir, bowerComponent.name),
          git = gitRunner(cwd);

      grunt.verbose.writeln('Releasing component ' + bowerComponent.name + '...');

      return q.fcall(fs.mkdir, cwd)
          .then(git('clone', bowerComponent.url, '.'))
          .then(promise(clean, cwd))
          .then(promise(cp, bowerComponent.dir, cwd))
          .then(git('describe', '--tags'))
          .then(function (result) {
            var currentVersion = semver(result.toString());
            var requestedVersion;
            if (version === 'auto') {
              requestedVersion = currentVersion.pump(increment);
            } else {
              requestedVersion = semver(version);
              // if current version on the server is greater or equal to requested
              // we have to stop execution here since we can't release component
              // with earlier version than current one.
              if (currentVersion.compare(requestedVersion) >= 0) {
                grunt.fatal('Requested version ' + requestedVersion.toString() + ' is less than current server version (' + currentVersion.toString() + ').');
              }
            }
            // save new version in bower component descriptor
            bowerComponent.content.version = bowerComponent.version = requestedVersion.toString();

            grunt.log.writeln(grunt.template.process('Releasing <%= name %>#<%= version %> ...', {data: bowerComponent}));

            // once new version number is known, we have store modified bower.json file and finalize release
            return q.fcall(fs.write, path.join(cwd, 'bower.json'), pp(bowerComponent.content))
                .then(git('add', '--all'))
                .then(git('commit', '--allow-empty', '-m', grunt.template.process(options.commitMessage, {data: bowerComponent})))
                .then(git('tag', bowerComponent.version))
                .then(git('push', '-f', '--tags', 'origin', 'master'));
          })
          .fail(function (error) {
            grunt.fatal(error.message);
          });
    }

    // components to release were specified manually (grunt release:compA:compB
    if (!_.isEmpty(components)) {
      releaseAll(components).done(finalize);
    } else if (bowerFiles.length === 1) { // there is only one discovered
      release(_.values(bowerComponents)[0]).done(finalize);
    } else {
      inquirer.prompt([
        {
          type: 'checkbox',
          name: 'components',
          message: 'Choose which components you want to release',
          choices: _.keys(bowerComponents)
        }
      ], function (answers) {
        releaseAll(answers.components).done(finalize);
      });
    }

  });

  //-------------------------------------------------
  // FS integration
  //-------------------------------------------------

  function readBowerFiles(root, paths) {
    var bowerFiles = {};
    _.each(paths, function (bowerFilePath) {
      bowerFilePath = path.join(root, bowerFilePath);
      var bowerFile = fs.readJSON(bowerFilePath);
      if (bowerFile) {
        this[bowerFile.name] = {
          name: bowerFile.name,
          content: bowerFile,
          version: bowerFile.version,
          dir: path.dirname(bowerFilePath),
          url: bowerFile.repository.url
        };
      } else {
        grunt.fatal('File ' + bowerFilePath + ' can\'t be read or is empty.');
      }
    }, bowerFiles);
    return bowerFiles;
  }

  /**
   * Performs recursive copy of the source directory content to the destination folder.
   * @param src source path.
   * @param dest destination path.
   */
  function cp(src, dest) {
    _.each(fs.expand(path.join(src, '**', '*')), function (filePath) {
      var relativePath = path.relative(src, filePath);
      var destination = path.join(dest, relativePath);
      if (fs.isDir(filePath)) {
        fs.mkdir(destination);
      } else {
        fs.copy(filePath, destination);
      }
    });
  }

  /**
   * Removes all files from given directory except .git folder and its' content.
   * @param dir path to directory that should be cleaned.
   */
  function clean(dir) {
    _.each(fs.expand(path.join(dir, '*')), function (filePath) {
      if (fs.exists(filePath) && filePath !== '.git') {
        grunt.log.debug('Deleting file ' + filePath + '...');
        fs.delete(filePath);
      }
    });
  }

  //-------------------------------------------------
  // GIT support
  //-------------------------------------------------

  function gitRunner(cwd) {
    return function git() {
      var args = grunt.util.toArray(arguments);
      grunt.log.debug('running: git ' + args.join(' '));
      return function () {
        var deferred = q.defer();
        grunt.util.spawn({
          cmd: 'git',
          args: args,
          opts: {cwd: cwd}
        }, function (error, output) {
          if (error) {
            var message = 'Error while running git command \'' +
                'git ' + args.join(' ') + '\' in directory \'' + cwd + '\'. ' +
                'Problem was caused by: ' + error.message;
            deferred.reject(new Error(message));
          } else {
            deferred.resolve(output);
          }
        });
        return deferred.promise;
      };
    };
  }

  //-------------------------------------------------
  // Async support
  //-------------------------------------------------

  function promise() {
    var args = grunt.util.toArray(arguments);
    return function () {
      return q.fcall.apply(this, args);
    };
  }

  //-------------------------------------------------
  // Semver support
  //-------------------------------------------------

  /**
   * Semver class represents component version defined in the {@link http://semver.org/ Semantic Versioning convention}.
   *
   * @param string a string with version in correct semver format MAJOR.MINOR.PATCH.
   * @constructor
   */
  function Semver(string) {
    Semver.assert(string);
    var parts = string.split('.');
    this.major = parseInt(parts[0], 10);
    this.minor = parseInt(parts[1], 10);
    this.patch = parseInt(parts[2], 10);
  }

  Semver.prototype = {
    /**
     * Increases version number using increment factor.
     *
     * @param increment indicates which part of version should be pumped (major, minor, patch).
     * @returns {*} current Semver instance for method chaining.
     */
    pump: function (increment) {
      increment = increment || Semver.PATCH; // default is patch
      switch (increment) {
        /* jshint indent: false */
        case Semver.MAJOR:
          this.major++;
          this.minor = this.patch = 0;
          break;
        case Semver.MINOR:
          this.minor++;
          this.patch = 0;
          break;
        case Semver.PATCH:
          this.patch++;
          break;
      }
      return this;
    },
    /**
     * Returns array representation of Semver object.
     * @returns {Array} array with three elements corresponding to veresion parts: [MAJOR, MINOR, PATCH].
     */
    toArray: function () {
      return [
        this.major,
        this.minor,
        this.patch
      ];
    },
    /**
     * Returns string representation of the Semver object.
     * @returns {string}
     */
    toString: function () {
      return this.toArray().join('.');
    },
    compare: function (semver) {
      function compInt(intValueA, intValueB) {
        function b2i(b) {
          return b ? 1 : 0;
        }
        return b2i(intValueA > intValueB) - b2i(intValueA < intValueB);
      }

      for (var i = 0; i < 3; i++) {
        var partResult = compInt(this.toArray()[i], semver.toArray[i]);
        if (partResult) {
          return partResult;
        }
      }
      return 0;
    },
    equals: function (semver) {
      return this.compare(semver) === 0;
    }
  };

  // possible values for the 'increment' flag. Default is 'patch'.
  Semver.MAJOR = 'major';
  Semver.MINOR = 'minor';
  Semver.PATCH = 'patch';
  Semver.INCREMENTS = [
    Semver.MAJOR,
    Semver.MINOR,
    Semver.PATCH
  ];
  Semver.verifyIncrement = function (value) {
    value = value || 'patch';
    if (!_.contains(Semver.INCREMENTS, value)) {
      grunt.fatal('Given value \'' + value + '\' does not match any possible option for --increment flag. ' +
      'Possible values are \'major\', \'minor\', \'patch\'');
    }
    return value;
  };

  /**
   * Static method that evaluates given string for correctness with semver convention for versioninig:
   * MAJOR.MINOR.PATCH
   *
   * @param versionString a string to evaluate.
   */
  Semver.assert = function (versionString) {
    if (!(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(versionString))) {
      throw new Error('Given version string \'' + versionString + '\' does not match Semver specification.');
    }
  };

  /**
   * Factory method that creates new instance of Semver class for given string.
   *
   * @param versionString a string with version number for which Semver instance should be created.
   * @returns {module.Semver} a newly created Semver instance.
   */
  function semver(versionString) {
    return new Semver(versionString);
  }

  //-------------------------------------------------
  // JSON pretty print
  //-------------------------------------------------

  /**
   * Simple pretty print function which converts given JavaScript object to the
   * JSON string with human readable indentations.
   *
   * Used to produce bower.json files.
   *
   * This function can be replaced by some already existing library, but I didn't find
   * anything lightweight enough by now.
   *
   * @param object a JavaScript object with content to print.
   * @returns {string} formatted JSON string.
   */
  function pp(object) {
    var ind = 0;
    var json = JSON.stringify(object);
    var result = '';
    for (var i = 0; i < json.length; i++) {
      var letter = json[i];
      switch (letter) {
        /* jshint indent: false */
        case '{':
        /* falls through */
        case '[':
          result += letter + '\n';
          ind++;
          result += grunt.util.repeat(ind, '\t');
          break;
        case '}':
        /* falls through */
        case ']':
          ind--;
          result += '\n' + grunt.util.repeat(ind, '\t') + letter;
          break;
        case ',':
          result += letter + '\n';
          result += grunt.util.repeat(ind, '\t');
          break;
        default:
          result += letter;
      }
    }
    return result;
  }

};<commit_msg>Changed line indent to 4 for better readability<commit_after>/*
 * grunt-release-bower
 * https://github.com/jkorona/grunt-release-bower
 *
 * Copyright (c) 2014 Jan Korona
 * Licensed under the MIT license.
 */
module.exports = function (grunt) {
    'use strict';

    var path = require('path');
    var inquirer = require('inquirer');
    var q = require('q');

    // a default options for release task
    var DEFAULT_OPTIONS = {
        // this option indicates root folder that should be used for components scanning.
        scanPath: 'dist',
        // this option specified name of the temporary directory used by task to get bower component
        tmpDir: 'tmp',
        // default message used to commit git changes
        commitMessage: 'Release <%= name %>, version <%= version %>.'
    };

    // import lo-dash
    var _ = grunt.util._;
    var fs = grunt.file;

    grunt.registerTask('release-bower', 'Release multiple Bower components.', function () {
        var options = this.options(DEFAULT_OPTIONS);
        var components = this.args;
        var bowerComponents;

        // scan given path in search for bower json files
        var bowerFiles = fs.expand({cwd: options.scanPath, matchBase: true}, 'bower.json');
        if (_.isEmpty(bowerFiles)) {
            grunt.fatal('Did not find any bower.json file in scan path \'' + options.scanPath + '\'.');
        } else {
            grunt.log.debug(grunt.log.wordlist(bowerFiles));
            bowerComponents = readBowerFiles(options.scanPath, bowerFiles);
        }

        // prepare asynchronous handling
        var done = this.async();

        var finalize = function (success) {
            fs.delete(options.tmpDir);
            done(success);
        };

        // create temp directory for task workspace
        fs.mkdir(options.tmpDir);

        function releaseAll(componentNames) {
            var promises = [];

            _.each(componentNames, function (componentName) {
                // match component with bower file
                if (bowerComponents.hasOwnProperty(componentName)) {
                    this.push(release(bowerComponents[componentName]));
                } else {
                    grunt.fatal('Couldn\'t match component \'' + componentName + '\' with corresponding bower.json file.');
                }
            }, promises);
            return q.all(promises);
        }

        function release(bowerComponent) {
            var version = grunt.option('version') || bowerComponent.version,
                increment = Semver.verifyIncrement(grunt.option('increment')),
                cwd = path.join(options.tmpDir, bowerComponent.name),
                git = gitRunner(cwd);

            grunt.verbose.writeln('Releasing component ' + bowerComponent.name + '...');

            return q.fcall(fs.mkdir, cwd)
                .then(git('clone', bowerComponent.url, '.'))
                .then(promise(clean, cwd))
                .then(promise(cp, bowerComponent.dir, cwd))
                .then(git('describe', '--tags'))
                .then(function (result) {
                    var currentVersion = semver(result.toString());
                    var requestedVersion;
                    if (version === 'auto') {
                        requestedVersion = currentVersion.pump(increment);
                    } else {
                        requestedVersion = semver(version);
                        // if current version on the server is greater or equal to requested
                        // we have to stop execution here since we can't release component
                        // with earlier version than current one.
                        if (currentVersion.compare(requestedVersion) >= 0) {
                            grunt.fatal('Requested version ' + requestedVersion.toString() + ' is less than current server version (' + currentVersion.toString() + ').');
                        }
                    }
                    // save new version in bower component descriptor
                    bowerComponent.content.version = bowerComponent.version = requestedVersion.toString();

                    grunt.log.writeln(grunt.template.process('Releasing <%= name %>#<%= version %> ...', {data: bowerComponent}));

                    // once new version number is known, we have store modified bower.json file and finalize release
                    return q.fcall(fs.write, path.join(cwd, 'bower.json'), pp(bowerComponent.content))
                        .then(git('add', '--all'))
                        .then(git('commit', '--allow-empty', '-m', grunt.template.process(options.commitMessage, {data: bowerComponent})))
                        .then(git('tag', bowerComponent.version))
                        .then(git('push', '-f', '--tags', 'origin', 'master'));
                })
                .fail(function (error) {
                    grunt.fatal(error.message);
                });
        }

        // components to release were specified manually (grunt release:compA:compB
        if (!_.isEmpty(components)) {
            releaseAll(components).done(finalize);
        } else if (bowerFiles.length === 1) { // there is only one discovered
            release(_.values(bowerComponents)[0]).done(finalize);
        } else {
            inquirer.prompt([
                {
                    type: 'checkbox',
                    name: 'components',
                    message: 'Choose which components you want to release',
                    choices: _.keys(bowerComponents)
                }
            ], function (answers) {
                releaseAll(answers.components).done(finalize);
            });
        }

    });

    //-------------------------------------------------
    // FS integration
    //-------------------------------------------------

    function readBowerFiles(root, paths) {
        var bowerFiles = {};
        _.each(paths, function (bowerFilePath) {
            bowerFilePath = path.join(root, bowerFilePath);
            var bowerFile = fs.readJSON(bowerFilePath);
            if (bowerFile) {
                this[bowerFile.name] = {
                    name: bowerFile.name,
                    content: bowerFile,
                    version: bowerFile.version,
                    dir: path.dirname(bowerFilePath),
                    url: bowerFile.repository.url
                };
            } else {
                grunt.fatal('File ' + bowerFilePath + ' can\'t be read or is empty.');
            }
        }, bowerFiles);
        return bowerFiles;
    }

    /**
     * Performs recursive copy of the source directory content to the destination folder.
     * @param src source path.
     * @param dest destination path.
     */
    function cp(src, dest) {
        _.each(fs.expand(path.join(src, '**', '*')), function (filePath) {
            var relativePath = path.relative(src, filePath);
            var destination = path.join(dest, relativePath);
            if (fs.isDir(filePath)) {
                fs.mkdir(destination);
            } else {
                fs.copy(filePath, destination);
            }
        });
    }

    /**
     * Removes all files from given directory except .git folder and its' content.
     * @param dir path to directory that should be cleaned.
     */
    function clean(dir) {
        _.each(fs.expand(path.join(dir, '*')), function (filePath) {
            if (fs.exists(filePath) && filePath !== '.git') {
                grunt.log.debug('Deleting file ' + filePath + '...');
                fs.delete(filePath);
            }
        });
    }

    //-------------------------------------------------
    // GIT support
    //-------------------------------------------------

    function gitRunner(cwd) {
        return function git() {
            var args = grunt.util.toArray(arguments);
            grunt.log.debug('running: git ' + args.join(' '));
            return function () {
                var deferred = q.defer();
                grunt.util.spawn({
                    cmd: 'git',
                    args: args,
                    opts: {cwd: cwd}
                }, function (error, output) {
                    if (error) {
                        var message = 'Error while running git command \'' +
                            'git ' + args.join(' ') + '\' in directory \'' + cwd + '\'. ' +
                            'Problem was caused by: ' + error.message;
                        deferred.reject(new Error(message));
                    } else {
                        deferred.resolve(output);
                    }
                });
                return deferred.promise;
            };
        };
    }

    //-------------------------------------------------
    // Async support
    //-------------------------------------------------

    function promise() {
        var args = grunt.util.toArray(arguments);
        return function () {
            return q.fcall.apply(this, args);
        };
    }

    //-------------------------------------------------
    // Semver support
    //-------------------------------------------------

    /**
     * Semver class represents component version defined in the {@link http://semver.org/ Semantic Versioning convention}.
     *
     * @param string a string with version in correct semver format MAJOR.MINOR.PATCH.
     * @constructor
     */
    function Semver(string) {
        Semver.assert(string);
        var parts = string.split('.');
        this.major = parseInt(parts[0], 10);
        this.minor = parseInt(parts[1], 10);
        this.patch = parseInt(parts[2], 10);
    }

    Semver.prototype = {
        /**
         * Increases version number using increment factor.
         *
         * @param increment indicates which part of version should be pumped (major, minor, patch).
         * @returns {*} current Semver instance for method chaining.
         */
        pump: function (increment) {
            increment = increment || Semver.PATCH; // default is patch
            switch (increment) {
                /* jshint indent: false */
                case Semver.MAJOR:
                    this.major++;
                    this.minor = this.patch = 0;
                    break;
                case Semver.MINOR:
                    this.minor++;
                    this.patch = 0;
                    break;
                case Semver.PATCH:
                    this.patch++;
                    break;
            }
            return this;
        },
        /**
         * Returns array representation of Semver object.
         * @returns {Array} array with three elements corresponding to veresion parts: [MAJOR, MINOR, PATCH].
         */
        toArray: function () {
            return [
                this.major,
                this.minor,
                this.patch
            ];
        },
        /**
         * Returns string representation of the Semver object.
         * @returns {string}
         */
        toString: function () {
            return this.toArray().join('.');
        },
        compare: function (semver) {
            function compInt(intValueA, intValueB) {
                function b2i(b) {
                    return b ? 1 : 0;
                }

                return b2i(intValueA > intValueB) - b2i(intValueA < intValueB);
            }

            for (var i = 0; i < 3; i++) {
                var partResult = compInt(this.toArray()[i], semver.toArray[i]);
                if (partResult) {
                    return partResult;
                }
            }
            return 0;
        },
        equals: function (semver) {
            return this.compare(semver) === 0;
        }
    };

    // possible values for the 'increment' flag. Default is 'patch'.
    Semver.MAJOR = 'major';
    Semver.MINOR = 'minor';
    Semver.PATCH = 'patch';
    Semver.INCREMENTS = [
        Semver.MAJOR,
        Semver.MINOR,
        Semver.PATCH
    ];
    Semver.verifyIncrement = function (value) {
        value = value || 'patch';
        if (!_.contains(Semver.INCREMENTS, value)) {
            grunt.fatal('Given value \'' + value + '\' does not match any possible option for --increment flag. ' +
            'Possible values are \'major\', \'minor\', \'patch\'');
        }
        return value;
    };

    /**
     * Static method that evaluates given string for correctness with semver convention for versioninig:
     * MAJOR.MINOR.PATCH
     *
     * @param versionString a string to evaluate.
     */
    Semver.assert = function (versionString) {
        if (!(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(versionString))) {
            throw new Error('Given version string \'' + versionString + '\' does not match Semver specification.');
        }
    };

    /**
     * Factory method that creates new instance of Semver class for given string.
     *
     * @param versionString a string with version number for which Semver instance should be created.
     * @returns {module.Semver} a newly created Semver instance.
     */
    function semver(versionString) {
        return new Semver(versionString);
    }

    //-------------------------------------------------
    // JSON pretty print
    //-------------------------------------------------

    /**
     * Simple pretty print function which converts given JavaScript object to the
     * JSON string with human readable indentations.
     *
     * Used to produce bower.json files.
     *
     * This function can be replaced by some already existing library, but I didn't find
     * anything lightweight enough by now.
     *
     * @param object a JavaScript object with content to print.
     * @returns {string} formatted JSON string.
     */
    function pp(object) {
        var ind = 0;
        var json = JSON.stringify(object);
        var result = '';
        for (var i = 0; i < json.length; i++) {
            var letter = json[i];
            switch (letter) {
                /* jshint indent: false */
                case '{':
                /* falls through */
                case '[':
                    result += letter + '\n';
                    ind++;
                    result += grunt.util.repeat(ind, '\t');
                    break;
                case '}':
                /* falls through */
                case ']':
                    ind--;
                    result += '\n' + grunt.util.repeat(ind, '\t') + letter;
                    break;
                case ',':
                    result += letter + '\n';
                    result += grunt.util.repeat(ind, '\t');
                    break;
                default:
                    result += letter;
            }
        }
        return result;
    }

};<|endoftext|>


<commit_before>/*
 * grunt-release-branch
 *
 * Copyright (c) 2013 Christoph Burgdorf, contributors
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

    var fs              = require("fs"),
        exec            = require('child_process').exec,
        defaultOptions  = {
            releaseBranch: 'gh-pages',
            remoteRepository: 'origin',
            distDir: 'dist',
            commitMessage: 'RELEASE',
            commit: true,
            push: false,
            blacklist: [
                '.git'
            ]
        };

    grunt.registerMultiTask('releaseBranchPre','release dist as branch', function(){

        var options = this.options(defaultOptions);

        var done = this.async();

        var releaseBranch = options.releaseBranch;
        exec('git branch -D ' +  releaseBranch + '; git checkout -b ' + releaseBranch, options.execOptions, function(){
            done();
        });

        grunt.log.writeln('running release branch pre task...');
    });

    grunt.registerMultiTask('releaseBranch','release dist as branch', function(){

        var options = this.options(defaultOptions);

        options.blacklist.push(options.distDir);
        var blacklist = options.blacklist;

        var rmdirRec = function(path) {
            var files = [];
            if( fs.existsSync(path) ) {
                files = fs.readdirSync(path);
                files.forEach(function(file,index){
                    var curPath = path + "/" + file;
                    if(fs.statSync(curPath).isDirectory()) { // recurse
                        rmdirRec(curPath);
                    } else { // delete file
                        fs.unlinkSync(curPath);
                    }
                });
                fs.rmdirSync(path);
            }
        };

        var done = this.async();

        fs.readdir('.', function(err, contents){

            contents.forEach(function(name, index){
                if (blacklist.indexOf(name) === -1){
                    fs.lstat(name, function(err, stats) {
                        if (!err && stats.isDirectory()) {
                            grunt.log.writeln('delete directory: ' + name);
                            rmdirRec(name);
                        }
                        else{
                            grunt.log.writeln('delete file: ' + name);
                            fs.unlink(name);
                        }
                    });
                }
            });

            //move all files from the dist dir to the root level
            exec('mv ' + options.distDir + '/* .', function(){

                //now that everything has been moved. Delete the dist dir
                rmdirRec(options.distDir);

                if (options.commit){

                    grunt.log.writeln('commiting files as: ' + options.commitMessage);

                    exec('git add -A && git commit -m "' + options.commitMessage + '"', function(){

                        if (options.push){

                            grunt.log.writeln('pushing commit to: ' + options.releaseBranch);
                            exec('git push -f ' + options.remoteRepository + ' ' + options.releaseBranch, function(){
                                done();
                            });
                        }
                        else{
                            done();
                        }
                    });
                }
                else{
                    done();
                }
            });
        });

        grunt.log.writeln('running release branch task...');
    });
};<commit_msg>fix(releaseBranch): fixed race condition<commit_after>/*
 * grunt-release-branch
 *
 * Copyright (c) 2013 Christoph Burgdorf, contributors
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

    var fs              = require("fs"),
        exec            = require('child_process').exec,
        defaultOptions  = {
            releaseBranch: 'gh-pages',
            remoteRepository: 'origin',
            distDir: 'dist',
            commitMessage: 'RELEASE',
            commit: true,
            push: false,
            blacklist: [
                '.git'
            ]
        };

    grunt.registerMultiTask('releaseBranchPre','release dist as branch', function(){

        var options = this.options(defaultOptions);

        var done = this.async();

        var releaseBranch = options.releaseBranch;
        exec('git branch -D ' +  releaseBranch + '; git checkout -b ' + releaseBranch, options.execOptions, function(){
            done();
        });

        grunt.log.writeln('running release branch pre task...');
    });

    grunt.registerMultiTask('releaseBranch','release dist as branch', function(){

        var options = this.options(defaultOptions);

        options.blacklist.push(options.distDir);
        var blacklist = options.blacklist;

        var rmdirRec = function(path) {
            var files = [];
            if( fs.existsSync(path) ) {
                files = fs.readdirSync(path);
                files.forEach(function(file,index){
                    var curPath = path + "/" + file;
                    if(fs.statSync(curPath).isDirectory()) { // recurse
                        rmdirRec(curPath);
                    } else { // delete file
                        fs.unlinkSync(curPath);
                    }
                });
                fs.rmdirSync(path);
            }
        };

        var done = this.async();

        fs.readdir('.', function(err, contents){

            contents.forEach(function(name, index){
                if (blacklist.indexOf(name) === -1){
                    var stats = fs.lstatSync(name);

                    if (!err && stats.isDirectory()) {
                        grunt.log.writeln('delete directory: ' + name);
                        rmdirRec(name);
                    }
                    else{
                        grunt.log.writeln('delete file: ' + name);
                        fs.unlinkSync(name);
                    }
                }
            });
            grunt.log.writeln('now moving files from ' + options.distDir + ' to root level');
            //move all files from the dist dir to the root level
            exec('mv ' + options.distDir + '/* .', function(){

                //now that everything has been moved. Delete the dist dir
                rmdirRec(options.distDir);

                if (options.commit){

                    grunt.log.writeln('commiting files as: ' + options.commitMessage);

                    exec('git add -A && git commit -m "' + options.commitMessage + '"', function(){

                        if (options.push){

                            grunt.log.writeln('pushing commit to: ' + options.releaseBranch);
                            exec('git push -f ' + options.remoteRepository + ' ' + options.releaseBranch, function(){
                                done();
                            });
                        }
                        else{
                            done();
                        }
                    });
                }
                else{
                    done();
                }
            });
        });

        grunt.log.writeln('running release branch task...');
    });
};<|endoftext|>


<commit_before>var _ = require('lodash');
var Q = require('q');

module.exports = function (grunt) {
    return;

    var promises = require('./lib/promises').init(grunt);
    var logger = require('./lib/logger').init(grunt);
    var config = require('./lib/config').init(grunt);

    /**
     * Loads the tasks from the grunt folder.
     */
    var subTasks = _.mapValues({
        'sass': {},
        'index': {},
        'watcher': {}
    }, function (value, key) {
        grunt.verbose.writeln("Loading sub-task " + key);
        return {
            name: key,
            target: null,
            config: require('./grunt/' + key)(grunt)
        };
    });

    /**
     * @param {string} prefix Corresponds to the key in grunt config.
     * @param {string[]} taskNames List of subTask names to run in that order (supports config names task:name)
     * @param {Object} options The options loaded via config.defaults
     */
    function runTasks(prefix, taskNames, options) {
        grunt.verbose.writeln("Options: " + JSON.stringify(options));
        var tasks = _.map(taskNames, function (taskName) {
            var name = taskName.split(':');
            if (!subTasks.hasOwnProperty(name[0])) {
                grunt.fail.fatal('subTask is not defined: ' + name[0]);
            }
            var task = _.clone(subTasks[name[0]]);
            task.target = name.length == 2 ? name[1] : null;
            return task;
        });
        _.each(tasks, function (subTask) {
            grunt.verbose.writeln('Running: ' + subTask.name + ':' + subTask.target);
            var opt = _.clone(options);
            opt[subTask.name] = grunt.config.get(prefix + subTask.name) || {};
            grunt.config.set(subTask.name, subTask.config(opt));
            grunt.task.run([subTask.name + (subTask.target ? ':' + subTask.target : '')]);
        });
    }

    grunt.task.registerTask('watch', 'Watches for changes to the SCSS and JS files.', function () {
        var done = this.async();
        config.defaults(this).then(function (options) {
            runTasks('', ['watcher'], options);
        }).catch(function(err){
            grunt.fail.fatal(err);
        }).finally(function () {
            done();
        });
    });

    grunt.task.registerTask('dev', 'Builds the development version of the project.', function () {
        var done = this.async();
        config.defaults(this).then(function (options) {
            runTasks('dev.', [
                'sass:dev',
                'index'
            ], options);
        }).catch(function(err){
            grunt.fail.fatal(err);
        }).finally(function () {
            done();
        });
    });

    grunt.task.registerTask('build', 'Builds the production version of the project.', function () {
        var done = this.async();
        config.defaults(this).then(function (options) {
            runTasks('prod.', [
                'sass:dev',
                'package'
            ], options);
        }).catch(function(err){
            grunt.fail.fatal(err);
        }).finally(function () {
            done();
        });
    });
};
<commit_msg>removed<commit_after><|endoftext|>


<commit_before>var FormData     = require('form-data');

require('sugar');

var url          = require('url'),
    util         = require('util');

var VcapClient = module.exports = function (info) {
    /**
     * VCAP cloudfoundry client.
     *
     * Parameters
     *
     * - info: object containing the following
     *   - host (required): host of CF deployment
     *   - protocol: http: vs https:
     *   - one of either:
     *     - token (access token)
     *     - email,password (two separate fields)
     */

    // ~~~~~ PRIVATE
    var self = this;

    if (! info.host) {
        return new TypeError('host must be provided');
    }

    var request = require('./request')(info.protocol || 'http:', info.host,
            info.token, info.email, info.password);

    // ~~~~~ PUBLIC

    var Collections = require('./collections');
    var collections = new Collections(request);

    this.apps = collections.create('apps', {
        name: { type: 'string' },
        space_guid: { type: 'string' },
    }, [ 'routes', 'summary', 'service_bindings', {
        method: 'instances',
        nested: [{
            method:     'logs',
            endpoint:   'files/logs'
        }],
        resultsMap:     function (results) {
            // the result from CF seems to be inconsistent. rather than an
            // array of instances, it's a map where keys are string index
            // numbers. We convert it here, recording the index to the `index`
            // field as a parsed int

            var asArray = [];

            Object.keys(results[0], function (key, value) {
                value.index = parseInt(key, 10);
                asArray[value.index] = value;
            });

            return asArray;
        }
    }]);

    this.services = collections.create('services', {
        label: { type: 'string' },
        url: { type: 'string' },
        provider: { type: 'string' },
        version: { type: 'string' },
        description: { type: 'string' },
    }, [ 'service_plans' ]);

    this.services.getByName = function (name, callback) {
        this.getBy(function (each) {
            return each.entity.label === name;
        }, callback);
    };

    this.users = collections.create('users', {});

    this.servicePlans = collections.create('service_plans', {
        name: { type: 'string' },
        free: { type: 'bool' },
        description: { type: 'string' },
    });

    this.serviceInstances = collections.create('service_instances', {
        name: { type: 'string' },
        space_guid: { type: 'string' },
        service_plan_guid: { type: 'string' },
    });

    this.serviceKeys = collections.create('service_keys', {
	service_instance_guid: { type: 'string' },
	name: { type: 'string' },
    });

    this.orgs = this.organizations = collections.create('organizations', {
        name: { type: 'string' }
    });

    this.spaces =     collections.create('spaces', {
        name: { type: 'string' },
        organization_guid: { type: 'string' }
    }, [ 'service_instances' ]);

    this.routes = collections.create('routes');
    this.domains = collections.create('domains');
    this.runtimes = collections.create('runtimes');
    this.frameworks = collections.create('frameworks');
    this.events = collections.create('events');

    // ~ applications

    this.apps.upload = function (guid, zipFile, callback) {
        var fileStream = typeof zipFile === 'string' ?
            require('fs').createReadStream(zipFile) :
            zipFile;

        var form = new FormData();
        form.append('application', fileStream,
                { contentType: 'application/zip' });

        form.append('resources', '[]');

        form.getLength(function (err, length) {
            if (err) {
                return callback(err);
            }

            var req = request({
                endpoint: [ 'apps', guid, 'bits' ].join('/'),
                method: 'PUT'
            }, callback);

            req.setHeader('Content-Length', length);
            req._form = form;
        });
    };

    this.apps.restart = function (id, callback) {
        var self = this;
        this.stop(id, function (err) {
            if (err) {
                return callback(err);
            }

            self.start(id, callback);
        });
    };

    this.apps.stop = function (id, callback) {
        self.apps.update(id, { state: 'STOPPED' }, callback);
    };

    this.apps.start = function (id, callback) {
        self.apps.update(id, { state: 'STARTED' }, callback);
    };
};
<commit_msg>Updated indenting for jshint.<commit_after>var FormData     = require('form-data');

require('sugar');

var url          = require('url'),
    util         = require('util');

var VcapClient = module.exports = function (info) {
    /**
     * VCAP cloudfoundry client.
     *
     * Parameters
     *
     * - info: object containing the following
     *   - host (required): host of CF deployment
     *   - protocol: http: vs https:
     *   - one of either:
     *     - token (access token)
     *     - email,password (two separate fields)
     */

    // ~~~~~ PRIVATE
    var self = this;

    if (! info.host) {
        return new TypeError('host must be provided');
    }

    var request = require('./request')(info.protocol || 'http:', info.host,
            info.token, info.email, info.password);

    // ~~~~~ PUBLIC

    var Collections = require('./collections');
    var collections = new Collections(request);

    this.apps = collections.create('apps', {
        name: { type: 'string' },
        space_guid: { type: 'string' },
    }, [ 'routes', 'summary', 'service_bindings', {
        method: 'instances',
        nested: [{
            method:     'logs',
            endpoint:   'files/logs'
        }],
        resultsMap:     function (results) {
            // the result from CF seems to be inconsistent. rather than an
            // array of instances, it's a map where keys are string index
            // numbers. We convert it here, recording the index to the `index`
            // field as a parsed int

            var asArray = [];

            Object.keys(results[0], function (key, value) {
                value.index = parseInt(key, 10);
                asArray[value.index] = value;
            });

            return asArray;
        }
    }]);

    this.services = collections.create('services', {
        label: { type: 'string' },
        url: { type: 'string' },
        provider: { type: 'string' },
        version: { type: 'string' },
        description: { type: 'string' },
    }, [ 'service_plans' ]);

    this.services.getByName = function (name, callback) {
        this.getBy(function (each) {
            return each.entity.label === name;
        }, callback);
    };

    this.users = collections.create('users', {});

    this.servicePlans = collections.create('service_plans', {
        name: { type: 'string' },
        free: { type: 'bool' },
        description: { type: 'string' },
    });

    this.serviceInstances = collections.create('service_instances', {
        name: { type: 'string' },
        space_guid: { type: 'string' },
        service_plan_guid: { type: 'string' },
    });

    this.serviceKeys = collections.create('service_keys', {
        service_instance_guid: { type: 'string' },
        name: { type: 'string' },
    });

    this.orgs = this.organizations = collections.create('organizations', {
        name: { type: 'string' }
    });

    this.spaces =     collections.create('spaces', {
        name: { type: 'string' },
        organization_guid: { type: 'string' }
    }, [ 'service_instances' ]);

    this.routes = collections.create('routes');
    this.domains = collections.create('domains');
    this.runtimes = collections.create('runtimes');
    this.frameworks = collections.create('frameworks');
    this.events = collections.create('events');

    // ~ applications

    this.apps.upload = function (guid, zipFile, callback) {
        var fileStream = typeof zipFile === 'string' ?
            require('fs').createReadStream(zipFile) :
            zipFile;

        var form = new FormData();
        form.append('application', fileStream,
                { contentType: 'application/zip' });

        form.append('resources', '[]');

        form.getLength(function (err, length) {
            if (err) {
                return callback(err);
            }

            var req = request({
                endpoint: [ 'apps', guid, 'bits' ].join('/'),
                method: 'PUT'
            }, callback);

            req.setHeader('Content-Length', length);
            req._form = form;
        });
    };

    this.apps.restart = function (id, callback) {
        var self = this;
        this.stop(id, function (err) {
            if (err) {
                return callback(err);
            }

            self.start(id, callback);
        });
    };

    this.apps.stop = function (id, callback) {
        self.apps.update(id, { state: 'STOPPED' }, callback);
    };

    this.apps.start = function (id, callback) {
        self.apps.update(id, { state: 'STARTED' }, callback);
    };
};
<|endoftext|>


<commit_before>//
// Vows.js - asynchronous event-based BDD for node.js
//
//   usage:
//
//       var vows = require('vows');
//
//       vows.describe('Deep Thought').addBatch({
//           "An instance of DeepThought": {
//               topic: new DeepThought,
//
//               "should know the answer to the ultimate question of life": function (deepThought) {
//                   assert.equal (deepThought.question('what is the answer to the universe?'), 42);
//               }
//           }
//       }).run();
//
var sys = require('sys'),
    path = require('path'),
    events = require('events'),
    vows = exports;

require.paths.unshift(__dirname);

// Options
vows.options = {
    Emitter: events.EventEmitter,
    reporter: require('vows/reporters/dot-matrix'),
    matcher: /.*/
};

vows.__defineGetter__('reporter', function () {
    return vows.options.reporter;
});

var stylize = require('vows/console').stylize;
var console = require('vows/console');

vows.inspect = require('vows/console').inspect;
vows.prepare = require('vows/extras').prepare;
vows.tryEnd = require('vows/suite').tryEnd;

//
// Assertion Macros & Extensions
//
require('./assert/error');
require('./assert/macros');

//
// Suite constructor
//
var Suite = require('vows/suite').Suite;

//
// This function gets added to events.EventEmitter.prototype, by default.
// It's essentially a wrapper around `addListener`, which adds all the specification
// goodness.
//
function addVow(vow) {
    var batch = vow.batch;

    batch.total ++;
    batch.vows.push(vow);

    return this.addListener("success", function () {
        var args = Array.prototype.slice.call(arguments);
        // If the callback is expecting two or more arguments,
        // pass the error as the first (null) and the result after.
        if (vow.callback.length >= 2) {
            args.unshift(null);
        }
        runTest(args);
        vows.tryEnd(batch);

    }).addListener("error", function (err) {
        var exception;

        if (vow.callback.length >= 2) {
            runTest([err]);
        } else {
            exception = { type: 'promise', error: err };
            batch.errored ++;
            output('errored', exception);
        }
        vows.tryEnd(batch);
    });

    function runTest(args) {
        var exception, topic, status;

        if (vow.callback instanceof String) {
            return output('pending');
        }

        // Run the test, and try to catch `AssertionError`s and other exceptions;
        // increment counters accordingly.
        try {
            vow.callback.apply(vow.binding || null, args);
            output('honored', exception);
        } catch (e) {
            if (e.name && e.name.match(/AssertionError/)) {
                exception = e.toString();
                output('broken', exception);
            } else {
                exception = e.stack || e.message || e.toString() || e;
                output('errored', exception);
            }
        }
    }

    function output(status, exception) {
        batch[status] ++;
        vow.status = status;

        if (vow.context && batch.lastContext !== vow.context) {
            batch.lastContext = vow.context;
            batch.suite.report(['context', vow.context]);
        }
        batch.suite.report(['vow', {
            title: vow.description,
            context: vow.context,
            status: status,
            exception: exception || null
        }]);
    }
};

//
// On exit, check that all promises have been fired.
// If not, report an error message.
//
process.addListener('exit', function () {
    var results = { honored: 0, broken: 0, errored: 0, pending: 0, total: 0 }, failure;

    vows.suites.forEach(function (s) {
        if ((s.results.total > 0) && (s.results.time === null)) {
            s.reporter.report(['error', { error: "Asynchronous Error", suite: s }]);
        }
        s.batches.forEach(function (b) {
            var unFired = [];

            b.vows.forEach(function (vow) {
                if (! vow.status) {
                    if (unFired.indexOf(vow.context) === -1) {
                        unFired.push(vow.context);
                    }
                }
            });

            if (unFired.length > 0) { sys.print('\n') }

            unFired.forEach(function (title) {
                s.reporter.report(['error', {
                    error: "not fired!",
                    context: title,
                    batch: b,
                    suite: s
                }]);
            });

            if (b.status === 'begin') {
                failure = true;
                results.errored ++;
                results.total ++;
            }
            Object.keys(results).forEach(function (k) { results[k] += b[k] });
        });
    });
    if (failure) {
        sys.puts(console.result(results));
    }
});

vows.suites = [];

//
// Create a new test suite
//
vows.describe = function (subject) {
    var suite = new(Suite)(subject);

    this.options.Emitter.prototype.addVow = addVow;
    this.suites.push(suite);

    return suite;
};

vows.version = require('fs').readFileSync(path.join(__dirname, '..', 'package.json'))
                            .toString().match(/"version"\s*:\s*"([\d.]+)"/)[1];
<commit_msg>more refactoring in addVow<commit_after>//
// Vows.js - asynchronous event-based BDD for node.js
//
//   usage:
//
//       var vows = require('vows');
//
//       vows.describe('Deep Thought').addBatch({
//           "An instance of DeepThought": {
//               topic: new DeepThought,
//
//               "should know the answer to the ultimate question of life": function (deepThought) {
//                   assert.equal (deepThought.question('what is the answer to the universe?'), 42);
//               }
//           }
//       }).run();
//
var sys = require('sys'),
    path = require('path'),
    events = require('events'),
    vows = exports;

require.paths.unshift(__dirname);

// Options
vows.options = {
    Emitter: events.EventEmitter,
    reporter: require('vows/reporters/dot-matrix'),
    matcher: /.*/
};

vows.__defineGetter__('reporter', function () {
    return vows.options.reporter;
});

var stylize = require('vows/console').stylize;
var console = require('vows/console');

vows.inspect = require('vows/console').inspect;
vows.prepare = require('vows/extras').prepare;
vows.tryEnd = require('vows/suite').tryEnd;

//
// Assertion Macros & Extensions
//
require('./assert/error');
require('./assert/macros');

//
// Suite constructor
//
var Suite = require('vows/suite').Suite;

//
// This function gets added to events.EventEmitter.prototype, by default.
// It's essentially a wrapper around `addListener`, which adds all the specification
// goodness.
//
function addVow(vow) {
    var batch = vow.batch;

    batch.total ++;
    batch.vows.push(vow);

    return this.addListener("success", function () {
        var args = Array.prototype.slice.call(arguments);
        // If the callback is expecting two or more arguments,
        // pass the error as the first (null) and the result after.
        if (vow.callback.length >= 2) {
            args.unshift(null);
        }
        runTest(args);
        vows.tryEnd(batch);

    }).addListener("error", function (err) {
        if (vow.callback.length >= 2) {
            runTest([err]);
        } else {
            output('errored', { type: 'promise', error: err });
        }
        vows.tryEnd(batch);
    });

    function runTest(args) {
        var topic, status;

        if (vow.callback instanceof String) {
            return output('pending');
        }

        // Run the test, and try to catch `AssertionError`s and other exceptions;
        // increment counters accordingly.
        try {
            vow.callback.apply(vow.binding || null, args);
            output('honored');
        } catch (e) {
            if (e.name && e.name.match(/AssertionError/)) {
                output('broken', e.toString());
            } else {
                output('errored', e.stack || e.message || e.toString() || e);
            }
        }
    }

    function output(status, exception) {
        batch[status] ++;
        vow.status = status;

        if (vow.context && batch.lastContext !== vow.context) {
            batch.lastContext = vow.context;
            batch.suite.report(['context', vow.context]);
        }
        batch.suite.report(['vow', {
            title: vow.description,
            context: vow.context,
            status: status,
            exception: exception || null
        }]);
    }
};

//
// On exit, check that all promises have been fired.
// If not, report an error message.
//
process.addListener('exit', function () {
    var results = { honored: 0, broken: 0, errored: 0, pending: 0, total: 0 }, failure;

    vows.suites.forEach(function (s) {
        if ((s.results.total > 0) && (s.results.time === null)) {
            s.reporter.report(['error', { error: "Asynchronous Error", suite: s }]);
        }
        s.batches.forEach(function (b) {
            var unFired = [];

            b.vows.forEach(function (vow) {
                if (! vow.status) {
                    if (unFired.indexOf(vow.context) === -1) {
                        unFired.push(vow.context);
                    }
                }
            });

            if (unFired.length > 0) { sys.print('\n') }

            unFired.forEach(function (title) {
                s.reporter.report(['error', {
                    error: "not fired!",
                    context: title,
                    batch: b,
                    suite: s
                }]);
            });

            if (b.status === 'begin') {
                failure = true;
                results.errored ++;
                results.total ++;
            }
            Object.keys(results).forEach(function (k) { results[k] += b[k] });
        });
    });
    if (failure) {
        sys.puts(console.result(results));
    }
});

vows.suites = [];

//
// Create a new test suite
//
vows.describe = function (subject) {
    var suite = new(Suite)(subject);

    this.options.Emitter.prototype.addVow = addVow;
    this.suites.push(suite);

    return suite;
};

vows.version = require('fs').readFileSync(path.join(__dirname, '..', 'package.json'))
                            .toString().match(/"version"\s*:\s*"([\d.]+)"/)[1];
<|endoftext|>


<commit_before>"use strict";

var Q = require("q");
var xhrLocal = require("./xhr");
var version = require("../package.json").version;

module.exports = function (origin, options) {

    var locationOrigin = location.protocol + "//" + location.host;
    options = options || {};

    function destroy() {
        if (iframe) {
            window.removeEventListener("message", responseMessageHandler);
            iframe.parentNode.removeChild(iframe);
        }
    }

    function xhrProxy(request) {
        var deferred = Q.defer();
        if (typeof request === "string") {
            request = { url: request };
        }
        queue[id] = { deferred: deferred };
        iframeWindow.postMessage(JSON.stringify({ id: id, request: request }), origin); // Post to the xhr proxy.
        id = (id + 1) % 65536; // Recycle ids (eventually).
        return deferred.promise;
    }
    xhrProxy.destroy = destroy;

    function reject(err) {
        clearTimeout(iframeTimer);
        window.removeEventListener("message", readyMessageHandler);
        iframe.parentNode.removeChild(iframe);
        xcopReadyDeferred.reject(err);
    }

    function xcopTimeout() {
        reject(new Error("XCOP is unavailable from origin " + origin));
    }

    function getMessageIfTrustedSender(e) {
        if (e.source === iframeWindow && e.origin === origin) {
            return JSON.parse(e.data);
        } else {
            return null;
        }
    }

    function readyMessageHandler(e) {
        var message = getMessageIfTrustedSender(e);
        if (message && message.type === "XCOP-READY") {
            clearTimeout(iframeTimer);
            window.removeEventListener("message", readyMessageHandler);
            window.addEventListener("message", responseMessageHandler);
            xcopReadyDeferred.resolve(xhrProxy);
        } else if (message && message.type === "XCOP-ERROR") {
            reject(new Error(message.message));
        }
    }

    function responseMessageHandler(e) {
        var message = getMessageIfTrustedSender(e);
        if (message && message.type === "XCOP-RESPONSE") {
            var response = message.response;
            var deferred = queue[message.id].deferred;
            delete queue[message.id];
            deferred.resolve(response);
        } else if (message && message.type === "XCOP-RESPONSE-ERROR") {
            var deferred = queue[message.id].deferred;
            delete queue[message.id];
            deferred.reject(new Error("XCOP XMLHttpRequest Error"));
        }
    }

    if (!origin || origin === locationOrigin) {
        return Q.resolve(xhrLocal); // No need to proxy so use native/local XHR.
    } else {
        var id = 0;
        var queue = {};
        var xcopReadyDeferred = Q.defer();

        window.addEventListener("message", readyMessageHandler); // Setup reverse listener.

        var iframe = document.createElement("iframe");
        iframe.style.display = "none";
        document.body.appendChild(iframe);
        var iframeWindow = iframe.contentWindow;
        var iframeTimer = setTimeout(xcopTimeout, (options.proxyTimeout || 15) * 1000);
        iframe.src = origin + (options.xcopDocument || "/xcop.html") +
            "?origin=" + encodeURIComponent(locationOrigin) +
            "&ver=" + encodeURIComponent(version);

        return xcopReadyDeferred.promise;
    }
};
<commit_msg>Add a `useCors` option.<commit_after>"use strict";

var Q = require("q");
var xhrLocal = require("./xhr");
var version = require("../package.json").version;

module.exports = function (origin, options) {

    var locationOrigin = location.protocol + "//" + location.host;
    options = options || {};

    function destroy() {
        if (iframe) {
            window.removeEventListener("message", responseMessageHandler);
            iframe.parentNode.removeChild(iframe);
        }
    }

    function xhrProxy(request) {
        var deferred = Q.defer();
        if (typeof request === "string") {
            request = { url: request };
        }
        queue[id] = { deferred: deferred };
        iframeWindow.postMessage(JSON.stringify({ id: id, request: request }), origin); // Post to the xhr proxy.
        id = (id + 1) % 65536; // Recycle ids (eventually).
        return deferred.promise;
    }
    xhrProxy.destroy = destroy;

    function reject(err) {
        clearTimeout(iframeTimer);
        window.removeEventListener("message", readyMessageHandler);
        iframe.parentNode.removeChild(iframe);
        xcopReadyDeferred.reject(err);
    }

    function xcopTimeout() {
        reject(new Error("XCOP is unavailable from origin " + origin));
    }

    function getMessageIfTrustedSender(e) {
        if (e.source === iframeWindow && e.origin === origin) {
            return JSON.parse(e.data);
        } else {
            return null;
        }
    }

    function readyMessageHandler(e) {
        var message = getMessageIfTrustedSender(e);
        if (message && message.type === "XCOP-READY") {
            clearTimeout(iframeTimer);
            window.removeEventListener("message", readyMessageHandler);
            window.addEventListener("message", responseMessageHandler);
            xcopReadyDeferred.resolve(xhrProxy);
        } else if (message && message.type === "XCOP-ERROR") {
            reject(new Error(message.message));
        }
    }

    function responseMessageHandler(e) {
        var message = getMessageIfTrustedSender(e);
        if (message && message.type === "XCOP-RESPONSE") {
            var response = message.response;
            var deferred = queue[message.id].deferred;
            delete queue[message.id];
            deferred.resolve(response);
        } else if (message && message.type === "XCOP-RESPONSE-ERROR") {
            var deferred = queue[message.id].deferred;
            delete queue[message.id];
            deferred.reject(new Error("XCOP XMLHttpRequest Error"));
        }
    }

    if (!origin || origin === locationOrigin || options.useCors) {
        return Q.resolve(xhrLocal); // No need to proxy so use native/local XHR.
    } else {
        var id = 0;
        var queue = {};
        var xcopReadyDeferred = Q.defer();

        window.addEventListener("message", readyMessageHandler); // Setup reverse listener.

        var iframe = document.createElement("iframe");
        iframe.style.display = "none";
        document.body.appendChild(iframe);
        var iframeWindow = iframe.contentWindow;
        var iframeTimer = setTimeout(xcopTimeout, (options.proxyTimeout || 15) * 1000);
        iframe.src = origin + (options.xcopDocument || "/xcop.html") +
            "?origin=" + encodeURIComponent(locationOrigin) +
            "&ver=" + encodeURIComponent(version);

        return xcopReadyDeferred.promise;
    }
};
<|endoftext|>


<commit_before>/* jshint ignore: start */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';

self.port.on('echo', _ => {
  self.port.emit('echo', '');
});
<commit_msg>remove jshint ignore on panel.js<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';

self.port.on('echo', _ => {
  self.port.emit('echo', '');
});
<|endoftext|>


<commit_before>;(function (window) {
  'use strict';
  /**
  * @function extend
  * Deep extend(recursive),by http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/
  */

  function extend (destination, source) {
    for (var property in source) {
      if (source[property] && source[property].constructor &&
       source[property].constructor === Object) {
        destination[property] = destination[property] || {};
      arguments.callee(destination[property], source[property]);
    } else {
      destination[property] = source[property];
    }
  }
  return destination;
};

  /** @function Deferred
  * js implementation of the jQuery Deferred object
  * https://api.jquery.com/category/deferred-object/
  */

  function Deferred(){
    this._done = [];
    this._fail = [];
  }
  Deferred.prototype = {
    execute: function(list, args){
      var i = list.length;

      // convert arguments to an array
      // so they can be sent to the
      // callbacks via the apply method
      args = Array.prototype.slice.call(args);

      while(i--) list[i].apply(null, args);
    },
    resolve: function(){
      this.execute(this._done, arguments);
    },
    reject: function(){
      this.execute(this._fail, arguments);
    },
    done: function(callback){
      this._done.push(callback);
    },
    fail: function(callback){
      this._fail.push(callback);
    }
  }

  /**
  * @function loadAPI
  * load youtube javascript API
  */

  var loadAPI = function loadAPI(callback){
    var tag = document.createElement('script');
    tag.src = "http://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    iframeIsReady(callback);

  }

  var iframeIsReady = function iframeIsReady(callback){
        // Listen for Gobal YT player callback
        if (typeof YT === 'undefined' && typeof window.loadingPlayer === 'undefined') {
        // Prevents Ready Event from being called twice
        window.loadingPlayer = true;
        window.d = new Deferred();
        window.onYouTubeIframeAPIReady = function() {
          window.onYouTubeIframeAPIReady = null;
          window.d.resolve( "done" );
          callback();
        };
      } else if (typeof YT === 'object')  {
        callback();
      } else {
        window.d.done(function( name ) {
          callback();
        });
      }

    }

    /**
    * @TubeVideo
    * Create TubeVideo
    */
    var TubeVideo= function(node, userOptions){
      player: null;
      this.defaults = {
        ratio: 16 / 9,
        videoId: 'gxCaDMB6y18',
        mute: true,
        repeat: true,
        width: window.innerWidth,
            //to come
            // playButtonClass: 'YTPlayer-play',
            // pauseButtonClass: 'YTPlayer-pause',
            // muteButtonClass: 'YTPlayer-mute',
            // volumeUpClass: 'YTPlayer-volume-up',
            // volumeDownClass: 'YTPlayer-volume-down',
            start: 0,
            playerVars: {
              modestbranding: 1,
              autoplay: 1,
              controls: 0,
              showinfo: 0,
              wmode: 'transparent',
              branding: 0,
              rel: 0,
              autohide: 0
                //origin: window.location.origin
              },
              events: null
            }

            this.node = node || ' ';
            this.userOptions = userOptions || ' ';
            this.options = extend(this.defaults, this.userOptions);
            this._init();
            this.node.setAttribute('style', "position: relative; overflow: hidden;");
          }

          TubeVideo.prototype = {
            _addContainer: function(){
              var self = this;
              var playerWrapper = document.createElement('div');
              playerWrapper.setAttribute("id", self.ID);
              playerWrapper.setAttribute("class", "tubeVideoplayer-container");
              playerWrapper.setAttribute("style", "position: absolute; z-index: -5; width: 100%; height: 100%; top: 0;");
              var playerInner = document.createElement('div');
              playerInner.setAttribute("id", self.holderID);
              self.node.appendChild(playerWrapper).appendChild(playerInner);
            },

        /**
        * @function resize
        * Resize event to change video size
        * params {this} because it will be later called in global scope
        */

        _resize: function(self){

          var container = self.node;
          var width = container.offsetWidth,
          pWidth,
          height = container.offsetHeight,
          pHeight,
          player = document.getElementById(self.holderID);
            // when screen aspect ratio differs from video, video must center and underlay one dimension
            if (width / self.options.ratio < height) {
                pWidth = Math.ceil(height * self.options.ratio); // get new player width
                self._getPlayer().setSize(pWidth,height);
                player.style.marginLeft = ((width - pWidth) / 2) + 'px';
                player.style.top = 0;
                console.log((width - pWidth) / 2);

                 // player width is greater, offset left; reset top
              } else { // new video width < window width (gap to right)
                pHeight = Math.ceil(width / self.options.ratio); // get new player height
                self._getPlayer().setSize(width,pHeight);
                player.style.left = 0;
                player.style.top = 0;

              }
            },

        /**
        * onYouTubeIframeAPIReady – The API will call this function when the page has finished downloading the JavaScript for the player API, which enables you to then use the API on your page. Thus, this function might create the player objects that you want to display when the page loads.
        */
        _onYouTubeIframeAPIReady: function() {
          var self = this;
          self.player = null;
          self.player = new window.YT.Player(self.holderID, self.options);
          //console.log(self.player);

        },

        /**
         * @function onPlayerReady
         * @ params {event} window event from youtube player
         */
         _onPlayerReady: function (e) {
          if (this.options.mute) {
            e.target.mute();
          }
          e.target.playVideo();
        },

        /**
         * @function getPlayer
         * returns youtube player
         */
         _getPlayer: function () {
          return this.player;
        },

        /**
         * @function init
         * Start!
         */
         _init: function(){
          var self = this;
          self.defaults.events = {
            onReady: function(e) {
              self._resize(self);
              self._onPlayerReady(e);
              // Callback for when finished
              if (typeof self.options.callback == 'function') {
                self.options.callback.call(this);
              }
            },
            onStateChange: function(e) {
              if (e.data === 1) {
                console.log("video loaded")
              } else if (e.data === 0 && self.options.repeat) { // video ended and repeat option is set true
                self.player.seekTo(self.options.start);
              }
            }
          }
          self.ID = (new Date()).getTime();
          self.options.height = Math.ceil(self.node.offsetWidth/ self.options.ratio);
          self.holderID = 'tubeVideo-ID-' + self.ID;
          self._addContainer();
          window.addEventListener('resize', function(event){
            self._resize(self);
          });
          loadAPI(self._onYouTubeIframeAPIReady.bind(self));
          return self;

        },

      }

      window.TubeVideo = TubeVideo;

    })(window);<commit_msg>better position calculation<commit_after>;(function (window) {
  'use strict';
  /**
  * @function extend
  * Deep extend(recursive),by http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/
  */

  function extend (destination, source) {
    for (var property in source) {
      if (source[property] && source[property].constructor &&
       source[property].constructor === Object) {
        destination[property] = destination[property] || {};
      arguments.callee(destination[property], source[property]);
    } else {
      destination[property] = source[property];
    }
  }
  return destination;
};

  /** @function Deferred
  * js implementation of the jQuery Deferred object
  * https://api.jquery.com/category/deferred-object/
  */

  function Deferred(){
    this._done = [];
    this._fail = [];
  }
  Deferred.prototype = {
    execute: function(list, args){
      var i = list.length;

      // convert arguments to an array
      // so they can be sent to the
      // callbacks via the apply method
      args = Array.prototype.slice.call(args);

      while(i--) list[i].apply(null, args);
    },
    resolve: function(){
      this.execute(this._done, arguments);
    },
    reject: function(){
      this.execute(this._fail, arguments);
    },
    done: function(callback){
      this._done.push(callback);
    },
    fail: function(callback){
      this._fail.push(callback);
    }
  }

  /**
  * @function loadAPI
  * load youtube javascript API
  */

  var loadAPI = function loadAPI(callback){
    var tag = document.createElement('script');
    tag.src = "http://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    iframeIsReady(callback);

  }

  var iframeIsReady = function iframeIsReady(callback){
        // Listen for Gobal YT player callback
        if (typeof YT === 'undefined' && typeof window.loadingPlayer === 'undefined') {
        // Prevents Ready Event from being called twice
        window.loadingPlayer = true;
        window.d = new Deferred();
        window.onYouTubeIframeAPIReady = function() {
          window.onYouTubeIframeAPIReady = null;
          window.d.resolve( "done" );
          callback();
        };
      } else if (typeof YT === 'object')  {
        callback();
      } else {
        window.d.done(function( name ) {
          callback();
        });
      }

    }

    /**
    * @TubeVideo
    * Create TubeVideo
    */
    var TubeVideo= function(node, userOptions){
      player: null;
      this.defaults = {
        ratio: 16 / 9,
        videoId: 'gxCaDMB6y18',
        mute: true,
        repeat: true,
        width: window.innerWidth,
            //to come
            // playButtonClass: 'YTPlayer-play',
            // pauseButtonClass: 'YTPlayer-pause',
            // muteButtonClass: 'YTPlayer-mute',
            // volumeUpClass: 'YTPlayer-volume-up',
            // volumeDownClass: 'YTPlayer-volume-down',
            start: 0,
            playerVars: {
              modestbranding: 1,
              autoplay: 1,
              controls: 0,
              showinfo: 0,
              wmode: 'transparent',
              branding: 0,
              rel: 0,
              autohide: 0
                //origin: window.location.origin
              },
              events: null
            }

            this.node = node || ' ';
            this.userOptions = userOptions || ' ';
            this.options = extend(this.defaults, this.userOptions);
            this._init();
            this.node.setAttribute('style', "position: relative; overflow: hidden;");
          }

          TubeVideo.prototype = {
            _addContainer: function(){
              var self = this;
              var playerWrapper = document.createElement('div');
              playerWrapper.setAttribute("id", self.ID);
              playerWrapper.setAttribute("class", "tubeVideoplayer-container");
              playerWrapper.setAttribute("style", "position: absolute; z-index: -5; width: 100%; height: 100%; top: 0;");
              var playerInner = document.createElement('div');
              playerInner.setAttribute("id", self.holderID);
              self.node.appendChild(playerWrapper).appendChild(playerInner);
            },

        /**
        * @function resize
        * Resize event to change video size
        * params {this} because it will be later called in global scope
        */

        _resize: function(self){

          var container = self.node;
          var width = container.offsetWidth,
          pWidth,
          height = container.offsetHeight,
          pHeight,
          player = document.getElementById(self.holderID);
            // when screen aspect ratio differs from video, video must center and underlay one dimension
            if (width / self.options.ratio < height) {
                pWidth = Math.ceil(height * self.options.ratio); // get new player width
                self._getPlayer().setSize(pWidth,height);
                player.style.marginLeft = ((width - pWidth) / 2) + 'px';
                player.style.top = 0;
                console.log((width - pWidth) / 2);

                 // player width is greater, offset left; reset top
              } else { // new video width < window width (gap to right)
                pHeight = Math.ceil(width / self.options.ratio); // get new player height
                self._getPlayer().setSize(width,pHeight);
                player.style.left = 0;
                player.style.top = ((height - pHeight) / 2) + 'px';

              }
            },

        /**
        * onYouTubeIframeAPIReady – The API will call this function when the page has finished downloading the JavaScript for the player API, which enables you to then use the API on your page. Thus, this function might create the player objects that you want to display when the page loads.
        */
        _onYouTubeIframeAPIReady: function() {
          var self = this;
          self.player = null;
          self.player = new window.YT.Player(self.holderID, self.options);
          //console.log(self.player);

        },

        /**
         * @function onPlayerReady
         * @ params {event} window event from youtube player
         */
         _onPlayerReady: function (e) {
          if (this.options.mute) {
            e.target.mute();
          }
          e.target.playVideo();
        },

        /**
         * @function getPlayer
         * returns youtube player
         */
         _getPlayer: function () {
          return this.player;
        },

        /**
         * @function init
         * Start!
         */
         _init: function(){
          var self = this;
          self.defaults.events = {
            onReady: function(e) {
              self._resize(self);
              self._onPlayerReady(e);
              // Callback for when finished
              if (typeof self.options.callback == 'function') {
                self.options.callback.call(this);
              }
            },
            onStateChange: function(e) {
              if (e.data === 1) {
                console.log("video loaded")
              } else if (e.data === 0 && self.options.repeat) { // video ended and repeat option is set true
                self.player.seekTo(self.options.start);
              }
            }
          }
          self.ID = (new Date()).getTime();
          self.options.height = Math.ceil(self.node.offsetWidth/ self.options.ratio);
          self.holderID = 'tubeVideo-ID-' + self.ID;
          self._addContainer();
          window.addEventListener('resize', function(event){
            self._resize(self);
          });
          loadAPI(self._onYouTubeIframeAPIReady.bind(self));
          return self;

        },

      }

      window.TubeVideo = TubeVideo;

    })(window);<|endoftext|>


<commit_before>#!/usr/bin/env node

// Copyright Jesus Perez <jesusprubio gmail com>
//           Antonio Carrasco <ancahy2600 gmail com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

'use strict';

const vorpal = require('vorpal')();

const cfg = require('./cfg');
const Bluebox = require('../');
const logger = require('../lib/utils/logger');
const utils = require('../lib/utils/utils');

const debug = utils.debug(utils.pathToName(__filename));

debug('Starting ...');
const bluebox = new Bluebox({});
debug('Getting all Bluebox modules details ...');
const modulesInfo = bluebox.help();
debug('Modules details', modulesInfo);

utils.debug('Defining the commands for the Bluebox modules ...');
utils.each(utils.keys(modulesInfo), moduleName => {
  vorpal
    .command(moduleName)
    .description(modulesInfo[moduleName].description)
    .action(() =>
      new Promise(resolve => {
        const expectedOpts = modulesInfo[moduleName].options;
        const parsedOpts = [];

        // Massaging the data to make Vorpal happy.
        utils.each(utils.keys(expectedOpts), name => {
          let message = `* ${name}: ${expectedOpts[name].description}`;

          if (expectedOpts[name].defaultValue) {
            message += ` (${expectedOpts[name].defaultValue})`;
          }

          parsedOpts.push({
            type: 'input',
            name,
            message,
          });
        });

        // We need to use "activeCommand" because of a Vorpal limitation
        // with ES6: https://github.com/dthree/vorpal/issues/14
        vorpal.activeCommand.prompt(parsedOpts)
        .then(answers => {
          bluebox.run(moduleName, answers)
          .then(res => {
            logger.bold('\nRESULT:\n');
            if (!res) {
              logger.result('No result');
            } else {
              logger.json(res);
            }
            logger.regular('\n');
            resolve();
          })
          .catch(err => {
            // We always resolve (instead reject) because we don't
            // want to stop the full program.
            logger.error(`Running the module : ${err.message}`);
            resolve();
          });
        })
        .catch(err => {
          logger.error(`Getting the options : ${err.message}`);
          resolve();
        });
      })
    );
});

logger.welcome('\n\tWelcome to Bluebox-ng');
logger.info(`\t(v${bluebox.version()})\n`);

debug('Starting the prompt ...');
vorpal
  .history('bluebox-ng')
  .delimiter(cfg.prompt)
  .show();

// Just in case ;).
// TODO: Needed with vorpal?
// process.on('uncaughtException', err => {
//   logger.error('"uncaughtException" found:');
//   logger.error(err);
//   createprompt();
// });
<commit_msg>Some minor comments added.<commit_after>#!/usr/bin/env node

// Copyright Jesus Perez <jesusprubio gmail com>
//           Antonio Carrasco <ancahy2600 gmail com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

'use strict';

const vorpal = require('vorpal')();

const cfg = require('./cfg');
const Bluebox = require('../');
const logger = require('../lib/utils/logger');
const utils = require('../lib/utils/utils');

const debug = utils.debug(utils.pathToName(__filename));

debug('Starting ...');
const bluebox = new Bluebox({});
debug('Getting all Bluebox modules details ...');
const modulesInfo = bluebox.help();
debug('Modules details', modulesInfo);

utils.debug('Defining the commands for the Bluebox modules ...');
utils.each(utils.keys(modulesInfo), moduleName => {
  vorpal
    .command(moduleName)
    .description(modulesInfo[moduleName].description)
    .action(() =>
      new Promise(resolve => {
        const expectedOpts = modulesInfo[moduleName].options;
        const parsedOpts = [];

        // Massaging the data to make Vorpal happy.
        utils.each(utils.keys(expectedOpts), name => {
          let message = `* ${name}: ${expectedOpts[name].description}`;

          if (expectedOpts[name].defaultValue) {
            message += ` (${expectedOpts[name].defaultValue})`;
          }

          parsedOpts.push({
            type: 'input',
            name,
            message,
          });
        });

        // We need to use "activeCommand" because of a Vorpal limitation
        // with ES6: https://github.com/dthree/vorpal/issues/14
        vorpal.activeCommand.prompt(parsedOpts)
        .then(answers => {
          bluebox.run(moduleName, answers)
          .then(res => {
            logger.bold('\nRESULT:\n');
            if (!res) {
              logger.result('No result');
            } else {
              logger.json(res);
            }
            logger.regular('\n');
            resolve();
          })
          .catch(err => {
            // We always resolve (instead reject) because we don't
            // want to stop the full program.
            logger.error(`Running the module : ${err.message}`);
            resolve();
          });
        })
        .catch(err => {
          logger.error(`Getting the options : ${err.message}`);
          resolve();
        });
      })
    );
});

logger.welcome('\n\tWelcome to Bluebox-ng');
logger.info(`\t(v${bluebox.version()})\n`);

debug('Starting the prompt ...');
vorpal
  // Persistent command history.
  .history('bluebox-ng')
  // Prompt content.
  .delimiter(cfg.prompt)
  // Starting the prompt.
  .show();

// Just in case ;).
// TODO: Needed with vorpal?
// process.on('uncaughtException', err => {
//   logger.error('"uncaughtException" found:');
//   logger.error(err);
//   createprompt();
// });
<|endoftext|>