<commit_before>
// Tableling
// ---------
//
// A tableling table is a Marionette layout which fetches data
// from a Backbone collection. It is controlled with an EventAggregator.
Tableling.Table = Backbone.Marionette.Layout.extend({

  className: 'tableling',

  // Default table options can be overriden by subclasses.
  tableling : {
    page : 1,
    pageSize : 15
  },

  initialize : function(options) {
    options = options || {};

    // Table options can also be overriden for each instance at construction.
    this.tableling = _.extend(_.clone(this.tableling), this.filterConfig(options));

    // We use an event aggregator to manage the layout and its components.
    // You can use your own by passing a `vent` option.
    this.vent = options.vent || new Backbone.Marionette.EventAggregator();

    // Components should trigger the `table:update` event to update
    // the table (e.g. change page size, sort) and fetch the new data.
    this.vent.on('table:update', this.update, this);

    this.on('render', this.setup, this);
  },

  // Called once rendering is complete. By default, it updates the table.
  setup : function() {
    this.vent.trigger('table:setup', this.filterConfig(this.tableling, true));
    this.vent.trigger('table:update');
  },

  // Subclasses must return the Backbone.Collection used to fetch data.
  getCollection : function() {
    throw new Error('#getCollection not implemented. It should return the Backbone.Collection instance used to fetch data.');
  },

  // ### Refreshing the table
  update : function(config, options) {

    _.each(this.filterConfig(config || {}), _.bind(this.updateValue, this));

    // Set the `refresh` option to false to update the table configuration
    // without refreshing.
    if (!options || typeof(options.refresh) == 'undefined' || options.refresh) {
      this.refresh();
    }
  },

  updateValue : function(value, key) {
    if (value && value.toString().length) {
      this.tableling[key] = value;
    } else {
      // Blank values are deleted to avoid sending them in ajax requests.
      delete this.tableling[key];
    }
  },

  refresh : function() {

    // `table:refreshing` is triggered every time new data is being fetched.
    // The first argument is the request data.
    var data = this.requestData();
    this.ventTrigger('table:refreshing', data);

    this.getCollection().fetch(_.extend(this.tableling.request || {}, {
      data: data,
      success: _.bind(this.processResponse, this)
    }));
  },

  // ### Request
  // You can provide `requestOptions` to add properties to the
  // fetch request.
  //
  //     var MyTable = Tableling.Table.extend({
  //       requestOptions : {
  //         type : 'POST' // fetch data with POST
  //       }
  //     });
  requestData : function() {
    return _.extend(_.clone(this.requestOptions || {}), this.filterConfig(this.tableling));
  },

  // ### Response
  processResponse : function(collection, response) {

    this.tableling.length = collection.length;

    // Tableling expects the response from a fetch to have a `total` property
    // which is the total number of items (not just in the current page).
    this.tableling.total = response.total;

    // `tableling:refreshed` is triggered after every refresh. The first argument
    // is the current table configuration with the following additional meta data:
    //
    // * `total` - the total number of items
    // * `length` - the number of items in the current page
    this.ventTrigger('table:refreshed', this.filterConfig(this.tableling, true));
  },

  // ### Utilities
  // Whitelists the given configuration to contain only table configuration properties.
  // Pass `true` as the second argument to include meta data (i.e. total & length).
  filterConfig : function(config, all) {
    if (all) {
      return _.pick(config, 'page', 'pageSize', 'quickSearch', 'sort', 'length', 'total');
    } else {
      return _.pick(config, 'page', 'pageSize', 'quickSearch', 'sort');
    }
  },

  // Triggers an event in the event aggregator. If `Tableling.debug` is set, it also
  // logs the event and its arguments.
  ventTrigger : function() {

    var args = Array.prototype.slice.call(arguments);
    this.vent.trigger.apply(this.vent, args);

    if (Tableling.debug) {
      console.log(args.shift() + ' - ' + JSON.stringify(args));
    }
  }
});

// Tableling.Collection
// --------------------
//
// Tableling expects fetch responses to have a `total` property in addition
// to the model data. You can extend this Backbone.Collection subclass which
// expects the following response format:
//
//     {
//       "total": 12,
//       "data": [
//         { /* ... model data ... */ },
//         { /* ... model data ... */ }
//       ]
//     }
Tableling.Collection = Backbone.Collection.extend({

  parse : function(response) {
    return response.data;
  }
});

// Tableling.Modular
// -----------------
//
// Tableling subclass which splits functionality into *modules*
// and handles rendering.
Tableling.Modular = Tableling.Table.extend({

  // The list of module names must be specified by subclasses.
  modules : [],

  // Modules are set up after rendering, before refreshing.
  setup : function() {

    this.moduleViews = {};
    _.each(this.modules, _.bind(this.setupModule, this));

    Tableling.Table.prototype.setup.call(this);
  },

  // ### Modules
  // Each module is identified by a name, for example `pageSize`.
  setupModule : function(name) {

    // The layout must have a region named after the module, e.g. `pageSizeRegion`.
    var region = name + 'Region';

    // It must have a view class, e.g. `pageSizeView`, which will be shown into
    // the region.
    var viewClass = this[name + 'View'];

    // When instantiated, the view class will be passed the event
    // aggregator as the `vent` option. Additional options can be
    // given named after the view class, e.g. `pageSizeViewOptions`.
    var options = _.extend(this[name + 'ViewOptions'] || {}, { vent: this.vent });

    var view = new viewClass(options);

    // Module view instances are stored by name in the `moduleViews` property
    // for future reference.
    this.moduleViews[name] = view;

    this[region].show(view);
    return view;
  },

  // By default, a modular table expects a `table` module which
  // should have a collection (e.g. a Marionette CompositeView or
  // CollectionView). If your subclass does not have that, it
  // should override this method to return the Backbone.Collection
  // used to fetch table data.
  getCollection : function() {
    return this.moduleViews.table.collection;
  }
});

// ### Example
// This is how a `PageSizeView` module might be registered in a subclass:
//
//     var MyTable = Tableling.Modular.extend({
//
//       modules : [ 'pageSize' ],
//
//       pageSizeView : PageSizeView,
//       pageSizeViewOptions : {
//         itemView : PageSizeItem
//       },
//
//       regions : {
//         pageSizeRegion : '.pageSize'
//       }
//     });

// ### Utilities
_.extend(Tableling.Modular, {

  // **createModule** creates an item view that is automatically bound
  // to the layout's event aggregator.
  createModule : function(options) {
    return Backbone.Marionette.ItemView.extend(_.extend({

      initialize : function(options) {
        this.vent = options.vent;

        // The `refresh` method of the view is called once the view is rendered
        // and every time the table is refreshed.
        this.vent.on('table:refreshed', this.refresh, this);
        this.on('render', this.refresh, this);
      },

      // Call `update` to trigger an update of the table.
      update : function() {
        this.vent.trigger('table:update', this.config());
      },

      // Implementations should override this to stay up to date with
      // the table state. Note that the data parameter will be undefined
      // on the first refresh when the view is rendered.
      refresh : function(data) {
      },

      // New table configuration to be sent on updates. For example,
      // a page size view might update the `pageSize` property.
      config : function() {
        return {};
      }
    }, options));
  },

  // **createFieldModule** creates a basic module with a single form field.
  // It comes with sensible defaults and only requires a `template` parameter.
  createFieldModule : function(name, options) {

    var definition = {

      // The name attribute of the form field is expected to be the name of
      // the module, e.g. `pageSize`.
      ui : {
        field : '[name="' + name + '"]'
      },

      events : {},

      // The table property updated is the one with the same name as the module.
      config : function() {
        var config = {};
        config[name] = this.ui.field.val();
        return config;
      }
    };

    // The `change` even triggers an update.
    definition.events['change [name="' + name + '"]'] = 'update';

    return Tableling.Modular.createModule(_.extend(definition, options));
  }

  // This is how a `PageSizeView` module might be implemented:
  //
  //     var html = '<input type="text" name="pageSize" />';
  //
  //     var PageSizeView =
  //       Tableling.Modular.createFieldModule('pageSize', {
  //
  //         template : _.template(html)
  //     });
  //
  // When the value of the input field changes, the event aggregator will
  // receive a `tableling:update` event with the `pageSize` property set
  // to that value.
});

