<commit_before>var treeSitter = require("../../index"),
    fs = require("fs-extra"),
    path = require("path"),
    mkdirp = require("mkdirp"),
    templates = require("./templates"),
    cwd = process.cwd();

module.exports = function compile(options) {
  require("coffee-script/register");
  var grammarConfig = require(path.join(cwd, "grammar.coffee"))(treeSitter.rules);
      grammar = treeSitter.grammar(grammarConfig);

  process.stdout.write("Generating parser... ");
  var startTime = process.hrtime();

  var code;
  try {
    code = treeSitter.compile(grammar)
  } catch (e) {
    if (e.isGrammarError) {
      console.warn("Error: " + e.message);
      return 1;
    } else {
      throw e;
    }
  }

  mkdirp.sync(path.join(cwd, "include", "tree_sitter"));
  fs.copySync(
    path.join(__dirname, "..", "..", "vendor", "tree-sitter", "include", "tree_sitter"),
    path.join(cwd, "include", "tree_sitter")
  )
  mkdirp.sync(path.join(cwd, "src"));
  fs.writeFileSync(path.join(cwd, "src", "parser.c"), code);
  fs.writeFileSync(path.join(cwd, "src", "binding.cc"), templates.bindingCC(grammar.name));
  fs.writeFileSync(path.join(cwd, "binding.gyp"), templates.bindingGyp(grammar.name));
  fs.writeFileSync(path.join(cwd, "index.js"), templates.indexJS(grammar.name));

  var endTime = process.hrtime(startTime);
  console.log("Done (%ds).", (endTime[0] + (endTime[1] / Math.pow(10, 9))).toFixed(2));
  return 0;
}
<commit_msg>Make grammar DSL methods global when loading grammars<commit_after>var treeSitter = require("../../index"),
    fs = require("fs-extra"),
    path = require("path"),
    mkdirp = require("mkdirp"),
    templates = require("./templates"),
    cwd = process.cwd();

module.exports = function compile(options) {
  require("coffee-script/register");

  global.grammar = treeSitter.grammar;
  Object.keys(treeSitter.rules).forEach(function(key) {
    global[key] = treeSitter.rules[key];
  });

  var grammar = require(path.join(cwd, "grammar.coffee"));

  process.stdout.write("Generating parser... ");
  var startTime = process.hrtime();

  var code;
  try {
    code = treeSitter.compile(grammar)
  } catch (e) {
    if (e.isGrammarError) {
      console.warn("Error: " + e.message);
      return 1;
    } else {
      throw e;
    }
  }

  mkdirp.sync(path.join(cwd, "include", "tree_sitter"));
  fs.copySync(
    path.join(__dirname, "..", "..", "vendor", "tree-sitter", "include", "tree_sitter"),
    path.join(cwd, "include", "tree_sitter")
  )
  mkdirp.sync(path.join(cwd, "src"));
  fs.writeFileSync(path.join(cwd, "src", "parser.c"), code);
  fs.writeFileSync(path.join(cwd, "src", "binding.cc"), templates.bindingCC(grammar.name));
  fs.writeFileSync(path.join(cwd, "binding.gyp"), templates.bindingGyp(grammar.name));
  fs.writeFileSync(path.join(cwd, "index.js"), templates.indexJS(grammar.name));

  var endTime = process.hrtime(startTime);
  console.log("Done (%ds).", (endTime[0] + (endTime[1] / Math.pow(10, 9))).toFixed(2));
  return 0;
}
<|endoftext|>