// Implementations
// ---------------
//
// tableling.bootstrap provides views styled
// with [Twitter Bootstrap](http://twitter.github.com/bootstrap/) classes.
<commit_msg>Renamed requestOptions to fetchOptions.<commit_after>
// Tableling
// ---------
//
// A tableling table is a Marionette layout which fetches data
// from a Backbone collection. It is controlled with an EventAggregator.
Tableling.Table = Backbone.Marionette.Layout.extend({

  className: 'tableling',

  // Default table options can be overriden by subclasses.
  tableling : {
    page : 1,
    pageSize : 15
  },

  initialize : function(options) {
    options = options || {};

    // Table options can also be overriden for each instance at construction.
    this.tableling = _.extend(_.clone(this.tableling), this.filterConfig(options));

    // We use an event aggregator to manage the layout and its components.
    // You can use your own by passing a `vent` option.
    this.vent = options.vent || new Backbone.Marionette.EventAggregator();

    // Components should trigger the `table:update` event to update
    // the table (e.g. change page size, sort) and fetch the new data.
    this.vent.on('table:update', this.update, this);

    this.on('render', this.setup, this);
  },

  // Called once rendering is complete. By default, it updates the table.
  setup : function() {
    this.vent.trigger('table:setup', this.filterConfig(this.tableling, true));
    this.vent.trigger('table:update');
  },

  // Subclasses must return the Backbone.Collection used to fetch data.
  getCollection : function() {
    throw new Error('#getCollection not implemented. It should return the Backbone.Collection instance used to fetch data.');
  },

  // ### Refreshing the table
  update : function(config, options) {

    _.each(this.filterConfig(config || {}), _.bind(this.updateValue, this));

    // Set the `refresh` option to false to update the table configuration
    // without refreshing.
    if (!options || typeof(options.refresh) == 'undefined' || options.refresh) {
      this.refresh();
    }
  },

  updateValue : function(value, key) {
    if (value && value.toString().length) {
      this.tableling[key] = value;
    } else {
      // Blank values are deleted to avoid sending them in ajax requests.
      delete this.tableling[key];
    }
  },

  refresh : function() {

    // `table:refreshing` is triggered every time new data is being fetched.
    // The first argument is the request data.
    var data = this.requestData();
    this.ventTrigger('table:refreshing', data);

    this.getCollection().fetch(_.extend(this.tableling.request || {}, {
      data: data,
      success: _.bind(this.processResponse, this)
    }));
  },

  // ### Request
  // You can provide `fetchOptions` to add properties to the
  // fetch request.
  //
  //     var MyTable = Tableling.Table.extend({
  //       fetchOptions : {
  //         type : 'POST' // fetch data with POST
  //       }
  //     });
  requestData : function() {
    return _.extend(_.clone(this.fetchOptions || {}), this.filterConfig(this.tableling));
  },

  // ### Response
  processResponse : function(collection, response) {

    this.tableling.length = collection.length;

    // Tableling expects the response from a fetch to have a `total` property
    // which is the total number of items (not just in the current page).
    this.tableling.total = response.total;

    // `tableling:refreshed` is triggered after every refresh. The first argument
    // is the current table configuration with the following additional meta data:
    //
    // * `total` - the total number of items
    // * `length` - the number of items in the current page
    this.ventTrigger('table:refreshed', this.filterConfig(this.tableling, true));
  },

  // ### Utilities
  // Whitelists the given configuration to contain only table configuration properties.
  // Pass `true` as the second argument to include meta data (i.e. total & length).
  filterConfig : function(config, all) {
    if (all) {
      return _.pick(config, 'page', 'pageSize', 'quickSearch', 'sort', 'length', 'total');
    } else {
      return _.pick(config, 'page', 'pageSize', 'quickSearch', 'sort');
    }
  },

  // Triggers an event in the event aggregator. If `Tableling.debug` is set, it also
  // logs the event and its arguments.
  ventTrigger : function() {

    var args = Array.prototype.slice.call(arguments);
    this.vent.trigger.apply(this.vent, args);

    if (Tableling.debug) {
      console.log(args.shift() + ' - ' + JSON.stringify(args));
    }
  }
});

// Tableling.Collection
// --------------------
//
// Tableling expects fetch responses to have a `total` property in addition
// to the model data. You can extend this Backbone.Collection subclass which
// expects the following response format:
//
//     {
//       "total": 12,
//       "data": [
//         { /* ... model data ... */ },
//         { /* ... model data ... */ }
//       ]
//     }
Tableling.Collection = Backbone.Collection.extend({

  parse : function(response) {
    return response.data;
  }
});

// Tableling.Modular
// -----------------
//
// Tableling subclass which splits functionality into *modules*
// and handles rendering.
Tableling.Modular = Tableling.Table.extend({

  // The list of module names must be specified by subclasses.
  modules : [],

  // Modules are set up after rendering, before refreshing.
  setup : function() {

    this.moduleViews = {};
    _.each(this.modules, _.bind(this.setupModule, this));

    Tableling.Table.prototype.setup.call(this);
  },

  // ### Modules
  // Each module is identified by a name, for example `pageSize`.
  setupModule : function(name) {

    // The layout must have a region named after the module, e.g. `pageSizeRegion`.
    var region = name + 'Region';

    // It must have a view class, e.g. `pageSizeView`, which will be shown into
    // the region.
    var viewClass = this[name + 'View'];

    // When instantiated, the view class will be passed the event
    // aggregator as the `vent` option. Additional options can be
    // given named after the view class, e.g. `pageSizeViewOptions`.
    var options = _.extend(this[name + 'ViewOptions'] || {}, { vent: this.vent });

    var view = new viewClass(options);

    // Module view instances are stored by name in the `moduleViews` property
    // for future reference.
    this.moduleViews[name] = view;

    this[region].show(view);
    return view;
  },

  // By default, a modular table expects a `table` module which
  // should have a collection (e.g. a Marionette CompositeView or
  // CollectionView). If your subclass does not have that, it
  // should override this method to return the Backbone.Collection
  // used to fetch table data.
  getCollection : function() {
    return this.moduleViews.table.collection;
  }
});

// ### Example
// This is how a `PageSizeView` module might be registered in a subclass:
//
//     var MyTable = Tableling.Modular.extend({
//
//       modules : [ 'pageSize' ],
//
//       pageSizeView : PageSizeView,
//       pageSizeViewOptions : {
//         itemView : PageSizeItem
//       },
//
//       regions : {
//         pageSizeRegion : '.pageSize'
//       }
//     });

// ### Utilities
_.extend(Tableling.Modular, {

  // **createModule** creates an item view that is automatically bound
  // to the layout's event aggregator.
  createModule : function(options) {
    return Backbone.Marionette.ItemView.extend(_.extend({

      initialize : function(options) {
        this.vent = options.vent;

        // The `refresh` method of the view is called once the view is rendered
        // and every time the table is refreshed.
        this.vent.on('table:refreshed', this.refresh, this);
        this.on('render', this.refresh, this);
      },

      // Call `update` to trigger an update of the table.
      update : function() {
        this.vent.trigger('table:update', this.config());
      },

      // Implementations should override this to stay up to date with
      // the table state. Note that the data parameter will be undefined
      // on the first refresh when the view is rendered.
      refresh : function(data) {
      },

      // New table configuration to be sent on updates. For example,
      // a page size view might update the `pageSize` property.
      config : function() {
        return {};
      }
    }, options));
  },

  // **createFieldModule** creates a basic module with a single form field.
  // It comes with sensible defaults and only requires a `template` parameter.
  createFieldModule : function(name, options) {

    var definition = {

      // The name attribute of the form field is expected to be the name of
      // the module, e.g. `pageSize`.
      ui : {
        field : '[name="' + name + '"]'
      },

      events : {},

      // The table property updated is the one with the same name as the module.
      config : function() {
        var config = {};
        config[name] = this.ui.field.val();
        return config;
      }
    };

    // The `change` even triggers an update.
    definition.events['change [name="' + name + '"]'] = 'update';

    return Tableling.Modular.createModule(_.extend(definition, options));
  }

  // This is how a `PageSizeView` module might be implemented:
  //
  //     var html = '<input type="text" name="pageSize" />';
  //
  //     var PageSizeView =
  //       Tableling.Modular.createFieldModule('pageSize', {
  //
  //         template : _.template(html)
  //     });
  //
  // When the value of the input field changes, the event aggregator will
  // receive a `tableling:update` event with the `pageSize` property set
  // to that value.
});

// Implementations
// ---------------
//
// tableling.bootstrap provides views styled
// with [Twitter Bootstrap](http://twitter.github.com/bootstrap/) classes.
<|endoftext|>


<commit_before>
var Promise = require("bluebird");
var util = require('util');
var fs = require('fs');
var mkdirp = Promise.promisify(require('mkdirp'));
var _ = require("lodash");

var git = require("./git");
var gerrit_ssh = require("./gerrit-ssh");
var logger = require("./logger");
var prompter = require('./prompter');

var gerrit = {};

gerrit.GerritError = function(msg) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.message = msg;
  if (util.isArray(this.message)) {
    this.message = util.format.apply(null, this.message);
  }
};
util.inherits(gerrit.GerritError, Error);

gerrit.repoConfig = function() {
  requireInRepo();

  var name = git.config("remote.origin.gerrit");
  return gerrit.config(name);
};

gerrit.repoProject = function() {
  requireInRepo();

  var remoteUrl = git.config("remote.origin.url");

  var projectMatch = remoteUrl.match(/^ssh:\/\/[^/]*\/(.*?)(.git)?$/);
  if (projectMatch && projectMatch.length > 1) {
    var projectName = projectMatch[1];
    return projectName;
  }

  return null;
};

gerrit.allConfigs = function() {

  var configs = {};
  var hosts = git.config("gerrit.*.host", {global: true, regex: true});

  for (var host in hosts) {
    var hostMatch = host.match(/^gerrit\.(.*)\.host$/);
    var configName = hostMatch[1];
    configs[configName] = gerrit.config(configName);
  }

  return configs;

};

gerrit.config = function(name) {
  if (name === undefined) {
    return gerrit.repoConfig();
  }

  var config = {};

  var gitconfig = git.config(util.format("gerrit.%s.*", name), {global: true, regex: true});

  if (_.isEmpty(gitconfig)) {
    throw new gerrit.GerritError(["Config for %s does not exist.", name]);
  }

  for (var key in gitconfig) {
    var value = gitconfig[key];
    key = key.match(/\.([^.]*)$/)[1];
    config[key] = value;
  }

  if (config.url) {
    // normalize url by removing trailing slash
    config.url = config.url.replace(/\/$/, '');
  }

  config.name = name;

  return config;

};

gerrit.projects = function(name) {
  return gerrit_ssh("ls-projects", gerrit.config(name)).then(function(result) {
    return result.split("\n");
  });
};

gerrit.clone = function(gerrit_name, project_name, destination_folder) {
  var config = gerrit.config(gerrit_name);

  destination_folder = destination_folder || project_name;

  if (fs.exists(destination_folder)) {
    return Promise.reject(util.format("Destination %s already exists", destination_folder));
  }

  logger.info(["Cloning project %s from %s into folder %s...", project_name, gerrit_name, destination_folder]);

  var source_url = util.format("ssh://%s@%s:%d/%s.git", config.user, config.host, config.port, project_name);

  return git.show(["clone", "--progress", source_url, destination_folder]).then(function(){

    process.chdir(destination_folder);

    git.config("remote.origin.gerrit", gerrit_name);

    return gerrit.installHook();

  });

};

gerrit.installHook = function() {
  logger.info("Setting up commit-msg hook...");

  requireInRepo();

  var hooks_dir = git.dir() + "/hooks";

  return mkdirp(hooks_dir).then(function() {

    return gerrit_ssh.scp("hooks/commit-msg", hooks_dir, gerrit.config());

  });

};

gerrit.ssh = function(command) {
  requireInRepo();

  return gerrit_ssh(command, gerrit.repoConfig());
};

gerrit.status = function() {
  requireInRepo();

  var project = gerrit.repoProject();

  return gerrit_ssh.query(["status:open project:%s", project], gerrit.repoConfig());
};

gerrit.assign = function(reviewersArray) {
  requireInRepo();

  var hash = git.hashFor("HEAD");

  var currentReviewers = git.config('gerrit.reviewers', {all: true}) || [];

  reviewersArray.forEach(function(reviewer) {

    gerrit_ssh(["set-reviewers --add '%s' -- %s", reviewer, hash], gerrit.repoConfig()).then(function() {

      logger.info("Assigned reviewer " + reviewer);

      if (currentReviewers.indexOf(reviewer) === -1) {
        git.config.add('gerrit.reviewers', reviewer);
      }

    });

  });
};

gerrit.push = function(base_branch, is_draft) {
  requireInRepo();

  var config = gerrit.repoConfig();

  var topic = git.branch.name();

  var type = (is_draft ? 'drafts' : 'for');

  base_branch = base_branch || git.config.get(util.format('branch.%s.merge', topic)) || "master";

  var ref = util.format("refs/%s/%s/%s", type, base_branch, topic);

  var draft_config_key = util.format('branch.%s.draft', topic);

  var should_undraft = false;

  if (!is_draft && git.config(draft_config_key) === "yes") {

    return prompter.confirm(
      ['Topic "%s" was previously saved as a *draft*, are you sure you want to un-draft it?', topic],
      false
    ).then(function(confirmed) {
      if (!confirmed) {
        return Promise.reject();
      }
      should_undraft = true;
      return do_push();
    });

  }

  return do_push();

  function do_push() {
    logger.info(["Pushing to %s (%s)", config.name, ref]);
    return git.show(['push', 'origin', 'HEAD:'+ref]).then(function() {
      if (should_undraft) {
        git.config.unset(draft_config_key);
      }
      else if (is_draft) {
        git.config(draft_config_key, "yes");
      }
    });
  }

};

gerrit.checkout = function(target, patch_set, force_branch_overwrite) {
  requireInRepo();

  var config = gerrit.repoConfig();

  var change_id;
  var topic;

  var q;

  if (/^[0-9]+$/.test(target)) {
    // change id

    change_id = target;

  }
  else if (/^https?:\/\/.*\/#\/c\/[0-9]+/.test(target)) {

    var matches = target.match(/#\/c\/([0-9]+)(\/([0-9]+))?/);

    change_id = matches[1];
    patch_set = matches[3];

  }

  if (change_id) {

    q = gerrit_ssh.query(change_id, config).then(function(result) {

      if (result.length === 0) {
        return Promise.reject(util.format('Could not find change id "%s"', change_id));
      }

      topic = result[0].topic;

      if (!topic) {
        logger.warn("No topic found for this patch, you will be checked out in a detached head.");
      }

    });

  }
  else {

    topic = target;

    q = gerrit_ssh.query(["project:%s topic:%s limit:1", gerrit.repoProject(), topic], config).then(function(result) {

      if (result.length === 0) {
        return Promise.reject(util.format('Could not find topic "%s".', topic));
      }

      change_id = result[0].number;

    });

  }

  return q.then(function() {

    var hash = change_id % 100;

    if (hash < 10) {
      hash = "0" + hash;
    }

    var ref = util.format("refs/changes/%s/%s", hash, change_id);

    if (!patch_set) {

      logger.info("Getting latest patchset...");

      var result = git("ls-remote origin '%s/*'", ref);

      patch_set = _.chain(result.split("\n"))
        .invoke(String.prototype.replace, /.*\/(.*)$/, "$1")
        .max()
        .value();

    }

    ref = ref + "/" + patch_set;

    logger.info(["Refspec is %s", ref]);

    git('fetch origin %s', ref);

    var q = Promise.resolve(true);

    git('checkout FETCH_HEAD');

    if (topic === "master") {

      logger.warn("Patch topic is \"master\", therefore staying on detached head.");

    }
    else if (topic && git.branch.exists(topic)) {

      if (!force_branch_overwrite) {

        q = q.then(function() {
          return prompter.confirm(
            ['Branch with name "%s" already exists. Overwrite?', topic],
            false
          );
        });

      }

      q.then(function(confirmed) {
        if (confirmed) {
          git.branch.remove(topic);
        }
        else {
          logger.warn("Staying on detached head.");
        }
      });

    }

    q.then(function() {

      if (topic && !git.branch.exists(topic)) {
        git('checkout -b "%s" FETCH_HEAD', topic);
      }

    });

  });

};

gerrit.review = function(verified_score, code_review_score, message, action) {
  requireInRepo();

  var allowedActions = ['submit', 'abandon'];

  var hash = git.hashFor("HEAD");

  var project = gerrit.repoProject();

  var command = ["review"];

  command.push(util.format("--project '%s'", project));

  if (action && _.contains(allowedActions, action)) {
    command.push("--" + action);
  }

  if (!_.isUndefined(verified_score) && verified_score !== null) {
    command.push(util.format("--verified '%s'", verified_score));
  }

  if (!_.isUndefined(code_review_score) && code_review_score !== null) {
    command.push(util.format("--code-review '%s'", code_review_score));
  }

  if (message) {
    command.push(util.format("--message '%s'", message));
  }

  command.push(hash);

  command = command.join(" ");

  return gerrit_ssh(command, gerrit.repoConfig());

};

function requireInRepo() {
  if (!git.inRepo()) {
    throw new GerritError("Working directory must be in a repository");
  }
};

module.exports = gerrit;
<commit_msg>Factor our changeid to/from topic methods<commit_after>
var Promise = require("bluebird");
var util = require('util');
var fs = require('fs');
var mkdirp = Promise.promisify(require('mkdirp'));
var _ = require("lodash");

var git = require("./git");
var gerrit_ssh = require("./gerrit-ssh");
var logger = require("./logger");
var prompter = require('./prompter');

var gerrit = {};

gerrit.GerritError = function(msg) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.message = msg;
  if (util.isArray(this.message)) {
    this.message = util.format.apply(null, this.message);
  }
};
util.inherits(gerrit.GerritError, Error);

gerrit.repoConfig = function() {
  requireInRepo();

  var name = git.config("remote.origin.gerrit");
  return gerrit.config(name);
};

gerrit.repoProject = function() {
  requireInRepo();

  var remoteUrl = git.config("remote.origin.url");

  var projectMatch = remoteUrl.match(/^ssh:\/\/[^/]*\/(.*?)(.git)?$/);
  if (projectMatch && projectMatch.length > 1) {
    var projectName = projectMatch[1];
    return projectName;
  }

  return null;
};

gerrit.allConfigs = function() {

  var configs = {};
  var hosts = git.config("gerrit.*.host", {global: true, regex: true});

  for (var host in hosts) {
    var hostMatch = host.match(/^gerrit\.(.*)\.host$/);
    var configName = hostMatch[1];
    configs[configName] = gerrit.config(configName);
  }

  return configs;

};

gerrit.config = function(name) {
  if (name === undefined) {
    return gerrit.repoConfig();
  }

  var config = {};

  var gitconfig = git.config(util.format("gerrit.%s.*", name), {global: true, regex: true});

  if (_.isEmpty(gitconfig)) {
    throw new gerrit.GerritError(["Config for %s does not exist.", name]);
  }

  for (var key in gitconfig) {
    var value = gitconfig[key];
    key = key.match(/\.([^.]*)$/)[1];
    config[key] = value;
  }

  if (config.url) {
    // normalize url by removing trailing slash
    config.url = config.url.replace(/\/$/, '');
  }

  config.name = name;

  return config;

};

gerrit.topic_for_changeid = function(change_id, config) {
  return gerrit_ssh.query(change_id, config).then(function(result) {

    if (result.length === 0) {
      return Promise.reject(util.format('Could not find change id "%s"', change_id));
    }

    return result[0].topic;

  });
};

gerrit.changeid_for_topic = function(topic, project, config) {
  return gerrit_ssh.query(["project:%s topic:%s limit:1", project, topic], config).then(function(result) {

    if (result.length === 0) {
      return Promise.reject(util.format('Could not find topic "%s".', topic));
    }

    return result[0].number;

  });
};

gerrit.projects = function(name) {
  return gerrit_ssh("ls-projects", gerrit.config(name)).then(function(result) {
    return result.split("\n");
  });
};

gerrit.clone = function(gerrit_name, project_name, destination_folder) {
  var config = gerrit.config(gerrit_name);

  destination_folder = destination_folder || project_name;

  if (fs.exists(destination_folder)) {
    return Promise.reject(util.format("Destination %s already exists", destination_folder));
  }

  logger.info(["Cloning project %s from %s into folder %s...", project_name, gerrit_name, destination_folder]);

  var source_url = util.format("ssh://%s@%s:%d/%s.git", config.user, config.host, config.port, project_name);

  return git.show(["clone", "--progress", source_url, destination_folder]).then(function(){

    process.chdir(destination_folder);

    git.config("remote.origin.gerrit", gerrit_name);

    return gerrit.installHook();

  });

};

gerrit.installHook = function() {
  logger.info("Setting up commit-msg hook...");

  requireInRepo();

  var hooks_dir = git.dir() + "/hooks";

  return mkdirp(hooks_dir).then(function() {

    return gerrit_ssh.scp("hooks/commit-msg", hooks_dir, gerrit.config());

  });

};

gerrit.ssh = function(command) {
  requireInRepo();

  return gerrit_ssh(command, gerrit.repoConfig());
};

gerrit.status = function() {
  requireInRepo();

  var project = gerrit.repoProject();

  return gerrit_ssh.query(["status:open project:%s", project], gerrit.repoConfig());
};

gerrit.assign = function(reviewersArray) {
  requireInRepo();

  var hash = git.hashFor("HEAD");

  var currentReviewers = git.config('gerrit.reviewers', {all: true}) || [];

  reviewersArray.forEach(function(reviewer) {

    gerrit_ssh(["set-reviewers --add '%s' -- %s", reviewer, hash], gerrit.repoConfig()).then(function() {

      logger.info("Assigned reviewer " + reviewer);

      if (currentReviewers.indexOf(reviewer) === -1) {
        git.config.add('gerrit.reviewers', reviewer);
      }

    });

  });
};