<commit_before>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto(CallBack) {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Value,
            Edit        = this,
            Diff,
            Ace,
            Session,
            Modelist,
            Msg,
            Dialog      = DOM.Dialog,
            Key         = CloudCmd.Key,
            Images      = DOM.Images,
            Element;

       function init() {
            Loading   = true;
            Util.loadOnLoad([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(pValue) {
            var lMode, htmlMode, cssMode,
                lName       = Info.name,
                isDir       = Info.isDir,
                lExt        = Info.ext;

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.anyload({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position: absolute;',
                        not_append : true
                    });

                  initAce();
                }

                if (isDir)
                    lMode = Modelist.modesByName.json.mode;
                else
                    lMode = Modelist.getModeForPath(lName).mode;

                htmlMode  = Modelist.modesByName.html.mode;
                cssMode   = Modelist.modesByName.css.mode;

                Session.setMode(lMode);

                if (lMode === htmlMode || lMode === cssMode)
                    DOM.jsload(DIR + 'emmet.js', function() {
                        var Emmet = ace.require("ace/ext/emmet");

                        Emmet.setCore(window.emmet);
                        Ace.setOption("enableEmmet", true);
                    });

                if (Util.isString(pValue)) {
                    Ace.setValue(pValue);
                    CloudCmd.View.show(Element, focus);
                    Key.unsetBind();
                } else
                    Info.getData(function(data) {
                        Value = data;
                        Ace.setValue(data);
                        CloudCmd.View.show(Element, focus);
                    });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function focus() {
            Ace.focus();
            Ace.clearSelection();
            Ace.moveCursorTo(0, 0);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.setTheme('ace/theme/tomorrow_night_blue');

            Ace.setShowPrintMargin(false);
            Ace.setShowInvisibles(true);
            Session.setUseSoftTabs(true);

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            Ace.setOptions({
                enableBasicAutocompletion   : true,
                enableSnippets              : true
            });
        }

        function save () {
            var lPath       = Info.path,
                lValue      = Ace.getValue();

            CloudCmd.getConfig(function(config) {
                var isDiff = config.diff;

                Util.ifExec(!isDiff, function(patch) {
                    var query,
                        isAllowed   = DOM.Storage.isAllowed();

                    Value           = lValue;

                    Util.ifExec(!isAllowed, function() {
                            DOM.RESTful.save(lPath,  lValue, onSave, query);
                        }, function(callback) {
                            DOM.checkStorageHash(lPath, function(error, equal) {
                                var isString    = Util.isString(patch),
                                    lessLength  = patch.length < lValue.length;

                                if (!error) {
                                    if (equal && isString && patch.length && lessLength) {
                                        lValue  = patch;
                                        query   = '?patch';
                                    }

                                    callback();
                                }
                            });
                    });

                }, function(callback) {
                    diff(lValue, callback);
                });
            });
        }

        function diff(pNewValue, pCallBack) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.jsload(url, function() {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (!Diff)
                    Diff        = new DiffProto(diff_match_patch);

                Util.ifExec(!isAllowed, function() {
                    patch       = Diff.createPatch(Value, pNewValue);
                    Util.exec(pCallBack, patch);
                }, function(callback) {
                    var path = Info.path;

                    DOM.getDataFromStorage(path, function(data) {
                        if (data)
                            Value   = data;

                        callback();
                    });
                });
            });
        }

        function load(callback) {
            var files  = [
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js',
                    DIR + 'ext-emmet.js'
                ],

                ace     = DIR + 'ace.js',
                url     = CloudFunc.getJoinURL(files);

            Util.time(Name + ' load');

            DOM.anyLoadOnLoad([ace, url], function() {
                Util.timeEnd(Name + ' load');
                Loading = false;
                Util.exec(callback);
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    DOM.RESTful.save(path, Value, onSave);
            }
        }

        this.showMessage    = function(text) {
            var parent,
                TWO_SECONDS = 2000;

            if (!Msg) {
                DOM.cssSet({
                    id      : 'msg-css',
                    inner   : '#view .msg {'        +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
                parent  = Element;

                Msg     = DOM.anyload({
                    name        : 'div',
                    className   : 'msg',
                    parent      : parent
                });
            }

            Msg.innerHTML = text;
            DOM.show(Msg);
            setTimeout(Util.retExec(DOM.hide, Msg), 2000);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<commit_msg>feature(edit) set emmet only for html, not for css<commit_after>var CloudCmd, Util, DOM, CloudFunc, ace, DiffProto, diff_match_patch;
(function(CloudCmd, Util, DOM, CloudFunc) {
    'use strict';

    CloudCmd.Edit = EditProto;

    function EditProto(CallBack) {
        var Name        = 'Edit',
            Loading     = false,
            DIR         = CloudCmd.LIBDIRCLIENT + 'edit/',
            LIBDIR      = CloudCmd.LIBDIR,
            Info        = DOM.CurrentInfo,
            Value,
            Edit        = this,
            Diff,
            Emmet,
            Ace,
            Session,
            Modelist,
            Msg,
            Dialog      = DOM.Dialog,
            Key         = CloudCmd.Key,
            Images      = DOM.Images,
            Element;

       function init() {
            Loading   = true;
            Util.loadOnLoad([
                CloudCmd.View,
                load,
                Edit.show
            ]);
        }

        this.show                       = function(pValue) {
            var lMode, htmlMode, cssMode, url,
                lName       = Info.name,
                isDir       = Info.isDir,
                lExt        = Info.ext;

            if (!Loading) {
                Images.showLoad();

                if (!Element) {
                    Element         = DOM.anyload({
                        name        : 'div',
                        style   :
                            'width      : 100%;'    +
                            'height     : 100%;'    +
                            'font       : 16px "Droid Sans Mono";' +
                            'position: absolute;',
                        not_append : true
                    });

                  initAce();
                }

                if (isDir)
                    lMode = Modelist.modesByName.json.mode;
                else
                    lMode = Modelist.getModeForPath(lName).mode;

                htmlMode  = Modelist.modesByName.html.mode;
                cssMode   = Modelist.modesByName.css.mode;

                Session.setMode(lMode);

                if (lMode === htmlMode) {
                    if (Emmet)
                        Ace.setOption('enableEmmet', true);
                    else {
                        url = CloudFunc.getJoinURL([
                            DIR + 'emmet.js',
                            DIR + 'ext-emmet.js'
                        ]);

                        DOM.jsload(url, function() {
                            Emmet = ace.require('ace/ext/emmet');
                            Emmet.setCore(window.emmet);
                            Ace.setOption('enableEmmet', true);
                        });
                    }
                } else if (Emmet) {
                    Ace.setOption('enableEmmet', false);
                }

                if (Util.isString(pValue)) {
                    Ace.setValue(pValue);
                    CloudCmd.View.show(Element, focus);
                    Key.unsetBind();
                } else
                    Info.getData(function(data) {
                        Value = data;
                        Ace.setValue(data);
                        CloudCmd.View.show(Element, focus);
                    });
            }
        };

        this.hide                       =  function() {
            CloudCmd.View.hide();
        };

        this.goToLine                   = function() {
            var msg     = 'Enter line number:',
                cursor  = Ace.selection.getCursor(),
                number  = cursor.row + 1,
                line    = Dialog.prompt(msg, number);

            number      = line - 0;

            if (number)
                Ace.gotoLine(number);
        };

        function focus() {
            Ace.focus();
            Ace.clearSelection();
            Ace.moveCursorTo(0, 0);
        }

        function initAce() {
            Ace     = ace.edit(Element);
            Session = Ace.getSession();

            Ace.setTheme('ace/theme/tomorrow_night_blue');

            Ace.setShowPrintMargin(false);
            Ace.setShowInvisibles(true);
            Session.setUseSoftTabs(true);

            Ace.commands.addCommand({
                name    : 'hide',
                bindKey : { win: 'Esc',  mac: 'Esc' },
                exec    : function () {
                    Edit.hide();
                }
            });

            Ace.commands.addCommand({
                name    : 'goToLine',
                bindKey : { win: 'Ctrl-G',  mac: 'Command-G' },
                exec    : function () {
                    Edit.goToLine();
                }
            });

            Ace.commands.addCommand({
                name    : 'save',
                bindKey : { win: 'Ctrl-S',  mac: 'Command-S' },
                exec    : save
            });

            Ace.commands.addCommand({
                name    : 'saveMC',
                bindKey : { win: 'F2',  mac: 'F2' },
                exec    : save
            });

            ace.require('ace/ext/language_tools');
            Modelist = ace.require('ace/ext/modelist');

            Ace.setOptions({
                enableBasicAutocompletion   : true,
                enableSnippets              : true
            });
        }

        function save () {
            var lPath       = Info.path,
                lValue      = Ace.getValue();

            CloudCmd.getConfig(function(config) {
                var isDiff = config.diff;

                Util.ifExec(!isDiff, function(patch) {
                    var query,
                        isAllowed   = DOM.Storage.isAllowed();

                    Value           = lValue;

                    Util.ifExec(!isAllowed, function() {
                            DOM.RESTful.save(lPath,  lValue, onSave, query);
                        }, function(callback) {
                            DOM.checkStorageHash(lPath, function(error, equal) {
                                var isString    = Util.isString(patch),
                                    lessLength  = patch.length < lValue.length;

                                if (!error) {
                                    if (equal && isString && patch.length && lessLength) {
                                        lValue  = patch;
                                        query   = '?patch';
                                    }

                                    callback();
                                }
                            });
                    });

                }, function(callback) {
                    diff(lValue, callback);
                });
            });
        }

        function diff(pNewValue, pCallBack) {
            var libs            = [
                    LIBDIR + 'diff/diff-match-patch.js',
                    LIBDIR + 'diff.js'
                ],
                url             = CloudFunc.getJoinURL(libs);

            DOM.jsload(url, function() {
                var patch,
                    isAllowed   = DOM.Storage.isAllowed();

                if (!Diff)
                    Diff        = new DiffProto(diff_match_patch);

                Util.ifExec(!isAllowed, function() {
                    patch       = Diff.createPatch(Value, pNewValue);
                    Util.exec(pCallBack, patch);
                }, function(callback) {
                    var path = Info.path;

                    DOM.getDataFromStorage(path, function(data) {
                        if (data)
                            Value   = data;

                        callback();
                    });
                });
            });
        }

        function load(callback) {
            var files  = [
                    DIR + 'theme-tomorrow_night_blue.js',
                    DIR + 'ext-language_tools.js',
                    DIR + 'ext-searchbox.js',
                    DIR + 'ext-modelist.js'
                ],

                ace     = DIR + 'ace.js',
                url     = CloudFunc.getJoinURL(files);

            Util.time(Name + ' load');

            DOM.anyLoadOnLoad([ace, url], function() {
                Util.timeEnd(Name + ' load');
                Loading = false;
                Util.exec(callback);
            });
        }

        function onSave(text) {
            var ret,
                isError = Util.isContainStrAtBegin(text, 'error'),
                path    = Info.path,
                msg     = '\nShould I save file anyway?';

            if (!isError) {
                Edit.showMessage(text);
                DOM.saveDataToStorage(path, Value);
            } else {
                ret     = Dialog.confirm(text + msg);

                if (ret)
                    DOM.RESTful.save(path, Value, onSave);
            }
        }

        this.showMessage    = function(text) {
            var parent,
                TWO_SECONDS = 2000;

            if (!Msg) {
                DOM.cssSet({
                    id      : 'msg-css',
                    inner   : '#view .msg {'        +
                                'z-index'           + ': 1;'                    +
                                'background-color'  + ': #7285B7;'              +
                                'color'             + ': #D1F1A9;'              +
                                'position'          + ': fixed;'                +
                                'left'              + ': 40%;'                  +
                                'top'               + ': 25px;'                 +
                                'padding'           + ': 5px;'                  +
                                'opacity'           + ': 0.9;'                  +
                                'transition'        + ': ease 0.5s;'            +
                            '}'
                });
                parent  = Element;

                Msg     = DOM.anyload({
                    name        : 'div',
                    className   : 'msg',
                    parent      : parent
                });
            }

            Msg.innerHTML = text;
            DOM.show(Msg);
            setTimeout(Util.retExec(DOM.hide, Msg), 2000);
        };

        init();
    }

})(CloudCmd, Util, DOM, CloudFunc);
<|endoftext|>


<commit_before>/*
 * Dep: [KadOH]/core/stateeventemitter
 * Dep: [KadOH]/core/deferred
 * Dep: [KadOH]/globals
 * Dep: [KadOH]/peer
 * Dep: [KadOH]/peerarray
 * Dep: [KadOH]/rpc/kadohreactor
 * Dep: [KadOH]/routingtable
 * Dep: [KadOH]/util/crypto
 * Dep: [KadOH]/iterativefind
 * Dep: [KadOH]/valuemanagement
 */

(function(exports) {

  var KadOH             = exports,
      StateEventEmitter = KadOH.core.StateEventEmitter,
      Deferred          = KadOH.core.Deferred,
      globals           = KadOH.globals,
      Peer              = KadOH.Peer,
      PeerArray         = KadOH.PeerArray,
      Reactor           = KadOH.rpc.KadOHReactor,
      RoutingTable      = KadOH.RoutingTable,
      Crypto            = KadOH.util.Crypto,
      IterativeFind     = KadOH.IterativeFind,
      ValueManagement   = KadOH.ValueManagement;

  KadOH.Node = Peer.extend({
    /**
     * TODO : explicit the options..
     *
     *
     * @param  {[type]} id      [description]
     * @param  {[type]} options [description]
     * @return {[type]}
     */
    initialize: function(id, options) {
      //extends Peer
      this.supr('null', id || Crypto.digest.randomSHA1());

      //implements StateEventEmitter
      for(var i in StateEventEmitter.prototype) {
        if(i !== 'initialize') this[i] = StateEventEmitter.prototype[i];
      }
      StateEventEmitter.prototype.initialize.call(this);

      this.setState('initializing');

      //store config
      var config = this.config = {};
      for (var option in options) {
        config[option] = options[option];
      }

      //instanciate a routing table and listen to it
      this._routingTable = new RoutingTable(this, config.routing_table);
      this._routingTable.on(this.routingTableEvents, this);

      //instanciate a reactor and listen to it
      this._reactor = new Reactor(this, config.reactor);
      this._reactor.on(this.reactorEvents, this);

      this.setState('initialized');
    },

    /**
     * Reactions to events coming from the reactor.
     * @type {Object}
     */
    reactorEvents : {

      /**
       * On `connected` event :
       *   - save our address on the network
       *   - state is `connected`
       *
       * @param  {String} address - Address of the node on the network
       */
      connected: function(address) {
        this.setAddress(address);
        if (typeof this._store == 'undefined') {
          this._store = new ValueManagement(this, this.config.value_management);
          this._store.on(this.VMEvents, this);
        }
        this.setState('connected');
      },

      /**
       * On `disconnected`, state becomes `disconnected`.
       */
      disconnected: function() {
        this.setState('disconnected');
      },

      /**
       * On `reached` peer, add it to routing table.
       *
       * @param  {Peer} peer - Peer that had been reached.
       */
      reached: function(peer) {
        peer.touch();
        this._routingTable.addPeer(peer);
      },

      /**
       * On `queried` (means we received a RPC request), call
       * the appopriate method to fullfill the RPC.
       * @see #handle+`method_name`
       *
       * @param  {RPC} rpc - The received rpc
       */
      queried: function(rpc) {
        if (! rpc.stateIs('progress'))
          return;
        var methodName = rpc.getMethod();
        this['handle'+methodName].call(this, rpc);
      },

      /**
       * On `outdated` (means we recived a response from a peer
       * which ID seems to be different from the one in the routing table),
       * update the ID in the routing table.
       *
       * @param  {Peer} peer - outdated peer
       * @param  {String} id - new id
       */
      outdated: function(peer, id) {
        this._routingTable.removePeer(peer);
        peer.setID(id);
        this._routingTable.addPeer(peer);
      }
    },

    /**
     * Reactions to events comming from the routing table.
     * @type {Object}
     */
    routingTableEvents : {

      /**
       * On `refresh` (means a kbucket has not seen any fresh
       * peers for a REFRESH_TIMEOUT time), do an titerative find node
       * on a random ID in the KBucket range.
       *
       * @param  {KBucket} kbucket - Kbucket needing to be refreshed
       */
      refresh: function(kbucket) {
        var random_sha = Crypto.digest.randomSHA1(this.getID(), kbucket.getRange());
        this.iterativeFindNode(random_sha);
      }
    },

    /**
     * Reactions to event coming from the value management.
     * @type {Object}
     */
    VMEvents : {

      /**
       * On `republish` (means a key-value needs to be republished
       * on the network ) : do an itrative store on it.
       *
       * @param  {String} key   - key
       * @param  {Object} value - value
       * @param  {Date | Number} exp   - expiration date
       */
      republish: function(key, value, exp) {
        this.iterativeStore(value, exp);
      }
    },

    /**
     * Connect method : make the reactor connect.
     *
     * @param  {Function} [callback] - callback to be called when connected
     * @param  {Object}   [context = this] - context of the callback
     * @return {self}
     */
    connect: function(callback, context) {
      if (this.stateIsNot('connected')) {
        if (callback) {
          this.once('connected', callback, context || this);
        }
        this._reactor.connectTransport();
      }
      return this;
    },

    /**
     * Disconnect method : make the reactor disconnect.
     *
     * @param  {Function} [callback] - callback to be called when connected
     * @param  {Object}   [context = this] - context of the callback
     * @return {self}
     */
    disconnect: function(callback, context) {
      if (this.stateIsNot('disconnected')) {
        if (callback) {
          this.once('disconnected', callback, context || this);
        }
        this._routingTable.stop();
        this._reactor.disconnectTransport();
      }
      return this;
    },

    /**
     * Joining process : do an iterative find node on our own ID,
     * startying by contacting the peers passed as bootstraps.
     *
     * TODO : expose a public API.
     *
     * @param  {Array}    bootstraps - array of adresses
     * @param  {Function} callback   - called when bootstraps process ends
     * @param  {Object}   context    - conetext of the callback
     *
     * @return {self} this
     */
    join: function(bootstraps, callback, context) {
      if (!bootstraps || bootstraps.length === 0) {
        throw new Error('No bootstrap to join the network');
      }

      // bootstrapping
      bootstraps = bootstraps.map(function(address) {
        return new Peer(address, null);
      });

      // lookup process
      var startLookup = function() {
        var deferred = new Deferred();
        this.emit('join started');
        this.iterativeFindNode(this)
            .addErrback(function(reached) {
              if (reached.length() >= globals.K) {
                deferred.resolve();
              } else {
                deferred.reject();
              }
            });
        return deferred;
      };
      var noBootstrap = function() {
        return new Error('no bootstrap');
      };

      // joining result
      var success = function() {
        this.emit('joined');
      };
      var failure = function() {
        this.emit('join failed');
      };

      context = context || this;
      Deferred.whenAtLeast(this._reactor.sendRPCs(bootstraps, 'PING'))
              .pipe(startLookup, noBootstrap, this)
              .then(success, failure, this)
              .then(callback, callback, context);

      return this;
    },

    /**
     * Iterative lookup used by kademlia
     * See /doc papers for informations on the loose parallelism
     * used in this implementation
     * @param {String} id Identifier of the peer or objects
     * @param {String} type The type of the lookup
     * @return {Promise}
     */
    _iterativeFind: function(peer, type) {
      var lookup = new IterativeFind(this, peer, type);
      var peers  = this._routingTable.getClosePeers(peer, globals.K);
      this.emit('iterativeFind started', lookup, peers);
      lookup.startWith(peers);
      return lookup;
    },

    /**
     * TODO : Description
     * TODO : expose a public API and add callback.
     *
     * @param  {[type]} peer [description]
     * @return {[type]}
     */
    iterativeFindNode: function(peer) {
      return this._iterativeFind(peer, 'NODE');
    },

    /**
     * TODO : Description
     * TODO : expose public API with callback
     *
     * @param  {[type]} key [description]
     * @return {[type]}
     */
    iterativeFindValue: function(key) {
      // if succeeds, STORE the value to the closest seen
      // peer which didn't returned the value
      var reactor = this._reactor;
      return this._iterativeFind(key, 'VALUE')
                 .addCallback(function(result, reached) {
                   if (reached.length() > 1) {
                     var index = (reached.newClosestIndex() > 0) ? 0 : 1;
                     reactor.STORE(reached.getPeer(index), key, result.value, result.exp);
                   }
                 });
    },

    /**
     * TODO : Description
     * TODO : Expose public API with callback
     *
     * @param  {[type]} value [description]
     * @param  {[type]} exp   [description]
     * @return {[type]}
     */
    iterativeStore: function(value, exp) {
      var key = Crypto.digest.SHA1(String(value));
      return this.iterativeFindNode(key).pipe(
        function(peers) {
          var targets = peers.pickOutFirst(globals.K);
          return Deferred.whenAtLeast(this._reactor.sendRPCs(targets, 'STORE', key, value, exp), 1)
                         .pipe(function(stores, not_stores) {

                           var peers_stored = new PeerArray(stores.map(function(rpc){
                             return rpc.getQueried();
                           }));

                           var peers_not_stored = new PeerArray(not_stores.map(function(rpc){
                             return rpc.getQueried();
                           }));

                           return {
                                    key        : key,
                                    stored     : peers_stored,
                                    not_stored : peers_not_stored
                                  };
                         }, function(stores, not_stores) {
                           return new PeerArray(not_stores.map(function(rpc){
                             return rpc.getQueried();
                           }));
                         });
        },
        function() {
          return new Error('iterative store failed');
        }, this);
    },

    /**
     * Handle an incoming PING RPC request :
     * simply respond to it.
     *
     * @param  {PingRPC} rpc - the incoming RPC object
     */
    handlePING: function(rpc) {
      rpc.resolve();
    },

    /**
     * Handle an incoming FIND_NODE RPC request :
     * fetch from the routing table the BETA closest
     * peers (except the querying peer) to the
     * targeted ID and respond to the rpc.
     *
     * @param  {FindNodeRPC} rpc - the inconming rpc object
     */
    handleFIND_NODE: function(rpc) {
      rpc.resolve(this._routingTable.getClosePeers(
        rpc.getTarget(),
        globals.BETA,
        [rpc.getQuerying()]
      ));
    },

    /**
     * Handle an incoming FIND_VALUE request:
     * - if we got the value, respond it.
     * - if not, fetch the BETA closest peer, respond them.
     *
     * @param  {FindValueRPC} rpc - the incoming rpc oject
     */
    handleFIND_VALUE: function(rpc) {
      this._store.retrieve(rpc.getTarget(), function(value, exp) {
        if(value !== null) {
          rpc.resolve({value : value, exp : exp}, true);
        } else {
          rpc.resolve(this._routingTable.getClosePeers(
            rpc.getTarget(),
            globals.BETA,
            [rpc.getQuerying()]
          ), false);
        }
      }, this);
    },

    /**
     * Handle an icoming STORE request :
     * sotore the value in ValueManagement and respond.
     *
     * @param  {StoreRPC} rpc - the incoming rpc object.
     */
    handleSTORE: function(rpc) {
      this._store.save(rpc.getKey(), rpc.getValue(), rpc.getExpiration())
                 .then(rpc.resolve, rpc.reject, rpc);
    }
  });

})('object' === typeof module ? module.exports : (this.KadOH = this.KadOH || {}));
<commit_msg>adding a `key` parameter to iterativeStore<commit_after>/*
 * Dep: [KadOH]/core/stateeventemitter
 * Dep: [KadOH]/core/deferred
 * Dep: [KadOH]/globals
 * Dep: [KadOH]/peer
 * Dep: [KadOH]/peerarray
 * Dep: [KadOH]/rpc/kadohreactor
 * Dep: [KadOH]/routingtable
 * Dep: [KadOH]/util/crypto
 * Dep: [KadOH]/iterativefind
 * Dep: [KadOH]/valuemanagement
 */

(function(exports) {

  var KadOH             = exports,
      StateEventEmitter = KadOH.core.StateEventEmitter,
      Deferred          = KadOH.core.Deferred,
      globals           = KadOH.globals,
      Peer              = KadOH.Peer,
      PeerArray         = KadOH.PeerArray,
      Reactor           = KadOH.rpc.KadOHReactor,
      RoutingTable      = KadOH.RoutingTable,
      Crypto            = KadOH.util.Crypto,
      IterativeFind     = KadOH.IterativeFind,
      ValueManagement   = KadOH.ValueManagement;

  KadOH.Node = Peer.extend({
    /**
     * TODO : explicit the options..
     *
     *
     * @param  {[type]} id      [description]
     * @param  {[type]} options [description]
     * @return {[type]}
     */
    initialize: function(id, options) {
      //extends Peer
      this.supr('null', id || Crypto.digest.randomSHA1());

      //implements StateEventEmitter
      for(var i in StateEventEmitter.prototype) {
        if(i !== 'initialize') this[i] = StateEventEmitter.prototype[i];
      }
      StateEventEmitter.prototype.initialize.call(this);

      this.setState('initializing');

      //store config
      var config = this.config = {};
      for (var option in options) {
        config[option] = options[option];
      }

      //instanciate a routing table and listen to it
      this._routingTable = new RoutingTable(this, config.routing_table);
      this._routingTable.on(this.routingTableEvents, this);

      //instanciate a reactor and listen to it
      this._reactor = new Reactor(this, config.reactor);
      this._reactor.on(this.reactorEvents, this);

      this.setState('initialized');
    },

    /**
     * Reactions to events coming from the reactor.
     * @type {Object}
     */
    reactorEvents : {

      /**
       * On `connected` event :
       *   - save our address on the network
       *   - state is `connected`
       *
       * @param  {String} address - Address of the node on the network
       */
      connected: function(address) {
        this.setAddress(address);
        if (typeof this._store == 'undefined') {
          this._store = new ValueManagement(this, this.config.value_management);
          this._store.on(this.VMEvents, this);
        }
        this.setState('connected');
      },

      /**
       * On `disconnected`, state becomes `disconnected`.
       */
      disconnected: function() {
        this.setState('disconnected');
      },

      /**
       * On `reached` peer, add it to routing table.
       *
       * @param  {Peer} peer - Peer that had been reached.
       */
      reached: function(peer) {
        peer.touch();
        this._routingTable.addPeer(peer);
      },

      /**
       * On `queried` (means we received a RPC request), call
       * the appopriate method to fullfill the RPC.
       * @see #handle+`method_name`
       *
       * @param  {RPC} rpc - The received rpc
       */
      queried: function(rpc) {
        if (! rpc.stateIs('progress'))
          return;
        var methodName = rpc.getMethod();
        this['handle'+methodName].call(this, rpc);
      },

      /**
       * On `outdated` (means we recived a response from a peer
       * which ID seems to be different from the one in the routing table),
       * update the ID in the routing table.
       *
       * @param  {Peer} peer - outdated peer
       * @param  {String} id - new id
       */
      outdated: function(peer, id) {
        this._routingTable.removePeer(peer);
        peer.setID(id);
        this._routingTable.addPeer(peer);
      }
    },

    /**
     * Reactions to events comming from the routing table.
     * @type {Object}
     */
    routingTableEvents : {

      /**
       * On `refresh` (means a kbucket has not seen any fresh
       * peers for a REFRESH_TIMEOUT time), do an titerative find node
       * on a random ID in the KBucket range.
       *
       * @param  {KBucket} kbucket - Kbucket needing to be refreshed
       */
      refresh: function(kbucket) {
        var random_sha = Crypto.digest.randomSHA1(this.getID(), kbucket.getRange());
        this.iterativeFindNode(random_sha);
      }
    },

    /**
     * Reactions to event coming from the value management.
     * @type {Object}
     */
    VMEvents : {

      /**
       * On `republish` (means a key-value needs to be republished
       * on the network ) : do an itrative store on it.
       *
       * @param  {String} key   - key
       * @param  {Object} value - value
       * @param  {Date | Number} exp   - expiration date
       */
      republish: function(key, value, exp) {
        this.iterativeStore(value, exp);
      }
    },

    /**
     * Connect method : make the reactor connect.
     *
     * @param  {Function} [callback] - callback to be called when connected
     * @param  {Object}   [context = this] - context of the callback
     * @return {self}
     */
    connect: function(callback, context) {
      if (this.stateIsNot('connected')) {
        if (callback) {
          this.once('connected', callback, context || this);
        }
        this._reactor.connectTransport();
      }
      return this;
    },

    /**
     * Disconnect method : make the reactor disconnect.
     *
     * @param  {Function} [callback] - callback to be called when connected
     * @param  {Object}   [context = this] - context of the callback
     * @return {self}
     */
    disconnect: function(callback, context) {
      if (this.stateIsNot('disconnected')) {
        if (callback) {
          this.once('disconnected', callback, context || this);
        }
        this._routingTable.stop();
        this._reactor.disconnectTransport();
      }
      return this;
    },

    /**
     * Joining process : do an iterative find node on our own ID,
     * startying by contacting the peers passed as bootstraps.
     *
     * TODO : expose a public API.
     *
     * @param  {Array}    bootstraps - array of adresses
     * @param  {Function} callback   - called when bootstraps process ends
     * @param  {Object}   context    - conetext of the callback
     *
     * @return {self} this
     */
    join: function(bootstraps, callback, context) {
      if (!bootstraps || bootstraps.length === 0) {
        throw new Error('No bootstrap to join the network');
      }

      // bootstrapping
      bootstraps = bootstraps.map(function(address) {
        return new Peer(address, null);
      });

      // lookup process
      var startLookup = function() {
        var deferred = new Deferred();
        this.emit('join started');
        this.iterativeFindNode(this)
            .addErrback(function(reached) {
              if (reached.length() >= globals.K) {
                deferred.resolve();
              } else {
                deferred.reject();
              }
            });
        return deferred;
      };
      var noBootstrap = function() {
        return new Error('no bootstrap');
      };

      // joining result
      var success = function() {
        this.emit('joined');
      };
      var failure = function() {
        this.emit('join failed');
      };

      context = context || this;
      Deferred.whenAtLeast(this._reactor.sendRPCs(bootstraps, 'PING'))
              .pipe(startLookup, noBootstrap, this)
              .then(success, failure, this)
              .then(callback, callback, context);

      return this;
    },

    /**
     * Iterative lookup used by kademlia
     * See /doc papers for informations on the loose parallelism
     * used in this implementation
     * @param {String} id Identifier of the peer or objects
     * @param {String} type The type of the lookup
     * @return {Promise}
     */
    _iterativeFind: function(peer, type) {
      var lookup = new IterativeFind(this, peer, type);
      var peers  = this._routingTable.getClosePeers(peer, globals.K);
      this.emit('iterativeFind started', lookup, peers);
      lookup.startWith(peers);
      return lookup;
    },

    /**
     * TODO : Description
     * TODO : expose a public API and add callback.
     *
     * @param  {[type]} peer [description]
     * @return {[type]}
     */
    iterativeFindNode: function(peer) {
      return this._iterativeFind(peer, 'NODE');
    },

    /**
     * TODO : Description
     * TODO : expose public API with callback
     *
     * @param  {[type]} key [description]
     * @return {[type]}
     */
    iterativeFindValue: function(key) {
      // if succeeds, STORE the value to the closest seen
      // peer which didn't returned the value
      var reactor = this._reactor;
      return this._iterativeFind(key, 'VALUE')
                 .addCallback(function(result, reached) {
                   if (reached.length() > 1) {
                     var index = (reached.newClosestIndex() > 0) ? 0 : 1;
                     reactor.STORE(reached.getPeer(index), key, result.value, result.exp);
                   }
                 });
    },

    /**
     * TODO : Description
     * TODO : Expose public API with callback
     *
     * @param  {[type]} value [description]
     * @param  {[type]} key   [description]
     * @param  {[type]} exp   [description]
     * @return {[type]}
     */
    iterativeStore: function(value, key, exp) {
      key = key || Crypto.digest.SHA1(String(value));
      return this.iterativeFindNode(key).pipe(
        function(peers) {
          var targets = peers.pickOutFirst(globals.K);
          return Deferred.whenAtLeast(this._reactor.sendRPCs(targets, 'STORE', key, value, exp), 1)
                         .pipe(function(stored, not_stored) {

                           var peers_stored = new PeerArray(stored.map(function(rpc){
                             return rpc.getQueried();
                           }));

                           var peers_not_stored = new PeerArray(not_stored.map(function(rpc){
                             return rpc.getQueried();
                           }));

                           return {
                             key        : key,
                             stored     : peers_stored,
                             not_stored : peers_not_stored
                           };
                         }, function(stored, not_stored) {
                           return new PeerArray(not_stored.map(function(rpc){
                             return rpc.getQueried();
                           }));
                         });
        },
        function() {
          return new Error('iterative store failed');
        }, this);
    },

    /**
     * Handle an incoming PING RPC request :
     * simply respond to it.
     *
     * @param  {PingRPC} rpc - the incoming RPC object
     */
    handlePING: function(rpc) {
      rpc.resolve();
    },

    /**
     * Handle an incoming FIND_NODE RPC request :
     * fetch from the routing table the BETA closest
     * peers (except the querying peer) to the
     * targeted ID and respond to the rpc.
     *
     * @param  {FindNodeRPC} rpc - the inconming rpc object
     */
    handleFIND_NODE: function(rpc) {
      rpc.resolve(this._routingTable.getClosePeers(
        rpc.getTarget(),
        globals.BETA,
        [rpc.getQuerying()]
      ));
    },

    /**
     * Handle an incoming FIND_VALUE request:
     * - if we got the value, respond it.
     * - if not, fetch the BETA closest peer, respond them.
     *
     * @param  {FindValueRPC} rpc - the incoming rpc oject
     */
    handleFIND_VALUE: function(rpc) {
      this._store.retrieve(rpc.getTarget(), function(value, exp) {
        if(value !== null) {
          rpc.resolve({value : value, exp : exp}, true);
        } else {
          rpc.resolve(this._routingTable.getClosePeers(
            rpc.getTarget(),
            globals.BETA,
            [rpc.getQuerying()]
          ), false);
        }
      }, this);
    },

    /**
     * Handle an icoming STORE request :
     * sotore the value in ValueManagement and respond.
     *
     * @param  {StoreRPC} rpc - the incoming rpc object.
     */
    handleSTORE: function(rpc) {
      this._store.save(rpc.getKey(), rpc.getValue(), rpc.getExpiration())
                 .then(rpc.resolve, rpc.reject, rpc);
    }
  });

})('object' === typeof module ? module.exports : (this.KadOH = this.KadOH || {}));
<|endoftext|>


<commit_before>// Copyright 2012 Mark Cavage, Inc.  All rights reserved.

var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var pooling = require('pooling');

var ConnectionError = require('../errors').ConnectionError;
var BindResponse = require('../messages').BindResponse;

var Client = require('./client');

///--- Globals

var STD_OPS = [
  'add',
  'del',
  'modify',
  'modifyDN'
];

var RETURN_VAL_OPS = [
  'compare',
  'exop'
];

///--- Internal Functions

function createPool(options) {
  assert.ok(options);

  return pooling.createPool({
    checkInterval: options.checkInterval,
    log: options.log,
    name: 'ldapjs_' + (options.url || options.socketPath).replace(/[:/]/g, '_'),
    max: options.maxConnections,
    maxIdleTime: options.maxIdleTime,

    create: function createClient(callback) {
      var client = new Client(options);

      client.on('error', function (err) {
        client.removeAllListeners('connect');
        return callback(err);
      });

      client.once('connect', function onConnect() {
        client.removeAllListeners('error');

        if (!options.bindDN || !options.bindCredentials)
          return callback(null, client);

        function bindCallback(err, res) {
          if (err)
            return callback(err, null);

          return callback(null, client);
        }

        return client.bind(options.bindDN,
                           options.bindCredentials,
                           options.bindControls || [],
                           bindCallback);
      });
    },

    check: function check(client, callback) {
      // just do a root dse search
      client.search('', '(objectclass=*)', function (err, res) {
        if (err)
          return callback(err);

        res.on('error', function (e) {
          client.removeAllListeners('end');
          callback(e);
        });

        res.on('end', function () {
          client.removeAllListeners('error');
          callback(null);
        });

        return undefined;
      });
    },

    destroy: function destroy(client) {
      client.unbind(function () {});
    }
  });
}

///--- API

function ClientPool(options) {
  assert.ok(options);
  EventEmitter.call(this, options);

  this.log = options.log.child({clazz: 'ClientPool'}, true);
  this.options = {
    bindDN: options.bindDN,
    bindCredentials: options.bindCredentials,
    bindControls: options.bindControls || [],
    checkInterval: options.checkInterval,
    connectTimeout: (options.connectTimeout || 0),
    maxIdleTime: options.maxIdleTime,
    maxConnections: options.maxConnections,
    log: options.log,
    socketPath: options.socketPath,
    timeout: (options.timeout || 0),
    url: options.url,
    tlsOptions: options.tlsOptions
  };
  this.pool = createPool(options);
}
util.inherits(ClientPool, EventEmitter);
module.exports = ClientPool;

STD_OPS.forEach(function (op) {
  ClientPool.prototype[op] = function clientProxy() {
    var args = Array.prototype.slice.call(arguments);
    var cb = args.pop();
    if (typeof (cb) !== 'function')
      throw new TypeError('callback (Function) required');
    var self = this;

    return this.pool.acquire(function onAcquire(err, client) {
      if (err)
        return cb(err);

      args.push(function proxyCallback(err, res) {
        self.pool.release(client);
        return cb(err, res);
      });

      try {
        return Client.prototype[op].apply(client, args);
      } catch (e) {
        self.pool.release(client);
        return cb(e);
      }
    });
  };
});

RETURN_VAL_OPS.forEach(function (op) {
  ClientPool.prototype[op] = function clientProxy() {
    var args = Array.prototype.slice.call(arguments);
    var cb = args.pop();
    if (typeof (cb) !== 'function')
      throw new TypeError('callback (Function) required');
    var self = this;

    return this.pool.acquire(function onAcquire(poolErr, client) {
      if (poolErr)
        return cb(poolErr);

      args.push(function proxyCallback(err, val, res) {
        self.pool.release(client);
        return cb(err, val, res);
      });

      try {
        return Client.prototype[op].apply(client, args);
      } catch (e) {
        self.pool.release(client);
        return cb(e);
      }
    });
  };
});

ClientPool.prototype.search = function search(base, opts, controls, callback) {
  if (typeof (controls) === 'function') {
    callback = controls;
    controls = [];
  }

  var self = this;

  return this.pool.acquire(function onAcquire(err, client) {
    if (err)
      return callback(err);

    // This is largely in existence for search requests
    client.timeout = self.timeout || client.timeout;

    return client.search(base, opts, controls, function (err, res) {
      function cleanup() {
        self.pool.release(client);
      }

      if (err) {
        cleanup();
        return callback(err, res);
      }
      res.on('error', cleanup);
      res.on('end', cleanup);

      return callback(null, res);
    });
  });
};

ClientPool.prototype.abandon = function abandon(msgid, controls, callback) {
  if (typeof (controls) === 'function') {
    callback = controls;
    controls = [];
  }

  this.log.error({
    messageID: msgid
  }, 'Abandon is not supported with connection pooling. Ignoring.');
  return callback(null);
};

ClientPool.prototype.bind = function bind(dn, creds, controls, callback) {
  if (typeof (controls) === 'function') {
    callback = controls;
    controls = [];
  }

  var self = this;

  self.options.bindDN = null;
  self.options.bindCredentials = null;
  self.options.bindControls = null;

  return this.pool.shutdown(function () {
    self.pool = createPool(self.options);

    return self.pool.acquire(function onAcquire(err, client) {
      if (err)
        return callback(err);

      return client.bind(dn, creds, controls, function (err, res) {
        self.pool.release(client);

        if (err)
          return callback(err, res);

        self.options.bindDN = dn;
        self.options.bindCredentials = creds;
        self.options.bindControls = controls;

        return callback(null, res);
      });
    });
  });
};

ClientPool.prototype.unbind = function unbind(callback) {
  return this.pool.shutdown(callback);
};
<commit_msg>remove listeners on the right object (s/client/res/)<commit_after>// Copyright 2012 Mark Cavage, Inc.  All rights reserved.

var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var pooling = require('pooling');

var ConnectionError = require('../errors').ConnectionError;
var BindResponse = require('../messages').BindResponse;

var Client = require('./client');

///--- Globals

var STD_OPS = [
  'add',
  'del',
  'modify',
  'modifyDN'
];

var RETURN_VAL_OPS = [
  'compare',
  'exop'
];

///--- Internal Functions

function createPool(options) {
  assert.ok(options);

  return pooling.createPool({
    checkInterval: options.checkInterval,
    log: options.log,
    name: 'ldapjs_' + (options.url || options.socketPath).replace(/[:/]/g, '_'),
    max: options.maxConnections,
    maxIdleTime: options.maxIdleTime,

    create: function createClient(callback) {
      var client = new Client(options);

      client.on('error', function (err) {
        client.removeAllListeners('connect');
        return callback(err);
      });

      client.once('connect', function onConnect() {
        client.removeAllListeners('error');

        if (!options.bindDN || !options.bindCredentials)
          return callback(null, client);

        function bindCallback(err, res) {
          if (err)
            return callback(err, null);

          return callback(null, client);
        }

        return client.bind(options.bindDN,
                           options.bindCredentials,
                           options.bindControls || [],
                           bindCallback);
      });
    },

    check: function check(client, callback) {
      // just do a root dse search
      client.search('', '(objectclass=*)', function (err, res) {
        if (err)
          return callback(err);

        res.on('error', function (e) {
          res.removeAllListeners('end');
          callback(e);
        });

        res.on('end', function () {
          res.removeAllListeners('error');
          callback(null);
        });

        return undefined;
      });
    },

    destroy: function destroy(client) {
      client.unbind(function () {});
    }
  });
}

///--- API

function ClientPool(options) {
  assert.ok(options);
  EventEmitter.call(this, options);

  this.log = options.log.child({clazz: 'ClientPool'}, true);
  this.options = {
    bindDN: options.bindDN,
    bindCredentials: options.bindCredentials,
    bindControls: options.bindControls || [],
    checkInterval: options.checkInterval,
    connectTimeout: (options.connectTimeout || 0),
    maxIdleTime: options.maxIdleTime,
    maxConnections: options.maxConnections,
    log: options.log,
    socketPath: options.socketPath,
    timeout: (options.timeout || 0),
    url: options.url,
    tlsOptions: options.tlsOptions
  };
  this.pool = createPool(options);
}
util.inherits(ClientPool, EventEmitter);
module.exports = ClientPool;

STD_OPS.forEach(function (op) {
  ClientPool.prototype[op] = function clientProxy() {
    var args = Array.prototype.slice.call(arguments);
    var cb = args.pop();
    if (typeof (cb) !== 'function')
      throw new TypeError('callback (Function) required');
    var self = this;

    return this.pool.acquire(function onAcquire(err, client) {
      if (err)
        return cb(err);

      args.push(function proxyCallback(err, res) {
        self.pool.release(client);
        return cb(err, res);
      });

      try {
        return Client.prototype[op].apply(client, args);
      } catch (e) {
        self.pool.release(client);
        return cb(e);
      }
    });
  };
});

RETURN_VAL_OPS.forEach(function (op) {
  ClientPool.prototype[op] = function clientProxy() {
    var args = Array.prototype.slice.call(arguments);
    var cb = args.pop();
    if (typeof (cb) !== 'function')
      throw new TypeError('callback (Function) required');
    var self = this;

    return this.pool.acquire(function onAcquire(poolErr, client) {
      if (poolErr)
        return cb(poolErr);

      args.push(function proxyCallback(err, val, res) {
        self.pool.release(client);
        return cb(err, val, res);
      });

      try {
        return Client.prototype[op].apply(client, args);
      } catch (e) {
        self.pool.release(client);
        return cb(e);
      }
    });
  };
});

ClientPool.prototype.search = function search(base, opts, controls, callback) {
  if (typeof (controls) === 'function') {
    callback = controls;
    controls = [];
  }

  var self = this;

  return this.pool.acquire(function onAcquire(err, client) {
    if (err)
      return callback(err);

    // This is largely in existence for search requests
    client.timeout = self.timeout || client.timeout;

    return client.search(base, opts, controls, function (err, res) {
      function cleanup() {
        self.pool.release(client);
      }

      if (err) {
        cleanup();
        return callback(err, res);
      }
      res.on('error', cleanup);
      res.on('end', cleanup);

      return callback(null, res);
    });
  });
};

ClientPool.prototype.abandon = function abandon(msgid, controls, callback) {
  if (typeof (controls) === 'function') {
    callback = controls;
    controls = [];
  }

  this.log.error({
    messageID: msgid
  }, 'Abandon is not supported with connection pooling. Ignoring.');
  return callback(null);
};

ClientPool.prototype.bind = function bind(dn, creds, controls, callback) {
  if (typeof (controls) === 'function') {
    callback = controls;
    controls = [];
  }

  var self = this;

  self.options.bindDN = null;
  self.options.bindCredentials = null;
  self.options.bindControls = null;

  return this.pool.shutdown(function () {
    self.pool = createPool(self.options);

    return self.pool.acquire(function onAcquire(err, client) {
      if (err)
        return callback(err);

      return client.bind(dn, creds, controls, function (err, res) {
        self.pool.release(client);

        if (err)
          return callback(err, res);

        self.options.bindDN = dn;
        self.options.bindCredentials = creds;
        self.options.bindControls = controls;

        return callback(null, res);
      });
    });
  });
};

ClientPool.prototype.unbind = function unbind(callback) {
  return this.pool.shutdown(callback);
};
<|endoftext|>


<commit_before>var Util, DOM, CloudFunc;

(function(Util, DOM, CloudFunc) {
    'use strict';

    var RESTful     = Util.extendProto(RESTfulProto),
        DOMProto    = Object.getPrototypeOf(DOM);

    Util.extend(DOMProto, {
        RESTful: RESTful
    });

    function RESTfulProto() {
        var Images = DOM.Images;

        this.delete = function(url, data, callback) {
            var isFunc      = Util.isFunction(data);

            if (!callback && isFunc) {
                callback    = data;
                data        = null;
            }

            sendRequest({
                method      : 'DELETE',
                url         : CloudFunc.FS + url,
                data        : data,
                callback    : callback,
                imgPosition : { top: !!data }
            });
        };

        this.write   = function(url, data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : CloudFunc.FS + url,
                data        : data,
                callback    : callback,
                imgPosition : { top: true }
            });
        };

        this.read   = function(url, dataType, callback) {
            var isQuery     = Util.isContainStr(url, '?'),
                isFunc      = Util.isFunction(dataType);

            if (!callback && isFunc) {
                callback    = dataType;
                dataType    = 'text';
            }

            sendRequest({
                method      : 'GET',
                url         : CloudFunc.FS + url,
                callback    : callback,
                notLog      : !isQuery,
                dataType    : dataType
            });
        };

         this.cp     = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/cp',
                data        : data,
                callback    : callback,
                imgPosition : { top: true }
            });
        };

        this.zip    = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/zip',
                data        : data,
                callback    : callback
            });
        };

        this.unzip  = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/unzip',
                data        : data,
                callback    : callback
            });
        };

        this.mv     = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/mv',
                data        : data,
                callback    : callback,
                imgPosition : { top: true }
            });
        };

        this.Config    = {
            read:   function(callback) {
                sendRequest({
                    method      : 'GET',
                    url         : '/config',
                    callback    : callback,
                    imgPosition : { top: true },
                    notLog      : true
                });
            },

            write:  function(data, callback) {
                sendRequest({
                    method      : 'PUT',
                    url         : '/config',
                    data        : data,
                    callback    : callback,
                    imgPosition : { top: true }
                });
            }
        };

        this.Markdown   = {
            read    : function(url, callback) {
                sendRequest({
                    method      : 'GET',
                    url         : '/markdown' + url,
                    callback    : callback,
                    imgPosition : { top: true },
                    notLog      : true
                });
            },

            render  : function(data, callback) {
                sendRequest({
                    method      : 'PUT',
                    url         : '/markdown',
                    data        : data,
                    callback    : callback,
                    imgPosition : { top: true },
                    notLog      : true
                });
            }
        };

       function sendRequest(params) {
            var p               = params,
                apiURL          = CloudFunc.apiURL;

            p.url   = apiURL + p.url;
            p.url   = encodeURI(p.url);

            DOM.load.ajax({
                method      : p.method,
                url         : p.url,
                data        : p.data,
                dataType    : p.dataType,
                error       : Images.showError,
                success     : function(data) {
                    Images.hide();

                    if (!p.notLog)
                        Util.log(data);

                    Util.exec(p.callback, data);
                }
            });
        }
    }
})(Util, DOM, CloudFunc);
<commit_msg>feature(rest) add ability to work with #-names<commit_after>var Util, DOM, CloudFunc;