gerrit.push = function(base_branch, is_draft) {
  requireInRepo();

  var config = gerrit.repoConfig();

  var topic = git.branch.name();

  var type = (is_draft ? 'drafts' : 'for');

  base_branch = base_branch || git.config.get(util.format('branch.%s.merge', topic)) || "master";

  var ref = util.format("refs/%s/%s/%s", type, base_branch, topic);

  var draft_config_key = util.format('branch.%s.draft', topic);

  var should_undraft = false;

  if (!is_draft && git.config(draft_config_key) === "yes") {

    return prompter.confirm(
      ['Topic "%s" was previously saved as a *draft*, are you sure you want to un-draft it?', topic],
      false
    ).then(function(confirmed) {
      if (!confirmed) {
        return Promise.reject();
      }
      should_undraft = true;
      return do_push();
    });

  }

  return do_push();

  function do_push() {
    logger.info(["Pushing to %s (%s)", config.name, ref]);
    return git.show(['push', 'origin', 'HEAD:'+ref]).then(function() {
      if (should_undraft) {
        git.config.unset(draft_config_key);
      }
      else if (is_draft) {
        git.config(draft_config_key, "yes");
      }
    });
  }

};

gerrit.checkout = function(target, patch_set, force_branch_overwrite) {
  requireInRepo();

  var config = gerrit.repoConfig();

  var change_id;
  var topic;

  var q;

  if (/^[0-9]+$/.test(target)) {
    // change id

    change_id = target;

  }
  else if (/^https?:\/\/.*\/#\/c\/[0-9]+/.test(target)) {

    var matches = target.match(/#\/c\/([0-9]+)(\/([0-9]+))?/);

    change_id = matches[1];
    patch_set = matches[3];

  }

  if (change_id) {

    q = gerrit.topic_for_changeid(change_id, config).then(function(result) {

      topic = result;

      if (!topic) {
        logger.warn("No topic found for this patch, you will be checked out in a detached head.");
      }

    });

  }
  else {

    topic = target;

    q = gerrit.changeid_for_topic(topic, gerrit.repoProject(), config).then(function(result) {

      change_id = result;

    });

  }

  return q.then(function() {

    var hash = change_id % 100;

    if (hash < 10) {
      hash = "0" + hash;
    }

    var ref = util.format("refs/changes/%s/%s", hash, change_id);

    if (!patch_set) {

      logger.info("Getting latest patchset...");

      var result = git("ls-remote origin '%s/*'", ref);

      patch_set = _.chain(result.split("\n"))
        .invoke(String.prototype.replace, /.*\/(.*)$/, "$1")
        .max()
        .value();

    }

    ref = ref + "/" + patch_set;

    logger.info(["Refspec is %s", ref]);

    git('fetch origin %s', ref);

    var q = Promise.resolve(true);

    git('checkout FETCH_HEAD');

    if (topic === "master") {

      logger.warn("Patch topic is \"master\", therefore staying on detached head.");

    }
    else if (topic && git.branch.exists(topic)) {

      if (!force_branch_overwrite) {

        q = q.then(function() {
          return prompter.confirm(
            ['Branch with name "%s" already exists. Overwrite?', topic],
            false
          );
        });

      }

      q.then(function(confirmed) {
        if (confirmed) {
          git.branch.remove(topic);
        }
        else {
          logger.warn("Staying on detached head.");
        }
      });

    }

    q.then(function() {

      if (topic && !git.branch.exists(topic)) {
        git('checkout -b "%s" FETCH_HEAD', topic);
      }

    });

  });

};

gerrit.review = function(verified_score, code_review_score, message, action) {
  requireInRepo();

  var allowedActions = ['submit', 'abandon'];

  var hash = git.hashFor("HEAD");

  var project = gerrit.repoProject();

  var command = ["review"];

  command.push(util.format("--project '%s'", project));

  if (action && _.contains(allowedActions, action)) {
    command.push("--" + action);
  }

  if (!_.isUndefined(verified_score) && verified_score !== null) {
    command.push(util.format("--verified '%s'", verified_score));
  }

  if (!_.isUndefined(code_review_score) && code_review_score !== null) {
    command.push(util.format("--code-review '%s'", code_review_score));
  }

  if (message) {
    command.push(util.format("--message '%s'", message));
  }

  command.push(hash);

  command = command.join(" ");

  return gerrit_ssh(command, gerrit.repoConfig());

};

function requireInRepo() {
  if (!git.inRepo()) {
    throw new GerritError("Working directory must be in a repository");
  }
};

module.exports = gerrit;
<|endoftext|>


<commit_before>'use strict';

var GitHubApi = require('github');
var githubapi = new GitHubApi({
	// required
	version: "3.0.0",
	// optional
	timeout: 3000
});

exports.getPackageJson = function (user, repo, callback) {
	githubapi.repos.getContent({
		user: user,
		repo: repo,
		path: 'package.json'
	}, function(error, result) {
		if (error) {
			console.error('github:getPackageJson:githubapi.repos.getContent ' + error);
			callback(error.message || error.defaultMessage || error);
			return;
		}

		var jsonString = new Buffer(result.content, result.encoding).toString();
		var json = JSON.parse(jsonString);
		callback(null, json);
	});
};

exports.getUserFromUrl = function(url) {
	var user = url && url.substr('https://github.com/'.length);
	return user && user.substr(0, user.indexOf('/'));
};

exports.getRepoFromUrl = function(url) {
	var repo = url && url.substr(url.lastIndexOf('/')+1);
	return repo && repo.substr(0, repo.lastIndexOf('.'));
};
<commit_msg>Cleaner getPackageJson call in github.js<commit_after>'use strict';

var GitHubApi = require('github');
var githubapi = new GitHubApi({
	// required
	version: "3.0.0",
	// optional
	timeout: 3000
});

exports.getPackageJson = function (user, repo, callback) {
	var options = {
		user: user,
		repo: repo,
		path: 'package.json'
	};

	githubapi.repos.getContent(options, function(error, result) {
		if (error) {
			callback(error.message || error.defaultMessage || error);
			return;
		}

		var jsonString = new Buffer(result.content, result.encoding).toString();
		var json = JSON.parse(jsonString);
		callback(null, json);
	});
};

exports.getUserFromUrl = function(url) {
	var user = url && url.substr('https://github.com/'.length);
	return user && user.substr(0, user.indexOf('/'));
};

exports.getRepoFromUrl = function(url) {
	var repo = url && url.substr(url.lastIndexOf('/')+1);
	return repo && repo.substr(0, repo.lastIndexOf('.'));
};
<|endoftext|>


<commit_before>var path = require('path'),
  config = require('./config'),
  alloy = require('./alloy'),
  component = require('./component'),
  tiapp = require('./tiapp'),
  rimraf = require('rimraf'),
  logger = require('./logger'),
  _ = require('underscore'),
  fs = require('fs-extra'),
  utils = require('./utils');
async = require('async');

function uninstall(o) {

  if (!_uninstallWidget(o)) {
    _uninstallModule(o);
  }
}

function _uninstallWidget(o) {
  var trgPath = path.join(config.widgets_path, o.id);
  var installed = fs.existsSync(trgPath) && (o.version === undefined || config.alloy_config.dependencies[o.id] === o.version);
  var prefix = o.id + (o.version ? '@' + o.version : '');

  if (installed) {
    rimraf.sync(trgPath);
    alloy.dropDependency(o.id, o.version);

    logger.info(prefix + ' uninstalled');

    return true;
  }

  return false;
}

function _uninstallModule(o) {
  var trgPath = o.global ? config.global_modules_path : path.join(config.modules_path);
  var uninstalled = false;

  config.current_modules.map(function(m) {

    if (m.name === o.id && (o.version === undefined || o.version === m.version) && (o.platform === undefined || o.platform === m.platform)) {
      tiapp.dropDependency(o.id, o.version, o.platform);
      rimraf.sync(path.join(trgPath, m.platform, m.name));

      logger.info(m.name + (m.version ? '@' + m.version : '') + ' uninstalled');

      uninstalled = true;
    }

  });

  if (!uninstalled) {
    logger.error(o.id + (o.version ? '@' + o.version : '') + ' not found');
  }
}

function install(o) {

  if (o.id) {
    return _installSingle(o);
  } else {
    return _installAll(o);
  }
}

function _installSingle(o) {
  component.lookup(o.id, function(err, info) {
    if (err) {
      logger.error(err);
      return;
    }

    var target;
    if (o.version && o.version !== '*') {
      target = _.find(info.versions, function(v) {
        return v.version === o.version;
      });
      if (!target) {
        logger.error("Invalid version " + o.version + " for " + o.id);
        return;
      }
    } else { // use latest version with dist
      target = _.find(info.versions, function(v) {
        return typeof v.dist === "string"  && v.dist.trim() != "";
      });
    }

    var trgPath, installed;
    if (info.type === 'widget') {
      trgPath = path.join(config.widgets_path, o.id);
      installed = fs.existsSync(trgPath) &&
        (o.version === undefined || require(path.join(trgPath,'widget.json')).version === o.version);
    } else {
      if (o.global) {
        trgPath = config.global_modules_path;
      } else {
        trgPath = path.join(config.modules_path);
      }
      // installed only true if module is installed for all platforms, project and global
      installed = _.reduce(target.platforms, function(memo, _platform) {
        var platform = _platform.replace("ios", "iphone");
        var available = config.available_modules;

        function check(scope) {
          return available[scope] && available[scope][platform] &&
            available[scope][platform][o.id] && available[scope][platform][o.id][target.version];
        }
        return memo && (check('project') || check('global'));
      }, true);
    }

    if (installed && !o.force) {
      logger.warn(o.id + '@' + target.version + ' already installed');
      if (info.type === "module") {
        tiapp.addDependency(o.id, target.version, target.platforms);
      } else if (info.type === "widget") {
        alloy.addDependency(o.id, target.version, target.platforms);
      }
      return;
    }

    logger.info(o.id + '@' + target.version + ' downloading..');
    component.download(target.dist, function(err, tmpPath) {

      if (err) {
        logger.error(err);
        return;
      }

      logger.info(o.id + '@' + target.version + ' installing..');
      fs.mkdirs(trgPath, function(err) {

        if (err) {
          logger.error(err);
          return;
        }

        var srcPath;
        if (info.type === "widget") {
          var repo = target.path.split("-")[0];
          var commit = _.last(target.dist.split("/")).slice(0, -4);
          srcPath = path.join(tmpPath, repo + "-" + commit);
        } else { //native module
          srcPath = path.join(tmpPath, 'modules');
        }

        fs.copy(srcPath, trgPath, function(err) {

          if (err) {
            logger.error(err);
            return;
          }

          if (info.type === 'widget') {
            alloy.addDependency(o.id, o.version || target.version);
          } else {
            tiapp.addDependency(o.id, target.version, target.platforms);
          }

          rimraf.sync(tmpPath);
          logger.info(o.id + '@' + target.version + ' installed');
          return;
        });
      });
    });
  });
}

function _installAll(o) {
  async.parallel([
    _.bind(_installAllWidgets, undefined, o),
    _.bind(_installAllModules, undefined, o)
  ]);
}

function _installAllWidgets(o) {

  if (config.isAlloy) {
    var data = config.alloy_config;

    if (data.dependencies) {
      var tasks = [];

      _.each(data.dependencies, function(version, widget) {
        tasks.push(function() {
          install(_.extend({
            id: widget,
            version: version
          }, o));
        });
      });

      async.parallel(tasks);
    }
  }
}

function _installAllModules(o) {
  var tasks = config.current_modules.map(function(m) {
    return function() {
      install(_.extend({
        id: m.name,
        version: m.version
      }, o));
    };
  });
  async.parallel(tasks);
}

function info(id) {
  component.lookup(id, function(err, info) {
    if (err) {
      logger.error(err);
      return;
    }
    utils.prettyJSON(info);
    console.log('');
  });
}

exports.install = install;
exports.uninstall = uninstall;
exports.info = info;
<commit_msg>Ellipses are three dots.<commit_after>var path = require('path'),
  config = require('./config'),
  alloy = require('./alloy'),
  component = require('./component'),
  tiapp = require('./tiapp'),
  rimraf = require('rimraf'),
  logger = require('./logger'),
  _ = require('underscore'),
  fs = require('fs-extra'),
  utils = require('./utils');
async = require('async');

function uninstall(o) {

  if (!_uninstallWidget(o)) {
    _uninstallModule(o);
  }
}

function _uninstallWidget(o) {
  var trgPath = path.join(config.widgets_path, o.id);
  var installed = fs.existsSync(trgPath) && (o.version === undefined || config.alloy_config.dependencies[o.id] === o.version);
  var prefix = o.id + (o.version ? '@' + o.version : '');

  if (installed) {
    rimraf.sync(trgPath);
    alloy.dropDependency(o.id, o.version);

    logger.info(prefix + ' uninstalled');

    return true;
  }

  return false;
}

function _uninstallModule(o) {
  var trgPath = o.global ? config.global_modules_path : path.join(config.modules_path);
  var uninstalled = false;

  config.current_modules.map(function(m) {

    if (m.name === o.id && (o.version === undefined || o.version === m.version) && (o.platform === undefined || o.platform === m.platform)) {
      tiapp.dropDependency(o.id, o.version, o.platform);
      rimraf.sync(path.join(trgPath, m.platform, m.name));

      logger.info(m.name + (m.version ? '@' + m.version : '') + ' uninstalled');

      uninstalled = true;
    }

  });

  if (!uninstalled) {
    logger.error(o.id + (o.version ? '@' + o.version : '') + ' not found');
  }
}

function install(o) {

  if (o.id) {
    return _installSingle(o);
  } else {
    return _installAll(o);
  }
}

function _installSingle(o) {
  component.lookup(o.id, function(err, info) {
    if (err) {
      logger.error(err);
      return;
    }

    var target;
    if (o.version && o.version !== '*') {
      target = _.find(info.versions, function(v) {
        return v.version === o.version;
      });
      if (!target) {
        logger.error("Invalid version " + o.version + " for " + o.id);
        return;
      }
    } else { // use latest version with dist
      target = _.find(info.versions, function(v) {
        return typeof v.dist === "string"  && v.dist.trim() != "";
      });
    }

    var trgPath, installed;
    if (info.type === 'widget') {
      trgPath = path.join(config.widgets_path, o.id);
      installed = fs.existsSync(trgPath) &&
        (o.version === undefined || require(path.join(trgPath,'widget.json')).version === o.version);
    } else {
      if (o.global) {
        trgPath = config.global_modules_path;
      } else {
        trgPath = path.join(config.modules_path);
      }
      // installed only true if module is installed for all platforms, project and global
      installed = _.reduce(target.platforms, function(memo, _platform) {
        var platform = _platform.replace("ios", "iphone");
        var available = config.available_modules;

        function check(scope) {
          return available[scope] && available[scope][platform] &&
            available[scope][platform][o.id] && available[scope][platform][o.id][target.version];
        }
        return memo && (check('project') || check('global'));
      }, true);
    }

    if (installed && !o.force) {
      logger.warn(o.id + '@' + target.version + ' already installed');
      if (info.type === "module") {
        tiapp.addDependency(o.id, target.version, target.platforms);
      } else if (info.type === "widget") {
        alloy.addDependency(o.id, target.version, target.platforms);
      }
      return;
    }

    logger.info(o.id + '@' + target.version + ' downloading...');
    component.download(target.dist, function(err, tmpPath) {

      if (err) {
        logger.error(err);
        return;
      }

      logger.info(o.id + '@' + target.version + ' installing...');
      fs.mkdirs(trgPath, function(err) {

        if (err) {
          logger.error(err);
          return;
        }

        var srcPath;
        if (info.type === "widget") {
          var repo = target.path.split("-")[0];
          var commit = _.last(target.dist.split("/")).slice(0, -4);
          srcPath = path.join(tmpPath, repo + "-" + commit);
        } else { //native module
          srcPath = path.join(tmpPath, 'modules');
        }

        fs.copy(srcPath, trgPath, function(err) {

          if (err) {
            logger.error(err);
            return;
          }

          if (info.type === 'widget') {
            alloy.addDependency(o.id, o.version || target.version);
          } else {
            tiapp.addDependency(o.id, target.version, target.platforms);
          }

          rimraf.sync(tmpPath);
          logger.info(o.id + '@' + target.version + ' installed');
          return;
        });
      });
    });
  });
}

function _installAll(o) {
  async.parallel([
    _.bind(_installAllWidgets, undefined, o),
    _.bind(_installAllModules, undefined, o)
  ]);
}

function _installAllWidgets(o) {

  if (config.isAlloy) {
    var data = config.alloy_config;

    if (data.dependencies) {
      var tasks = [];

      _.each(data.dependencies, function(version, widget) {
        tasks.push(function() {
          install(_.extend({
            id: widget,
            version: version
          }, o));
        });
      });

      async.parallel(tasks);
    }
  }
}

function _installAllModules(o) {
  var tasks = config.current_modules.map(function(m) {
    return function() {
      install(_.extend({
        id: m.name,
        version: m.version
      }, o));
    };
  });
  async.parallel(tasks);
}

function info(id) {
  component.lookup(id, function(err, info) {
    if (err) {
      logger.error(err);
      return;
    }
    utils.prettyJSON(info);
    console.log('');
  });
}

exports.install = install;
exports.uninstall = uninstall;
exports.info = info;
<|endoftext|>


<commit_before>var request = require('request');
var cheerio = require('cheerio');
var querystring = require('querystring');
var util = require('util');

var linkSel = 'h3.r a';
var descSel = 'div.s';
var itemSel = 'li.g';
var nextSel = 'td.b a span';

var URL = 'http://www.google.%s/search?hl=%s&q=%s&start=%s&sa=N&num=%s&ie=UTF-8&oe=UTF-8';

var nextTextErrorMsg = 'Translate `google.nextText` option to selected language to detect next results link.';

// start parameter is optional
function google (query, start, callback) {
  var startIndex = 0;
  if (typeof callback === 'undefined') {
    callback = start;
  } else {
    startIndex = start;
  }
  igoogle(query, startIndex, callback);
}

google.resultsPerPage = 10;
google.tld = 'com';
google.lang = 'en';
google.requestOptions = {};
google.nextText = 'Next';

var igoogle = function (query, start, callback) {
  if (google.resultsPerPage > 100) google.resultsPerPage = 100; // Google won't allow greater than 100 anyway
  if (google.lang !== 'en' && google.nextText === 'Next') console.warn(nextTextErrorMsg);

  // timeframe is optional. splice in if set
  if (google.timeSpan) {
    URL = URL.indexOf('tbs=qdr:') >= 0 ? URL.replace(/tbs=qdr:[snhdwmy]\d*/, 'tbs=qdr:' + google.timeSpan) : URL.concat('&tbs=qdr:', google.timeSpan);
  }

  var newUrl = util.format(URL, google.tld, google.lang, querystring.escape(query), start, google.resultsPerPage);
  console.log(newUrl);
  var requestOptions = {
    url: newUrl,
    method: 'GET',
    headers: {
      'User-Agent': 'request'
    }
  };

  for (var k in google.requestOptions) {
    requestOptions[k] = google.requestOptions[k];
  }

  request(requestOptions, function (err, resp, body) {
    if ((err === null) && resp.statusCode === 200) {
      var $ = cheerio.load(body);
      var links = [];

      $(itemSel).each(function (i, elem) {
        var linkElem = $(elem).find(linkSel);
        var descElem = $(elem).find(descSel);
        console.log(linkElem);
        console.log($(linkElem).first().text());
        var item = {
          title: $(linkElem).first().text(),
          link: null,
          description: null,
          href: null
        };
        var qsObj = querystring.parse($(linkElem).attr('href'));

        if (qsObj['/url?q']) {
          item.link = qsObj['/url?q'];
          item.href = item.link;
        }

        $(descElem).find('div').remove();
        item.description = $(descElem).text();

        links.push(item);
      });

      var nextFunc = null;
      if ($(nextSel).last().text() === google.nextText) {
        nextFunc = function () {
          igoogle(query, start + google.resultsPerPage, callback);
        };
      }

      callback(null, nextFunc, links);
    } else {
      callback(new Error('Error on response' + (resp ? ' (' + resp.statusCode + ')' : '') + ':' + err + ' : ' + body), null, null);
    }
  });
};

module.exports = google;
<commit_msg>Playing with headers to get right result<commit_after>var request = require('request');
var cheerio = require('cheerio');
var querystring = require('querystring');
var util = require('util');

var linkSel = 'h3.r a';
var descSel = 'div.s';
var itemSel = 'li.g';
var nextSel = 'td.b a span';

var URL = 'http://www.google.%s/search?hl=%s&q=%s&start=%s&sa=N&num=%s&ie=UTF-8&oe=UTF-8';

var nextTextErrorMsg = 'Translate `google.nextText` option to selected language to detect next results link.';

// start parameter is optional
function google (query, start, callback) {
  var startIndex = 0;
  if (typeof callback === 'undefined') {
    callback = start;
  } else {
    startIndex = start;
  }
  igoogle(query, startIndex, callback);
}

google.resultsPerPage = 10;
google.tld = 'com';
google.lang = 'en';
google.requestOptions = {};
google.nextText = 'Next';

var igoogle = function (query, start, callback) {
  if (google.resultsPerPage > 100) google.resultsPerPage = 100; // Google won't allow greater than 100 anyway
  if (google.lang !== 'en' && google.nextText === 'Next') console.warn(nextTextErrorMsg);

  // timeframe is optional. splice in if set
  if (google.timeSpan) {
    URL = URL.indexOf('tbs=qdr:') >= 0 ? URL.replace(/tbs=qdr:[snhdwmy]\d*/, 'tbs=qdr:' + google.timeSpan) : URL.concat('&tbs=qdr:', google.timeSpan);
  }

  var newUrl = util.format(URL, google.tld, google.lang, querystring.escape(query), start, google.resultsPerPage);
  console.log(newUrl);
  var requestOptions = {
    url: newUrl,
    method: 'GET',
    headers: {
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
      'Accept-Encoding': 'gzip, deflate, sdch',
      'Accept-Language': 'en-US,en;q=0.8',
      'Cache-Control': 'max-age=0',
      'Connection': 'keep-alive',
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36'
    }
  };

  for (var k in google.requestOptions) {
    requestOptions[k] = google.requestOptions[k];
  }

  request(requestOptions, function (err, resp, body) {
    if ((err === null) && resp.statusCode === 200) {
      var $ = cheerio.load(body);
      var links = [];

      $(itemSel).each(function (i, elem) {
        var linkElem = $(elem).find(linkSel);
        var descElem = $(elem).find(descSel);
        console.log(linkElem);
        console.log($(linkElem).first().text());
        var item = {
          title: $(linkElem).first().text(),
          link: null,
          description: null,
          href: null
        };
        var qsObj = querystring.parse($(linkElem).attr('href'));

        if (qsObj['/url?q']) {
          item.link = qsObj['/url?q'];
          item.href = item.link;
        }

        $(descElem).find('div').remove();
        item.description = $(descElem).text();

        links.push(item);
      });

      var nextFunc = null;
      if ($(nextSel).last().text() === google.nextText) {
        nextFunc = function () {
          igoogle(query, start + google.resultsPerPage, callback);
        };
      }

      callback(null, nextFunc, links);
    } else {
      callback(new Error('Error on response' + (resp ? ' (' + resp.statusCode + ')' : '') + ':' + err + ' : ' + body), null, null);
    }
  });
};

module.exports = google;
<|endoftext|>


<commit_before>'use strict';

var chumblRequest=require("./chumbl-request.js");
var queryBuilder = require('./query-builder');

module.exports = {
    getGroups: getGroups,
    getMemberGroups: getMemberGroups,
    getGroup: getGroup,
    addGroup: addGroup,
    updateGroup: updateGroup,
    removeGroup: removeGroup,
    getGroupMembers: getGroupMembers,
    getGroupMember: getGroupMember,
    addFixedGroupMember: addFixedGroupMember,
    setFixedGroupMember: setFixedGroupMember,
    removeFixedGroupMember: removeFixedGroupMember
};

function getGroups(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function getMemberGroups(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/members/{memberId}", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function getGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function addGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups", options);
    options.verb = "post";
    chumblRequest(options, callback);
}

function updateGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}", options);
    options.verb = "put";
    chumblRequest(options, callback);
}

function removeGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}", options);
    options.verb = "delete";
    chumblRequest(options, callback);
}

function getGroupMembers(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function getGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members/{memberId}", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function addFixedGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members", options);
    options.verb = "post";
    chumblRequest(options, callback);
}

function setFixedGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members/{memberId}", options);
    options.verb = "put";
    chumblRequest(options, callback);
}

function removeFixedGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members/{memberId}", options);
    options.verb = "delete";
    chumblRequest(options, callback);
}
<commit_msg>Fix delete<commit_after>'use strict';

var chumblRequest=require("./chumbl-request.js");
var queryBuilder = require('./query-builder');

module.exports = {
    getGroups: getGroups,
    getMemberGroups: getMemberGroups,
    getGroup: getGroup,
    addGroup: addGroup,
    updateGroup: updateGroup,
    removeGroup: removeGroup,
    getGroupMembers: getGroupMembers,
    getGroupMember: getGroupMember,
    addFixedGroupMember: addFixedGroupMember,
    setFixedGroupMember: setFixedGroupMember,
    removeFixedGroupMember: removeFixedGroupMember
};

function getGroups(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function getMemberGroups(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/members/{memberId}", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function getGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function addGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups", options);
    options.verb = "post";
    chumblRequest(options, callback);
}

function updateGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}", options);
    options.verb = "put";
    chumblRequest(options, callback);
}