(function(Util, DOM, CloudFunc) {
    'use strict';

    var RESTful     = Util.extendProto(RESTfulProto),
        DOMProto    = Object.getPrototypeOf(DOM);

    Util.extend(DOMProto, {
        RESTful: RESTful
    });

    function RESTfulProto() {
        var Images = DOM.Images;

        this.delete = function(url, data, callback) {
            var isFunc      = Util.isFunction(data);

            if (!callback && isFunc) {
                callback    = data;
                data        = null;
            }

            sendRequest({
                method      : 'DELETE',
                url         : CloudFunc.FS + url,
                data        : data,
                callback    : callback,
                imgPosition : { top: !!data }
            });
        };

        this.write   = function(url, data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : CloudFunc.FS + url,
                data        : data,
                callback    : callback,
                imgPosition : { top: true }
            });
        };

        this.read   = function(url, dataType, callback) {
            var isQuery     = Util.isContainStr(url, '?'),
                isFunc      = Util.isFunction(dataType);

            if (!callback && isFunc) {
                callback    = dataType;
                dataType    = 'text';
            }

            sendRequest({
                method      : 'GET',
                url         : CloudFunc.FS + url,
                callback    : callback,
                notLog      : !isQuery,
                dataType    : dataType
            });
        };

         this.cp     = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/cp',
                data        : data,
                callback    : callback,
                imgPosition : { top: true }
            });
        };

        this.zip    = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/zip',
                data        : data,
                callback    : callback
            });
        };

        this.unzip  = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/unzip',
                data        : data,
                callback    : callback
            });
        };

        this.mv     = function(data, callback) {
            sendRequest({
                method      : 'PUT',
                url         : '/mv',
                data        : data,
                callback    : callback,
                imgPosition : { top: true }
            });
        };

        this.Config    = {
            read:   function(callback) {
                sendRequest({
                    method      : 'GET',
                    url         : '/config',
                    callback    : callback,
                    imgPosition : { top: true },
                    notLog      : true
                });
            },

            write:  function(data, callback) {
                sendRequest({
                    method      : 'PUT',
                    url         : '/config',
                    data        : data,
                    callback    : callback,
                    imgPosition : { top: true }
                });
            }
        };

        this.Markdown   = {
            read    : function(url, callback) {
                sendRequest({
                    method      : 'GET',
                    url         : '/markdown' + url,
                    callback    : callback,
                    imgPosition : { top: true },
                    notLog      : true
                });
            },

            render  : function(data, callback) {
                sendRequest({
                    method      : 'PUT',
                    url         : '/markdown',
                    data        : data,
                    callback    : callback,
                    imgPosition : { top: true },
                    notLog      : true
                });
            }
        };

       function sendRequest(params) {
            var p               = params,
                apiURL          = CloudFunc.apiURL;

            p.url   = apiURL + p.url;
            p.url   = encodeURI(p.url);

            /*
             * if we send ajax request -
             * no need in hash so we escape #
             */
            p.url   = Util.replaceStr(p.url, '#', '%23');

            DOM.load.ajax({
                method      : p.method,
                url         : p.url,
                data        : p.data,
                dataType    : p.dataType,
                error       : Images.showError,
                success     : function(data) {
                    Images.hide();

                    if (!p.notLog)
                        Util.log(data);

                    Util.exec(p.callback, data);
                }
            });
        }
    }
})(Util, DOM, CloudFunc);
<|endoftext|>