function removeGroup(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}", options);
    options.verb = "del";
    chumblRequest(options, callback);
}

function getGroupMembers(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function getGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members/{memberId}", options);
    options.verb = "get";
    chumblRequest(options, callback);
}

function addFixedGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members", options);
    options.verb = "post";
    chumblRequest(options, callback);
}

function setFixedGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members/{memberId}", options);
    options.verb = "put";
    chumblRequest(options, callback);
}

function removeFixedGroupMember(options, callback) {
    options.url = queryBuilder("/{chumblr}/groups/{groupId}/members/{memberId}", options);
    options.verb = "del";
    chumblRequest(options, callback);
}
<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');
var logger = require('./logger.js');

var health = {};

health.get = function (req, res, sensu, config) {
  var self = this;
  this.sensu(sensu, config, function (result) {
    if (req.params.component) {
      if (req.params.component === 'uchiwa') {
        self.respond(res, {uchiwa: 'ok'}, 200);
      }
      else if (req.params.component === 'sensu') {
        self.respond(res, {sensu: result.json}, result.code);
      }
      else {
        self.respond(res, {component: 'not found'}, 404);
      }
    }
    else {
      self.respond(res, {uchiwa: 'ok', sensu: result.json}, result.code);
    }
  });
};

health.respond = function (res, data, code) {
  res.setHeader('Last-Modified', (new Date()).toUTCString());
  res.setHeader('Content-Type', 'application/json');
  res.send(code, JSON.stringify(data));
};

health.sensu = function (sensu, config, next) {
  var result = {json: {}, code: 200};
  if (!_.isArray(config.sensu) || config.sensu.length === 0) {
    logger.error('Could not retrieve Sensu APIs details from config.json');
    return next({json: {}, code: 404})
  }
  if (!_.isArray(sensu.dc) || sensu.dc.length === 0) {
    logger.error('Datacenters details and statistics are missing');
    return next({json: {}, code: 404})
  }
  config.sensu.forEach(function(api){
    var datacenter = sensu.dc.filter(function (e){
      return e.name === api.name;
    })[0];

    if (datacenter === undefined) {
      result.json[api.name] = {};
      result.json[api.name].output = 'error: ' + api.name + ' is missing';
    }
    else {
      result.json[datacenter.name] = {};
      if (datacenter.health !== 'ok') {
        result.code = 503;
      }
      result.json[datacenter.name].output = datacenter.health;
    }
  });
  next(result);
};

module.exports = health;
<commit_msg>Linting in health.js<commit_after>'use strict';

var _ = require('underscore');
var logger = require('./logger.js');

var health = {};

health.get = function (req, res, sensu, config) {
  var self = this;
  this.sensu(sensu, config, function (result) {
    if (req.params.component) {
      if (req.params.component === 'uchiwa') {
        self.respond(res, {uchiwa: 'ok'}, 200);
      }
      else if (req.params.component === 'sensu') {
        self.respond(res, {sensu: result.json}, result.code);
      }
      else {
        self.respond(res, {component: 'not found'}, 404);
      }
    }
    else {
      self.respond(res, {uchiwa: 'ok', sensu: result.json}, result.code);
    }
  });
};

health.respond = function (res, data, code) {
  res.setHeader('Last-Modified', (new Date()).toUTCString());
  res.setHeader('Content-Type', 'application/json');
  res.send(code, JSON.stringify(data));
};

health.sensu = function (sensu, config, next) {
  var result = {json: {}, code: 200};
  if (!_.isArray(config.sensu) || config.sensu.length === 0) {
    logger.error('Could not retrieve Sensu APIs details from config.json');
    return next({json: {}, code: 404});
  }
  if (!_.isArray(sensu.dc) || sensu.dc.length === 0) {
    logger.error('Datacenters details and statistics are missing');
    return next({json: {}, code: 404});
  }
  config.sensu.forEach(function(api){
    var datacenter = sensu.dc.filter(function (e){
      return e.name === api.name;
    })[0];

    if (datacenter === undefined) {
      result.json[api.name] = {};
      result.json[api.name].output = 'error: ' + api.name + ' is missing';
    }
    else {
      result.json[datacenter.name] = {};
      if (datacenter.health !== 'ok') {
        result.code = 503;
      }
      result.json[datacenter.name].output = datacenter.health;
    }
  });
  next(result);
};

module.exports = health;
<|endoftext|>


<commit_before>/*
 * openi_data_api
 * openi-ict.eu
 *
 * Copyright (c) 2013 dmccarthy
 * Licensed under the MIT license.
 */

'use strict';

var openiLogger  = require('openi-logger')
var openiUtils   = require('openi-cloudlet-utils')
var zmq          = require('m2nodehandler');
var querystring  = require('querystring')

var allowedTypes = ['boolean', 'int', 'float', 'string', 'date', 'timestamp', 'openitype', 'hexadecimal', 'base64']

var init = function(logger_params){
   this.logger = openiLogger(logger_params);
}

var getType = function (path) {

   var parts   = path.split('/')
   var namePos = 4;

   return parts[namePos]

}

var validateType = function(type){

   if ( !('@reference' in  type) || '' === type['@reference']){
      return {valid:false, message:'There is no _reference property'};
   }
   if ( !('@context' in  type) || !Array.isArray(type['@context']) || 0 === type['@context'].length ){
      return {valid:false, message:'There is no _context property'};
   }

   for ( var i in type['@context']){

      var entry = type['@context'][i];

      if ( !('@property_name' in  entry) || '' === entry['@property_name']){
         return {valid:false, message:'There is no _property_name parameter in entry ' + i};
      }
      if ( !('@property_context' in  entry) ){
         return {valid:false, message:'There is no _property_context parameter in entry ' + i};

      }

      if ( !( '@id' in entry['@property_context']) || '' === entry['@property_context']['@id']){
         return {valid:false, message:'There is no _id parameter in context of the entry ' + i};
      }

      if ( !( '@openi_type' in entry['@property_context']) ){
         return {valid:false, message:'There is no _openi_type parameter in context of the entry ' + i};
      }

      if (-1 === allowedTypes.indexOf(entry['@property_context']['@openi_type'])){
         return {valid:false, message: entry['@property_context']['@openi_type'] + ' is not a valid type.'};
      }

   }

   return {valid:true};
}

var genPostMessage = function(msg, senderToDao, senderToClient, terminal_handler){

   if (undefined === msg.json || null === msg.json){

      var resp = zmq.Response(zmq.status.BAD_REQUEST_400, zmq.header_json, {'error' : 'Empty body.' })

      senderToClient.send(msg.uuid, msg.connId, resp);

      return
   }

   var typeId = 't_' + openiUtils.hash(msg.json)

   var typeRestUrl = "https://" + msg.headers.host + "/api/v1/types/" + typeId;

   msg.json['@id']            = typeId;
   msg.json['@location']      = typeRestUrl;
   msg.json['_date_created '] = new Date().toJSON();

   var validCheck = validateType(msg.json);

   if (!validCheck.valid){

      var resp = zmq.Response(zmq.status.BAD_REQUEST_400, zmq.header_json, {'error' : 'Type object isn\'t properly structured : ' + validCheck.message})

      senderToClient.send(msg.uuid, msg.connId, resp);

      return;
   }

   senderToDao.send({
      'dao_actions'      : [
         {
            'action'       : 'POST',
            'database'    : typeId,
            'object_name' : 'meta',
            'object_data' : msg.json,
            'id'          : typeId
         }
      ],
      'mongrel_sink' : terminal_handler,
      'clients'      : [
         {'uuid' : msg.uuid, 'connId' : msg.connId }
      ]
   });
}

var genGetMessage = function(msg, senderToDao, senderToClient, terminal_handler){

   var query = querystring.parse(msg.headers.QUERY);

   if ( msg.path === '/api/v1/types' ){

      var viewName  = 'types_list';

      if ('true' === query.id_only){
         viewName  = 'types_id_list';
      }

      senderToDao.send({
         'dao_actions'      : [
            {
               'action'       : 'VIEW',
               'design_doc'   : 'type_views',
               'view_name'    : viewName,
               'count'        : Number(query.limit),
               'skip'         : Number(query.skip),
               'filter_show'  : query['only_show_properties'],
               'content-type' : query['content-type'],
               'resp_type'    : 'type'
            }
         ],
         'mongrel_sink' : terminal_handler,
         'clients'      : [
            {'uuid' : msg.uuid, 'connId' : msg.connId }
         ]
      })
   }
   else if ( msg.path === '/api/v1/types/stats' ){

      senderToDao.send({
         'dao_actions'      : [
            {
               'action'       : 'VIEW',
               'design_doc'   : 'type_views',
               'view_name'    : 'types_usage',
               'group'        : true,
               'resp_type'    : 'type_stats'
            }
         ],
         'mongrel_sink' : terminal_handler,
         'clients'      : [
            {'uuid' : msg.uuid, 'connId' : msg.connId }
         ]
      })
   }
   else{
      var type =  getType(msg.path).replace('/api/v1/types/','')

      var typeRestUrl = "https://" + msg.headers.host + "/api/v1/types/" + type;

      senderToDao.send({
         'dao_actions'      : [
            {
               'action' : 'GET',
               'database': type,
               'id' : type,
               'content-type' : query['content-type'],
               'resp_type'    : 'type'
            }
         ],
         'mongrel_sink' : terminal_handler,
         'clients'      : [
            {'uuid' : msg.uuid, 'connId' : msg.connId }
         ]
      });
   }
}

var genPatchMessage = function(msg, senderToDao, senderToClient, terminal_handler){

   if (undefined === msg.json || null === msg.json){

      var resp = zmq.Response(zmq.status.BAD_REQUEST_400, zmq.header_json, {'error' : 'Type array is empty' })

      senderToClient.send(msg.uuid, msg.connId, resp);

      return
   }

   var actions = []

   for ( var i =0; i < msg.json.length; i++){
      var entry       = msg.json[i]
      var typeId      = 't_' + openiUtils.hash(entry)
      var typeRestUrl = "https://" + msg.headers.host + "/api/v1/types/" + typeId;

      if (!validateType(entry)){

         var resp = zmq.Response(zmq.status.BAD_REQUEST_400, zmq.header_json, {'error' : 'Type object isn\'t properly structured' })

         senderToClient.send(msg.uuid, msg.connId, resp);

         return;
      }

      entry['@id']            = typeId;
      entry['@location']      = typeRestUrl;
      entry['_date_created'] = new Date().toJSON();

      actions.push({ 'action' : 'POST',
         'database'    : typeId,
         'object_name' : 'meta',
         'object_data' : entry,
         'id'          : typeId,
         'resp_type'   : 'type'
      });
   }

   senderToDao.send({
      'dao_actions'  : actions,
      'mongrel_sink' : terminal_handler,
      'clients'      : [
         {'uuid' : msg.uuid, 'connId' : msg.connId }
      ]
   });
}

var processMongrel2Message = function (msg, senderToDao, senderToClient, terminal_handler) {

   this.logger.logMongrel2Message(msg);

   for(var key in msg.json) if(msg.json[key] === null) delete msg.json[key];

   switch(msg.headers['METHOD']){
   case 'POST':
      genPostMessage(msg, senderToDao, senderToClient, terminal_handler)
      break;
   case 'GET':
      genGetMessage(msg, senderToDao, senderToClient, terminal_handler)
      break;
   case 'PATCH':
      genPatchMessage(msg, senderToDao, senderToClient, terminal_handler)
      break;
   default:
      break;
   }

}

module.exports.init                   = init
module.exports.getObject              = getType
module.exports.processMongrel2Message = processMongrel2Message
<commit_msg>Refactored to handle m2nodehandler<commit_after>/*
 * openi_data_api
 * openi-ict.eu
 *
 * Copyright (c) 2013 dmccarthy
 * Licensed under the MIT license.
 */

'use strict';

var openiLogger  = require('openi-logger')
var openiUtils   = require('openi-cloudlet-utils')
var zmq          = require('m2nodehandler');
var querystring  = require('querystring')

var allowedTypes = ['boolean', 'int', 'float', 'string', 'date', 'timestamp', 'openitype', 'hexadecimal', 'base64']

var init = function(logger_params){
   this.logger = openiLogger(logger_params);
}

var getType = function (path) {

   var parts   = path.split('/')
   var namePos = 4;

   return parts[namePos]

}

var validateType = function(type){

   if ( !('@reference' in  type) || '' === type['@reference']){
      return {valid:false, message:'There is no _reference property'};
   }
   if ( !('@context' in  type) || !Array.isArray(type['@context']) || 0 === type['@context'].length ){
      return {valid:false, message:'There is no _context property'};
   }

   for ( var i in type['@context']){

      var entry = type['@context'][i];

      if ( !('@property_name' in  entry) || '' === entry['@property_name']){
         return {valid:false, message:'There is no _property_name parameter in entry ' + i};
      }
      if ( !('@property_context' in  entry) ){
         return {valid:false, message:'There is no _property_context parameter in entry ' + i};

      }

      if ( !( '@id' in entry['@property_context']) || '' === entry['@property_context']['@id']){
         return {valid:false, message:'There is no _id parameter in context of the entry ' + i};
      }

      if ( !( '@openi_type' in entry['@property_context']) ){
         return {valid:false, message:'There is no _openi_type parameter in context of the entry ' + i};
      }

      if (-1 === allowedTypes.indexOf(entry['@property_context']['@openi_type'])){
         return {valid:false, message: entry['@property_context']['@openi_type'] + ' is not a valid type.'};
      }

   }

   return {valid:true};
}

var genPostMessage = function(msg, senderToDao, senderToClient, terminal_handler){

   if (undefined === msg.json || null === msg.json){

      senderToClient.send(msg.uuid, msg.connId, zmq.status.BAD_REQUEST_400, zmq.standard_headers.json, {'error' : 'Empty body.' });

      return
   }

   var typeId = 't_' + openiUtils.hash(msg.json)

   var typeRestUrl = "https://" + msg.headers.host + "/api/v1/types/" + typeId;

   msg.json['@id']            = typeId;
   msg.json['@location']      = typeRestUrl;
   msg.json['_date_created '] = new Date().toJSON();

   var validCheck = validateType(msg.json);

   if (!validCheck.valid){

      senderToClient.send(msg.uuid, msg.connId, zmq.status.BAD_REQUEST_400, zmq.standard_headers.json, {'error' : 'Type object isn\'t properly structured : ' + validCheck.message});

      return;
   }

   senderToDao.send({
      'dao_actions'      : [
         {
            'action'       : 'POST',
            'database'    : typeId,
            'object_name' : 'meta',
            'object_data' : msg.json,
            'id'          : typeId
         }
      ],
      'mongrel_sink' : terminal_handler,
      'clients'      : [
         {'uuid' : msg.uuid, 'connId' : msg.connId }
      ]
   });
}