<commit_before>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

module.exports = {
  projectId: process.env.GCLOUD_TESTS_PROJECT_ID,
  keyFilename: process.env.GCLOUD_TESTS_KEY
};

console.log('google-cloud-node configuration');
console.log(module.exports);
<commit_msg>ci: correct tagged commit recognition (#2157)<commit_after>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

module.exports = {
  projectId: process.env.GCLOUD_TESTS_PROJECT_ID,
  keyFilename: process.env.GCLOUD_TESTS_KEY
};
<|endoftext|>


<commit_before>'use strict';

var log = require('db-migrate-shared').log;
var assert = require('assert');

function executeDB (internals, config, callback) {
  var index = require('../../connect');

  if (internals.argv._.length > 0) {
    internals.argv.dbname = internals.argv._.shift().toString();
  } else {
    log.info('Error: You must enter a database name!');
    return;
  }

  index.driver(config.getCurrent().settings, function (err, db) {
    assert.ifError(err);

    if (internals.mode === 'create') {
      db.createDatabase(
        internals.argv.dbname,
        {
          ifNotExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to create database!', err);
          } else {
            log.info('Created database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          else process.exit(err ? 1 : 0);
        }
      );
    } else if (internals.mode === 'drop') {
      db.dropDatabase(
        internals.argv.dbname,
        {
          ifExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to drop database!', err);
          } else {
            log.info('Deleted database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          else process.exit(err ? 1 : 0);
        }
      );
    }
  });
}

module.exports = executeDB;
<commit_msg>fix: #468<commit_after>'use strict';

var log = require('db-migrate-shared').log;
var assert = require('assert');

function executeDB (internals, config, callback) {
  var index = require('../../connect');

  if (internals.argv._.length > 0) {
    internals.argv.dbname = internals.argv._.shift().toString();
  } else {
    log.info('Error: You must enter a database name!');
    return;
  }

  delete config.getCurrent().settings.database;

  index.driver(config.getCurrent().settings, function (err, db) {
    assert.ifError(err);

    if (internals.mode === 'create') {
      db.createDatabase(
        internals.argv.dbname,
        {
          ifNotExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to create database!', err);
          } else {
            log.info('Created database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          else process.exit(err ? 1 : 0);
        }
      );
    } else if (internals.mode === 'drop') {
      db.dropDatabase(
        internals.argv.dbname,
        {
          ifExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to drop database!', err);
          } else {
            log.info('Deleted database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          else process.exit(err ? 1 : 0);
        }
      );
    }
  });
}

module.exports = executeDB;
<|endoftext|>


<commit_before>var File = require('./file');
var Cache = require('./cache');
var Module = require('./module');
var utils = require('./client/utils');

var composition_cache = Cache('compositions');

/**
 * Get module instance composition.
 */
module.exports = function (name, role, callback) {

    // get composition from cache
    var composition = composition_cache.get(name);
    switch (composition) {

        // handle invalid composition configuration
        case 'INVALID':
            return callback(new Error('Invalid composition "' + name + '".'));

        // handle cache hit
        case !undefined:

            // check access for cached item
            if (!utils.roleAccess(composition, role)) {
                return callback(new Error('Access denied for composition "' + name + '"'));
            }

            // return if composition is complete
            if (!composition.LOAD) {
                return callback(null, composition);
            }
    }

    // read the composition json
    File.json(engine.paths.app_composition + name + '.json', function (err, config) {

        // handle error
        if ((err = err || checkComposition(name, role, config))) {
            return callback(err);
        }

        // create mandatory package infos to custom module
        if (typeof config.module === 'object') {
            config.module.name = name;
            config.module.version = 'custom';
            config.module._id = name + '@custom';
            module._base = engine.repo;
        }

        Module(config.module, function (err, modulePackage) {

            // handle module package error
            if (err) {
                return callback(err);
            }

            // TODO prepare instance components
            // File.prepare(config);

            // merge package data into config
            if (modulePackage.engine_instance) {
                config = mergePackage(modulePackage.version, modulePackage.engine_instance, config);
            }

            // save composition in cache
            composition_cache.set(name, config);

            // return composition config
            callback(null, config);
        });
    });
};

/**
 * Check composition config.
 */
function checkComposition (name, role, config) {

    // handle not found
    if (!config) {
        return new Error('composition "' + name +'" not found.');
    }

    // check if composition has a module
    if (!config.module) {

        // save as invalid in cache
        composition_cache.set(name, 'INVALID');
        return new Error('No module info in composition "' + name + '".');
    }

    // check access
    if (!utils.roleAccess(config, role)) {

        // save access information in cache, to check access without loading the hole file again
        composition_cache.set(name, {roles: config.roles, LOAD: true});
        return new Error('Access denied: Role "' + role + '", Composition "' + name + '".');
    }

    // set composition name as custom module name
    if (typeof config.module === 'object' && !config.module.name) {
        config.module.name = config.name;
    }
}

/**
 * Merge package config into composition config.
 */
function mergePackage (version, package_instance, config) {

    // merge client related options
    if (package_instance.client) {

        // ensure client config object
        config.client = config.client || {};
        config.client.name = config.name;
        config.client.version = version;

        // set client module scripts
        if (package_instance.client.module) {
            config.client.module = package_instance.client.module;
        }

        // config
        if (package_instance.client.config) {
            for (var key in package_instance.client.config) {
                if (typeof config.client.config[key] === 'undefined') {
                    config.client.config[key] = package_instance.client.config[key];
                }
            }
        }

        // flow
        if (package_instance.client.flow) {
            config.client.flow = (config.client.flow || []).concat(package_instance.client.flow);
        }

        // markup
        if (package_instance.client.markup) {
            config.client.markup = (config.client.markup || []).concat(package_instance.client.markup);
        }

        // styles
        if (package_instance.client.styles) {
            config.client.styles = (config.client.styles || []).concat(package_instance.client.styles);
        }
    }

    // server flow
    if (package_instance.flow) {
        config.flow = (config.flow || []).concat(package_instance.flow);
    }

    // merge server config
    if (package_instance.config) {
        for (var prop in package_instance.config) {
            if (typeof config.config[prop] === 'undefined') {
                config.config[prop] = package_instance.config[prop];
            }
        }
    }

    return config;
}
<commit_msg>dont check if composition has a server module<commit_after>var File = require('./file');
var Cache = require('./cache');
var Module = require('./module');
var utils = require('./client/utils');

var composition_cache = Cache('compositions');

/**
 * Get module instance composition.
 */
module.exports = function (name, role, callback) {

    // get composition from cache
    var composition = composition_cache.get(name);
    switch (composition) {

        // handle invalid composition configuration
        case 'INVALID':
            return callback(new Error('Invalid composition "' + name + '".'));

        // handle cache hit
        case !undefined:

            // check access for cached item
            if (!utils.roleAccess(composition, role)) {
                return callback(new Error('Access denied for composition "' + name + '"'));
            }

            // return if composition is complete
            if (!composition.LOAD) {
                return callback(null, composition);
            }
    }

    // read the composition json
    File.json(engine.paths.app_composition + name + '.json', function (err, config) {

        // handle error
        if ((err = err || checkComposition(name, role, config))) {
            return callback(err);
        }

        // create mandatory package infos to custom module
        if (typeof config.module === 'object') {
            config.module.name = name;
            config.module.version = 'custom';
            config.module._id = name + '@custom';
            module._base = engine.repo;
        }

        Module(config.module, function (err, modulePackage) {

            // handle module package error
            if (err) {
                return callback(err);
            }

            // prepare instance components
            if (config.client && (config.client.module || config.client.styles || config.client.markup)) {
                File.prepare(config.client, function (err, files) {

                    // update file paths in module package
                    if (files.styles) {
                        config.client.styles = files.styles;
                    }

                    if (files.markup) {
                        config.client.markup = files.markup;
                    }

                    finish(name, modulePackage, config, callback);
                });
                return;
            }

            finish(name, modulePackage, config, callback);
        });
    });
};

function finish (name, modulePackage, config, callback) {

    // merge package data into config
    if (modulePackage.composition) {
        config = mergePackage(modulePackage.version, modulePackage.composition, config);
    }

    // save composition in cache
    composition_cache.set(name, config);

    // return composition config
    callback(null, config);
}

/**
 * Check composition config.
 */
function checkComposition (name, role, config) {

    // handle not found
    if (!config) {
        return new Error('composition "' + name +'" not found.');
    }

    // check if composition has a module
    if (!config.module) {

        // save as invalid in cache
        composition_cache.set(name, 'INVALID');
        return new Error('No module info in composition "' + name + '".');
    }

    // check access
    if (!utils.roleAccess(config, role)) {

        // save access information in cache, to check access without loading the hole file again
        composition_cache.set(name, {roles: config.roles, LOAD: true});
        return new Error('Access denied: Role "' + role + '", Composition "' + name + '".');
    }

    // set composition name as custom module name
    if (typeof config.module === 'object' && !config.module.name) {
        config.module.name = config.name;
    }
}

/**
 * Merge package config into composition config.
 */
function mergePackage (version, package_instance, config) {

    // merge client related options
    if (package_instance.client) {

        // ensure client config object
        config.client = config.client || {};
        config.client.name = config.name;
        config.client.version = version;

        // set client module scripts
        if (package_instance.client.module) {
            config.client.module = package_instance.client.module;
        }

        // config
        if (package_instance.client.config) {
            for (var key in package_instance.client.config) {
                if (typeof config.client.config[key] === 'undefined') {
                    config.client.config[key] = package_instance.client.config[key];
                }
            }
        }

        // flow
        if (package_instance.client.flow) {
            config.client.flow = (config.client.flow || []).concat(package_instance.client.flow);
        }

        // markup
        if (package_instance.client.markup) {
            config.client.markup = (config.client.markup || []).concat(package_instance.client.markup);
        }

        // styles
        if (package_instance.client.styles) {
            config.client.styles = (config.client.styles || []).concat(package_instance.client.styles);
        }
    }

    // server flow
    if (package_instance.flow) {
        config.flow = (config.flow || []).concat(package_instance.flow);
    }

    // merge server config
    if (package_instance.config) {
        for (var prop in package_instance.config) {
            if (typeof config.config[prop] === 'undefined') {
                config.config[prop] = package_instance.config[prop];
            }
        }
    }

    return config;
}
<|endoftext|>


<commit_before>var arrify = require('arrify')
var fs = require('fs')
var path = require('path')
var findUp = require('find-up')
var testExclude = require('test-exclude')
var Yargs = require('yargs/yargs')

var Config = {}

// load config from a cascade of sources:
// * command line arguments.
// * package.json.
// * .nycrc (coming soon)
Config.loadConfig = function (argv, cwd) {
  cwd = cwd || process.env.NYC_CWD || process.cwd()
  var pkgPath = findUp.sync('package.json', {cwd: cwd})
  var rcPath = findUp.sync('.nycrc', {cwd: cwd})
  var rcConfig = null

  if (rcPath) {
    rcConfig = JSON.parse(
      fs.readFileSync(rcPath, 'utf-8')
    )
  }

  if (pkgPath) {
    cwd = path.dirname(pkgPath)
  }

  var config = Config.buildYargs(cwd)
    .default({
      cwd: cwd
    })
  if (rcConfig) config.config(rcConfig)
  config = config.parse(argv || [])

  // post-hoc, we convert several of the
  // configuration settings to arrays, providing
  // a consistent contract to index.js.
  config.require = arrify(config.require)
  config.extension = arrify(config.extension)
  config.exclude = arrify(config.exclude)
  config.include = arrify(config.include)
  config.cwd = cwd

  return config
}

// build a yargs object, omitting any settings
// that would cause the application to exit early.
Config.buildYargs = function (cwd) {
  return Yargs([])
    .usage('$0 [command] [options]\n\nrun your tests with the nyc bin to instrument them with coverage')
    .command('report', 'run coverage report for .nyc_output', function (yargs) {
      return yargs
        .usage('$0 report [options]')
        .option('reporter', {
          alias: 'r',
          describe: 'coverage reporter(s) to use',
          default: 'text'
        })
        .option('report-dir', {
          describe: 'directory to output coverage reports in',
          default: 'coverage'
        })
        .option('temp-directory', {
          describe: 'directory from which coverage JSON files are read',
          default: './.nyc_output'
        })
        .option('show-process-tree', {
          describe: 'display the tree of spawned processes',
          default: false,
          type: 'boolean'
        })
        .example('$0 report --reporter=lcov', 'output an HTML lcov report to ./coverage')
    })
    .command('check-coverage', 'check whether coverage is within thresholds provided', function (yargs) {
      return yargs
        .usage('$0 check-coverage [options]')
        .option('branches', {
          default: 0,
          description: 'what % of branches must be covered?'
        })
        .option('functions', {
          default: 0,
          description: 'what % of functions must be covered?'
        })
        .option('lines', {
          default: 90,
          description: 'what % of lines must be covered?'
        })
        .option('statements', {
          default: 0,
          description: 'what % of statements must be covered?'
        })
        .example('$0 check-coverage --lines 95', "check whether the JSON in nyc's output folder meets the thresholds provided")
    })
    .option('reporter', {
      alias: 'r',
      describe: 'coverage reporter(s) to use',
      default: 'text'
    })
    .option('report-dir', {
      describe: 'directory to output coverage reports in',
      default: 'coverage'
    })
    .option('silent', {
      alias: 's',
      default: false,
      type: 'boolean',
      describe: "don't output a report after tests finish running"
    })
    .option('all', {
      alias: 'a',
      default: false,
      type: 'boolean',
      describe: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)'
    })
    .option('exclude', {
      alias: 'x',
      default: testExclude.defaultExclude,
      describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded'
    })
    .option('include', {
      alias: 'n',
      default: [],
      describe: 'a list of specific files that should be covered, glob patterns are supported'
    })
    .option('require', {
      alias: 'i',
      default: [],
      describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., babel-register, babel-polyfill.'
    })
    .option('cache', {
      alias: 'c',
      default: false,
      type: 'boolean',
      describe: 'cache instrumentation results for improved performance'
    })
    .option('extension', {
      alias: 'e',
      default: [],
      describe: 'a list of extensions that nyc should handle in addition to .js'
    })
    .option('check-coverage', {
      type: 'boolean',
      default: false,
      describe: 'check whether coverage is within thresholds provided'
    })
    .option('branches', {
      default: 0,
      description: 'what % of branches must be covered?'
    })
    .option('functions', {
      default: 0,
      description: 'what % of functions must be covered?'
    })
    .option('lines', {
      default: 90,
      description: 'what % of lines must be covered?'
    })
    .option('statements', {
      default: 0,
      description: 'what % of statements must be covered?'
    })
    .option('source-map', {
      default: true,
      type: 'boolean',
      description: 'should nyc detect and handle source maps?'
    })
    .option('instrument', {
      default: true,
      type: 'boolean',
      description: 'should nyc handle instrumentation?'
    })
    .option('hook-run-in-context', {
      default: true,
      type: 'boolean',
      description: 'should nyc wrap vm.runInThisContext?'
    })
    .option('show-process-tree', {
      describe: 'display the tree of spawned processes',
      default: false,
      type: 'boolean'
    })
    .pkgConf('nyc', cwd || process.cwd())
    .example('$0 npm test', 'instrument your tests with coverage')
    .example('$0 --require babel-core/register npm test', 'instrument your tests with coverage and babel')
    .example('$0 report --reporter=text-lcov', 'output lcov report after running your tests')
    .epilog('visit https://git.io/voHar for list of available reporters')
    .boolean('help')
    .boolean('h')
    .boolean('version')
}

// decorate yargs with all the actions
// that would make it exit: help, version, command.
Config.decorateYargs = function (yargs) {
  return yargs
    .help('h')
    .alias('h', 'help')
    .version()
    .command(require('../lib/commands/instrument'))
}

module.exports = Config
<commit_msg>chore: Remove 'coming soon' note for .nycrc file (#396)<commit_after>var arrify = require('arrify')
var fs = require('fs')
var path = require('path')
var findUp = require('find-up')
var testExclude = require('test-exclude')
var Yargs = require('yargs/yargs')

var Config = {}

// load config from a cascade of sources:
// * command line arguments
// * package.json
// * .nycrc
Config.loadConfig = function (argv, cwd) {
  cwd = cwd || process.env.NYC_CWD || process.cwd()
  var pkgPath = findUp.sync('package.json', {cwd: cwd})
  var rcPath = findUp.sync('.nycrc', {cwd: cwd})
  var rcConfig = null

  if (rcPath) {
    rcConfig = JSON.parse(
      fs.readFileSync(rcPath, 'utf-8')
    )
  }

  if (pkgPath) {
    cwd = path.dirname(pkgPath)
  }

  var config = Config.buildYargs(cwd)
    .default({
      cwd: cwd
    })
  if (rcConfig) config.config(rcConfig)
  config = config.parse(argv || [])

  // post-hoc, we convert several of the
  // configuration settings to arrays, providing
  // a consistent contract to index.js.
  config.require = arrify(config.require)
  config.extension = arrify(config.extension)
  config.exclude = arrify(config.exclude)
  config.include = arrify(config.include)
  config.cwd = cwd

  return config
}

// build a yargs object, omitting any settings
// that would cause the application to exit early.
Config.buildYargs = function (cwd) {
  return Yargs([])
    .usage('$0 [command] [options]\n\nrun your tests with the nyc bin to instrument them with coverage')
    .command('report', 'run coverage report for .nyc_output', function (yargs) {
      return yargs
        .usage('$0 report [options]')
        .option('reporter', {
          alias: 'r',
          describe: 'coverage reporter(s) to use',
          default: 'text'
        })
        .option('report-dir', {
          describe: 'directory to output coverage reports in',
          default: 'coverage'
        })
        .option('temp-directory', {
          describe: 'directory from which coverage JSON files are read',
          default: './.nyc_output'
        })
        .option('show-process-tree', {
          describe: 'display the tree of spawned processes',
          default: false,
          type: 'boolean'
        })
        .example('$0 report --reporter=lcov', 'output an HTML lcov report to ./coverage')
    })
    .command('check-coverage', 'check whether coverage is within thresholds provided', function (yargs) {
      return yargs
        .usage('$0 check-coverage [options]')
        .option('branches', {
          default: 0,
          description: 'what % of branches must be covered?'
        })
        .option('functions', {
          default: 0,
          description: 'what % of functions must be covered?'
        })
        .option('lines', {
          default: 90,
          description: 'what % of lines must be covered?'
        })
        .option('statements', {
          default: 0,
          description: 'what % of statements must be covered?'
        })
        .example('$0 check-coverage --lines 95', "check whether the JSON in nyc's output folder meets the thresholds provided")
    })
    .option('reporter', {
      alias: 'r',
      describe: 'coverage reporter(s) to use',
      default: 'text'
    })
    .option('report-dir', {
      describe: 'directory to output coverage reports in',
      default: 'coverage'
    })
    .option('silent', {
      alias: 's',
      default: false,
      type: 'boolean',
      describe: "don't output a report after tests finish running"
    })
    .option('all', {
      alias: 'a',
      default: false,
      type: 'boolean',
      describe: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)'
    })
    .option('exclude', {
      alias: 'x',
      default: testExclude.defaultExclude,
      describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded'
    })
    .option('include', {
      alias: 'n',
      default: [],
      describe: 'a list of specific files that should be covered, glob patterns are supported'
    })
    .option('require', {
      alias: 'i',
      default: [],
      describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., babel-register, babel-polyfill.'
    })
    .option('cache', {
      alias: 'c',
      default: false,
      type: 'boolean',
      describe: 'cache instrumentation results for improved performance'
    })
    .option('extension', {
      alias: 'e',
      default: [],
      describe: 'a list of extensions that nyc should handle in addition to .js'
    })
    .option('check-coverage', {
      type: 'boolean',
      default: false,
      describe: 'check whether coverage is within thresholds provided'
    })
    .option('branches', {
      default: 0,
      description: 'what % of branches must be covered?'
    })
    .option('functions', {
      default: 0,
      description: 'what % of functions must be covered?'
    })
    .option('lines', {
      default: 90,
      description: 'what % of lines must be covered?'
    })
    .option('statements', {
      default: 0,
      description: 'what % of statements must be covered?'
    })
    .option('source-map', {
      default: true,
      type: 'boolean',
      description: 'should nyc detect and handle source maps?'
    })
    .option('instrument', {
      default: true,
      type: 'boolean',
      description: 'should nyc handle instrumentation?'
    })
    .option('hook-run-in-context', {
      default: true,
      type: 'boolean',
      description: 'should nyc wrap vm.runInThisContext?'
    })
    .option('show-process-tree', {
      describe: 'display the tree of spawned processes',
      default: false,
      type: 'boolean'
    })
    .pkgConf('nyc', cwd || process.cwd())
    .example('$0 npm test', 'instrument your tests with coverage')
    .example('$0 --require babel-core/register npm test', 'instrument your tests with coverage and babel')
    .example('$0 report --reporter=text-lcov', 'output lcov report after running your tests')
    .epilog('visit https://git.io/voHar for list of available reporters')
    .boolean('help')
    .boolean('h')
    .boolean('version')
}

// decorate yargs with all the actions
// that would make it exit: help, version, command.
Config.decorateYargs = function (yargs) {
  return yargs
    .help('h')
    .alias('h', 'help')
    .version()
    .command(require('../lib/commands/instrument'))
}

module.exports = Config
<|endoftext|>