var genGetMessage = function(msg, senderToDao, senderToClient, terminal_handler){

   var query = querystring.parse(msg.headers.QUERY);

   if ( msg.path === '/api/v1/types' ){

      var viewName  = 'types_list';

      if ('true' === query.id_only){
         viewName  = 'types_id_list';
      }

      senderToDao.send({
         'dao_actions'      : [
            {
               'action'       : 'VIEW',
               'design_doc'   : 'type_views',
               'view_name'    : viewName,
               'count'        : Number(query.limit),
               'skip'         : Number(query.skip),
               'filter_show'  : query['only_show_properties'],
               'content-type' : query['content-type'],
               'resp_type'    : 'type'
            }
         ],
         'mongrel_sink' : terminal_handler,
         'clients'      : [
            {'uuid' : msg.uuid, 'connId' : msg.connId }
         ]
      })
   }
   else if ( msg.path === '/api/v1/types/stats' ){

      senderToDao.send({
         'dao_actions'      : [
            {
               'action'       : 'VIEW',
               'design_doc'   : 'type_views',
               'view_name'    : 'types_usage',
               'group'        : true,
               'resp_type'    : 'type_stats'
            }
         ],
         'mongrel_sink' : terminal_handler,
         'clients'      : [
            {'uuid' : msg.uuid, 'connId' : msg.connId }
         ]
      })
   }
   else{
      var type =  getType(msg.path).replace('/api/v1/types/','')

      var typeRestUrl = "https://" + msg.headers.host + "/api/v1/types/" + type;

      senderToDao.send({
         'dao_actions'      : [
            {
               'action' : 'GET',
               'database': type,
               'id' : type,
               'content-type' : query['content-type'],
               'resp_type'    : 'type'
            }
         ],
         'mongrel_sink' : terminal_handler,
         'clients'      : [
            {'uuid' : msg.uuid, 'connId' : msg.connId }
         ]
      });
   }
}

var genPatchMessage = function(msg, senderToDao, senderToClient, terminal_handler){

   if (undefined === msg.json || null === msg.json){

      senderToClient.send(msg.uuid, msg.connId, zmq.status.BAD_REQUEST_400, zmq.standard_headers.json, {'error' : 'Type array is empty' });

      return
   }

   var actions = []

   for ( var i =0; i < msg.json.length; i++){
      var entry       = msg.json[i]
      var typeId      = 't_' + openiUtils.hash(entry)
      var typeRestUrl = "https://" + msg.headers.host + "/api/v1/types/" + typeId;

      if (!validateType(entry)){

         senderToClient.send(msg.uuid, msg.connId, zmq.status.BAD_REQUEST_400, zmq.standard_headers.json, {'error' : 'Type object isn\'t properly structured' });

         return;
      }

      entry['@id']            = typeId;
      entry['@location']      = typeRestUrl;
      entry['_date_created'] = new Date().toJSON();

      actions.push({ 'action' : 'POST',
         'database'    : typeId,
         'object_name' : 'meta',
         'object_data' : entry,
         'id'          : typeId,
         'resp_type'   : 'type'
      });
   }

   senderToDao.send({
      'dao_actions'  : actions,
      'mongrel_sink' : terminal_handler,
      'clients'      : [
         {'uuid' : msg.uuid, 'connId' : msg.connId }
      ]
   });
}

var processMongrel2Message = function (msg, senderToDao, senderToClient, terminal_handler) {

   this.logger.logMongrel2Message(msg);

   for(var key in msg.json) if(msg.json[key] === null) delete msg.json[key];

   switch(msg.headers['METHOD']){
   case 'POST':
      genPostMessage(msg, senderToDao, senderToClient, terminal_handler)
      break;
   case 'GET':
      genGetMessage(msg, senderToDao, senderToClient, terminal_handler)
      break;
   case 'PATCH':
      genPatchMessage(msg, senderToDao, senderToClient, terminal_handler)
      break;
   default:
      break;
   }

}

module.exports.init                   = init
module.exports.getObject              = getType
module.exports.processMongrel2Message = processMongrel2Message
<|endoftext|>


<commit_before>'use strict';
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;

/**
 * Renders a component
 *
 * @method renderComponent
 * @param {ReactComponent} Component class
 * @param {Object} props used to initialize the component
 * @return {ReactElement} rendered react element
 **/
function renderComponent(Component, props) {
    var element = React.createElement(Component, props);
    return TestUtils.renderIntoDocument(element);
}

/**
 * Simulates an event triggered on given element
 *
 * @method simulateEvent
 * @param {ReactElement or DOMNode} element that will trigger the event
 * @param {String} event that will be triggered
 **/
function simulateEvent(element, event) {
    TestUtils.Simulate[event](
       element.getDOMNode ? element.getDOMNode() : element
    );
}

/**
 * Simulates an native event on given element
 *
 * @method simulateNativeEvent
 * @param {ReactElement or DOMNode} element that will trigger the event
 * @param {String} event that will be triggered
 **/
function simulateNativeEvent(element, event) {
    TestUtils.SimulateNative[event](
       element.getDOMNode ? element.getDOMNode() : element
    );
}

/**
 * Element by query selector
 *
 * @method elementQuerySelector
 * @param {ReactElement} element node where you will search
 * @param {string} query css selector
 * @return {DOMNode} the first DOM node that matches the query
 **/
function elementQuerySelector(element, query) {
    return element.getDOMNode().querySelector(query);
}

/**
 * Elements by query selector
 *
 * @method elementQuerySelectorAll
 * @param {ReactElement} element node where you will search
 * @param {String} query css selector
 * @return {DOMNode} all DOM nodes that matches the query
 **/
function elementQuerySelectorAll(element, query) {
    return element.getDOMNode().querySelectorAll(query);
}

/**
 * Creates a ComponentStub
 *
 * @method stubComponent
 * @param {ReactElement|String} tag element to create
 * @param {Object} assertProps raises an error if component props don't match
 * @return {ReactComponent} ComponentStub
 **/
function stubComponent(tag, children, showDataProps) {
    return React.createClass({
        displayName: tag.displayName || tag,

        componentWillMount: function () {
            showDataProps && this.addDataProps();
        },

        addDataProps: function () {
            Object.keys(this.props).forEach(function (key) {
                this.props['data-' + key] = this.props[key]
            }, this);
        },

        render: function () {
            return React.createElement(tag, this.props, children);
        }
    });
}

/**
 * Wraps component in a context creating component
 *
 * @method withContext
 * @param {ReactComponent} Component class
 * @param {Object} props used to initialize the component
 * @return {ReactElement} react class with context setup
 **/
function withContext(context, Component, props) {
    var Elem = React.createFactory(Component);
    var childContextTypes = {};

    for (var key in context) {
        childContextTypes[key] = React.PropTypes.any;
    }

    return React.createClass({
        childContextTypes: childContextTypes,
        getChildContext: function () {
            return context;
        },
        render: function () {
            return Elem(props);
        }
    });
}

/**
 * @module helper
 **/
module.exports = {
    simulateEvent: simulateEvent,
    simulateNativeEvent: simulateNativeEvent,
    renderComponent: renderComponent,
    elementQuerySelector: elementQuerySelector,
    elementQuerySelectorAll: elementQuerySelectorAll,
    stubComponent: stubComponent,
    withContext: withContext
};
<commit_msg>Pass props down<commit_after>'use strict';
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;

/**
 * Renders a component
 *
 * @method renderComponent
 * @param {ReactComponent} Component class
 * @param {Object} props used to initialize the component
 * @return {ReactElement} rendered react element
 **/
function renderComponent(Component, props) {
    var element = React.createElement(Component, props);
    return TestUtils.renderIntoDocument(element);
}

/**
 * Simulates an event triggered on given element
 *
 * @method simulateEvent
 * @param {ReactElement or DOMNode} element that will trigger the event
 * @param {String} event that will be triggered
 **/
function simulateEvent(element, event) {
    TestUtils.Simulate[event](
       element.getDOMNode ? element.getDOMNode() : element
    );
}

/**
 * Simulates an native event on given element
 *
 * @method simulateNativeEvent
 * @param {ReactElement or DOMNode} element that will trigger the event
 * @param {String} event that will be triggered
 **/
function simulateNativeEvent(element, event) {
    TestUtils.SimulateNative[event](
       element.getDOMNode ? element.getDOMNode() : element
    );
}

/**
 * Element by query selector
 *
 * @method elementQuerySelector
 * @param {ReactElement} element node where you will search
 * @param {string} query css selector
 * @return {DOMNode} the first DOM node that matches the query
 **/
function elementQuerySelector(element, query) {
    return element.getDOMNode().querySelector(query);
}

/**
 * Elements by query selector
 *
 * @method elementQuerySelectorAll
 * @param {ReactElement} element node where you will search
 * @param {String} query css selector
 * @return {DOMNode} all DOM nodes that matches the query
 **/
function elementQuerySelectorAll(element, query) {
    return element.getDOMNode().querySelectorAll(query);
}

/**
 * Creates a ComponentStub
 *
 * @method stubComponent
 * @param {ReactElement|String} tag element to create
 * @param {Object} assertProps raises an error if component props don't match
 * @return {ReactComponent} ComponentStub
 **/
function stubComponent(tag, children, showDataProps) {
    return React.createClass({
        displayName: tag.displayName || tag,

        componentWillMount: function () {
            showDataProps && this.addDataProps();
        },

        addDataProps: function () {
            Object.keys(this.props).forEach(function (key) {
                this.props['data-' + key] = this.props[key]
            }, this);
        },

        render: function () {
            return React.createElement(tag, this.props, children);
        }
    });
}

/**
 * Wraps component in a context creating component
 *
 * @method withContext
 * @param {ReactComponent} Component class
 * @return {ReactElement} react class with context setup
 **/
function withContext(context, Component) {
    var Elem = React.createFactory(Component);
    var childContextTypes = {};

    for (var key in context) {
        childContextTypes[key] = React.PropTypes.any;
    }

    return React.createClass({
        childContextTypes: childContextTypes,
        getChildContext: function () {
            return context;
        },
        render: function () {
            return Elem(this.props);
        }
    });
}

/**
 * @module helper
 **/
module.exports = {
    simulateEvent: simulateEvent,
    simulateNativeEvent: simulateNativeEvent,
    renderComponent: renderComponent,
    elementQuerySelector: elementQuerySelector,
    elementQuerySelectorAll: elementQuerySelectorAll,
    stubComponent: stubComponent,
    withContext: withContext
};
<|endoftext|>