<commit_before>const domain = require('domain'); // eslint-disable-line no-restricted-modules
const vm = require('vm');
const oe = require('obj-ease');
const mqttWildcard = require('mqtt-wildcard');

/* istanbul ignore next */
const time = process.env.DEBUG ? console.time : () => {};
/* istanbul ignore next */
const timeEnd = process.env.DEBUG ? console.timeEnd : () => {};

class Views {
    constructor() {
        this.db = {};
        this.queries = {};
        this.views = {};
        this.viewsEnv = {};
        this.updateQueue = [];

        /* istanbul ignore next */
        this.scriptTimeout = (typeof process.env.SCRIPT_TIMEOUT === 'undefined') ? 0 : process.env.SCRIPT_TIMEOUT;

        process.on('message', msg => {
            switch (msg.type) {
                case 'db':
                    this.db = msg.db;
                    this.rev = msg.rev;
                    Object.keys(this.db).forEach(id => {
                        Object.freeze(this.db[id]);
                    });
                    break;
                case 'update':
                    if (msg.payload === '') {
                        delete this.db[msg.id];
                    } else {
                        this.db[msg.id] = msg.payload;
                        Object.freeze(this.db[msg.id]);
                    }
                    this.rev = msg.rev;
                    this.updateViews();
                    break;

                case 'query':
                    if (msg.init) {
                        this.views[msg.id] = msg.init;
                    }
                    this.query(msg.id, msg.payload, Boolean(msg.init));
                    break;

                /* istanbul ignore next */
                default:
            }
        });
    }

    query(id, payload) {
        if (payload === '') {
            // Delete view
            delete this.queries[id];
            delete this.views[id];
            delete this.viewsEnv[id];
            process.send({type: 'view', id, payload: ''});
        } else {
            // Create/overwrite view
            this.queries[id] = payload;

            const map = payload.map;
            const reduce = payload.reduce;
            const filter = payload.filter;

            if (!this.viewsEnv[id]) {
                this.viewsEnv[id] = {};
            }
            this.viewsEnv[id].rev = -1;

            if (!this.views[id]) {
                this.views[id] = {
                    _id: id,
                    _rev: -1
                };
            }

            let src = `
                api.map = function () {
                    ${map}
                };
                api._result = [];
                api.forEachDocument(id => {`;

            if (filter) {
                src += `
                    if (api.mqttWildcard(id, ${JSON.stringify(filter)})) {
                        api.map.apply(api.getDocument(id));
                    }`;
            } else {
                src += `
                    api.map.apply(api.getDocument(id));`;
            }
            src += `
                });
            `;
            if (reduce) {
                src += `
                api.reduce = function (result) {
                    ${reduce}
                }
                api._result = api.reduce(api._result);
                `;
            }
            delete this.viewsEnv[id].context;
            delete this.viewsEnv[id].script;
            delete this.views[id].serror;
            try {
                time(process.pid + ' create script ' + id);
                this.viewsEnv[id].script = new vm.Script(src, {
                    filename: 'view-' + id
                });
                timeEnd(process.pid + ' create script ' + id);
            } catch (err) {
                this.views[id].error = 'script creation: ' + err.message;
                delete this.views[id].result;
                delete this.views[id].length;
                delete this.viewsEnv[id].script;
                process.send({type: 'view', id, payload: this.views[id]});
            }

            /* istanbul ignore else */
            if (!this.viewsEnv[id].context) {
                time(process.pid + ' createContext ' + id);
                const Sandbox = {
                    /**
                     * @class api
                     */
                    api: {
                        /**
                         * @method api.forEachDocument
                         * @param {forEachDocumentCallback} callback
                         * @description executes a provided function once for each document.
                         */
                        forEachDocument: callback => Object.keys(this.db).forEach(callback),
                        /**
                         * @callback forEachDocumentCallback
                         * @param {string} id the id of the current document
                         */

                        /**
                         * @method api.getDocument
                         * @param {string} id a document id
                         * @returns {object} the document
                         * @description get a document by id
                         */
                        getDocument: id => this.db[id],

                        /**
                         * @method api.getProp
                         * @param {object} document
                         * @param {string} property
                         * @returns {*} the properties value or undefined
                         * @description get a properties value
                         * @see {@link https://github.com/hobbyquaker/obj-ease#getprop|obj-ease documentation}
                         */
                        getProp: oe.getProp,

                        /**
                         * @method api.mqttWildcard
                         * @param {string} id
                         * @param {string} pattern
                         * @returns {array|null}
                         * @description match a string against a MQTT wildcard pattern
                         * @see {@link https://github.com/hobbyquaker/mqtt-wildcard#api|mqtt-wildcard documentation}
                         */
                        mqttWildcard,
                        _result: []
                    },
                    /**
                     * @method emit
                     * @param {*} item
                     * @description push an item to the result array
                     */
                    emit: item => Sandbox.api._result.push(item)
                };
                this.viewsEnv[id].context = vm.createContext(Sandbox);
                timeEnd(process.pid + ' createContext ' + id);
            }

            if (this.viewsEnv[id].script) {
                this.updateQueue.push(id);
                this.shiftQueue();
            }
        }
    }

    execView(id, callback) {
        time(process.pid + ' execView ' + id);
        const script = this.viewsEnv[id].script;
        time(process.pid + ' create domain ' + id);
        const viewDomain = domain.create();
        timeEnd(process.pid + ' create domain ' + id);
        const context = this.viewsEnv[id].context;

        viewDomain.on('error', err => {
            this.views[id].error = 'script execution: ' + err.message;
            delete this.views[id].result;
            delete this.views[id].length;
            process.send({type: 'view', id, payload: this.views[id]});
            callback();
        });

        viewDomain.run(() => {
            setImmediate(() => {
                const rev = this.rev;
                time(process.pid + ' runInContext ' + id);
                script.runInContext(context, {
                    filename: 'view-' + id,
                    timeout: this.scriptTimeout,
                    lineOffset: 2
                });
                timeEnd(process.pid + ' runInContext ' + id);
                timeEnd(process.pid + ' execView ' + id);

                this.viewsEnv[id].rev = rev;

                const res = context.api._result;
                /* istanbul ignore if */
                if (!this.views[id]) {
                    this.views[id] = {
                        _rev: -1
                    };
                }
                delete this.views[id].error;
                delete this.views[id].serror;
                if (!oe.equal(res, this.views[id].result)) {
                    this.views[id]._rev += 1;
                    this.views[id].result = res;
                    this.views[id].length = res.length;
                    process.send({type: 'view', id, payload: this.views[id]});
                }
                callback();
            });
        });
    }

    updateViews() {
        Object.keys(this.queries).forEach(id => {
            this.updateQueue.push(id);
        });
        setImmediate(() => {
            this.shiftQueue();
        });
    }

    shiftQueue() {
        if (this.viewRunning || this.updateQueue.length === 0) {
            return;
        }
        const id = this.updateQueue.shift();
        if (this.viewsEnv[id].rev === this.rev) {
            setImmediate(() => {
                this.shiftQueue();
            });
        } else {
            this.viewRunning = true;
            this.execView(id, () => {
                this.viewRunning = false;
                setImmediate(() => {
                    this.shiftQueue();
                });
            });
        }
    }
}

new Views(); // eslint-disable-line no-new
<commit_msg>performance hint for api.forEachDocument<commit_after>const domain = require('domain'); // eslint-disable-line no-restricted-modules
const vm = require('vm');
const oe = require('obj-ease');
const mqttWildcard = require('mqtt-wildcard');

/* istanbul ignore next */
const time = process.env.DEBUG ? console.time : () => {};
/* istanbul ignore next */
const timeEnd = process.env.DEBUG ? console.timeEnd : () => {};

class Views {
    constructor() {
        this.db = {};
        this.queries = {};
        this.views = {};
        this.viewsEnv = {};
        this.updateQueue = [];

        /* istanbul ignore next */
        this.scriptTimeout = (typeof process.env.SCRIPT_TIMEOUT === 'undefined') ? 0 : process.env.SCRIPT_TIMEOUT;

        process.on('message', msg => {
            switch (msg.type) {
                case 'db':
                    this.db = msg.db;
                    this.rev = msg.rev;
                    Object.keys(this.db).forEach(id => {
                        Object.freeze(this.db[id]);
                    });
                    break;
                case 'update':
                    if (msg.payload === '') {
                        delete this.db[msg.id];
                    } else {
                        this.db[msg.id] = msg.payload;
                        Object.freeze(this.db[msg.id]);
                    }
                    this.rev = msg.rev;
                    this.updateViews();
                    break;

                case 'query':
                    if (msg.init) {
                        this.views[msg.id] = msg.init;
                    }
                    this.query(msg.id, msg.payload, Boolean(msg.init));
                    break;

                /* istanbul ignore next */
                default:
            }
        });
    }

    query(id, payload) {
        if (payload === '') {
            // Delete view
            delete this.queries[id];
            delete this.views[id];
            delete this.viewsEnv[id];
            process.send({type: 'view', id, payload: ''});
        } else {
            // Create/overwrite view
            this.queries[id] = payload;

            const map = payload.map;
            const reduce = payload.reduce;
            const filter = payload.filter;

            if (!this.viewsEnv[id]) {
                this.viewsEnv[id] = {};
            }
            this.viewsEnv[id].rev = -1;

            if (!this.views[id]) {
                this.views[id] = {
                    _id: id,
                    _rev: -1
                };
            }

            let src = `
                api.map = function () {
                    ${map}
                };
                api._result = [];
                api.forEachDocument(id => {`;

            if (filter) {
                src += `
                    if (api.mqttWildcard(id, ${JSON.stringify(filter)})) {
                        api.map.apply(api.getDocument(id));
                    }`;
            } else {
                src += `
                    api.map.apply(api.getDocument(id));`;
            }
            src += `
                });
            `;
            if (reduce) {
                src += `
                api.reduce = function (result) {
                    ${reduce}
                }
                api._result = api.reduce(api._result);
                `;
            }
            delete this.viewsEnv[id].context;
            delete this.viewsEnv[id].script;
            delete this.views[id].serror;
            try {
                time(process.pid + ' create script ' + id);
                this.viewsEnv[id].script = new vm.Script(src, {
                    filename: 'view-' + id
                });
                timeEnd(process.pid + ' create script ' + id);
            } catch (err) {
                this.views[id].error = 'script creation: ' + err.message;
                delete this.views[id].result;
                delete this.views[id].length;
                delete this.viewsEnv[id].script;
                process.send({type: 'view', id, payload: this.views[id]});
            }

            /* istanbul ignore else */
            if (!this.viewsEnv[id].context) {
                time(process.pid + ' createContext ' + id);
                const Sandbox = {
                    /**
                     * @class api
                     */
                    api: {
                        /**
                         * @method api.forEachDocument
                         * @param {forEachDocumentCallback} callback
                         * @description executes a provided function once for each document. Do not use this function inside a map-script, that would result in O(n²) complexity and ruin view composition performance.
                         */
                        forEachDocument: callback => Object.keys(this.db).forEach(callback),
                        /**
                         * @callback forEachDocumentCallback
                         * @param {string} id the id of the current document
                         */

                        /**
                         * @method api.getDocument
                         * @param {string} id a document id
                         * @returns {object} the document
                         * @description get a document by id
                         */
                        getDocument: id => this.db[id],

                        /**
                         * @method api.getProp
                         * @param {object} document
                         * @param {string} property
                         * @returns {*} the properties value or undefined
                         * @description get a properties value
                         * @see {@link https://github.com/hobbyquaker/obj-ease#getprop|obj-ease documentation}
                         */
                        getProp: oe.getProp,

                        /**
                         * @method api.mqttWildcard
                         * @param {string} id
                         * @param {string} pattern
                         * @returns {array|null}
                         * @description match a string against a MQTT wildcard pattern
                         * @see {@link https://github.com/hobbyquaker/mqtt-wildcard#api|mqtt-wildcard documentation}
                         */
                        mqttWildcard,
                        _result: []
                    },
                    /**
                     * @method emit
                     * @param {*} item
                     * @description push an item to the result array
                     */
                    emit: item => Sandbox.api._result.push(item)
                };
                this.viewsEnv[id].context = vm.createContext(Sandbox);
                timeEnd(process.pid + ' createContext ' + id);
            }

            if (this.viewsEnv[id].script) {
                this.updateQueue.push(id);
                this.shiftQueue();
            }
        }
    }

    execView(id, callback) {
        time(process.pid + ' execView ' + id);
        const script = this.viewsEnv[id].script;
        time(process.pid + ' create domain ' + id);
        const viewDomain = domain.create();
        timeEnd(process.pid + ' create domain ' + id);
        const context = this.viewsEnv[id].context;

        viewDomain.on('error', err => {
            this.views[id].error = 'script execution: ' + err.message;
            delete this.views[id].result;
            delete this.views[id].length;
            process.send({type: 'view', id, payload: this.views[id]});
            callback();
        });

        viewDomain.run(() => {
            setImmediate(() => {
                const rev = this.rev;
                time(process.pid + ' runInContext ' + id);
                script.runInContext(context, {
                    filename: 'view-' + id,
                    timeout: this.scriptTimeout,
                    lineOffset: 2
                });
                timeEnd(process.pid + ' runInContext ' + id);
                timeEnd(process.pid + ' execView ' + id);

                this.viewsEnv[id].rev = rev;

                const res = context.api._result;
                /* istanbul ignore if */
                if (!this.views[id]) {
                    this.views[id] = {
                        _rev: -1
                    };
                }
                delete this.views[id].error;
                delete this.views[id].serror;
                if (!oe.equal(res, this.views[id].result)) {
                    this.views[id]._rev += 1;
                    this.views[id].result = res;
                    this.views[id].length = res.length;
                    process.send({type: 'view', id, payload: this.views[id]});
                }
                callback();
            });
        });
    }

    updateViews() {
        Object.keys(this.queries).forEach(id => {
            this.updateQueue.push(id);
        });
        setImmediate(() => {
            this.shiftQueue();
        });
    }

    shiftQueue() {
        if (this.viewRunning || this.updateQueue.length === 0) {
            return;
        }
        const id = this.updateQueue.shift();
        if (this.viewsEnv[id].rev === this.rev) {
            setImmediate(() => {
                this.shiftQueue();
            });
        } else {
            this.viewRunning = true;
            this.execView(id, () => {
                this.viewRunning = false;
                setImmediate(() => {
                    this.shiftQueue();
                });
            });
        }
    }
}

new Views(); // eslint-disable-line no-new
<|endoftext|>


<commit_before>var sys    = require('sys');

var REQUIRED_NODE_VERSION = '0.1.99';
_checkVersionNumber();

var events = require('events'),
    fs     = require('fs');

var csv = exports;

var CsvReader = csv.CsvReader = function(readStream, options) {
    var self = this;
    _setOptions(self, options);

    self.parsingStatus = {
        rows:          0,
        openRecord:    [],
        openField:     '',
        lastChar:      '',
        quotedField:   false,
        commentedLine: false
    };

    if (readStream) {
        readStream.addListener('data', function(data) { self.parse(data) });
        readStream.addListener('error', function() { self.emit('error') });
        readStream.addListener('end', function() { self.end() });
    }
};
sys.inherits(CsvReader, events.EventEmitter);

CsvReader.prototype.parse = function(data) {
    var ps = this.parsingStatus;
    for (var i = 0; i < data.length; i++) {
        var c = data.charAt(i);
        switch (c) {
            // escape and separator may be the same char, typically '"'
            case this.escapechar:
            case this.quotechar:
                if (ps.commentedLine) break;
                var isEscape = false;
                if (c === this.escapechar) {
                    var nextChar = data.charAt(i + 1);
                    if (this._isEscapable(nextChar)) {
                        this._addCharacter(nextChar);
                        i++;
                        isEscape = true;
                    }
                }
                if (!isEscape && (c === this.quotechar)) {
                    if (ps.openField && !ps.quotedField) {
                        ps.quotedField = true;
                        break;
                    }
                    if (ps.quotedField) {
                        // closing quote should be followed by separator unless the nested quotes option is set
                        var nextChar = data.charAt(i + 1);
                        if (nextChar && nextChar != '\r' && nextChar != '\n' && nextChar !== this.separator && this.nestedQuotes != true) {
                            throw new Error("separator expected after a closing quote; found " + nextChar);
                        } else {
                            ps.quotedField = false;
                        }
                    } else if (ps.openField === '') {
                        ps.quotedField = true;
                    }
                }
                break;
            case this.separator:
                if (ps.commentedLine) break;
                if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addField();
                }
                break;
            case '\n':
                // handle CRLF sequence
                if (!ps.quotedField && (ps.lastChar === '\r')) {
                    break;
                }
            case '\r':
                if (ps.commentedLine) {
                    ps.commentedLine = false;
                } else if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addField();
                    this._addRecord();
                }
                break;
            case this.commentchar:
                if (ps.commentedLine) break;
                if (ps.openRecord.length === 0 && ps.openField === '' && !ps.quotedField) {
                    ps.commentedLine = true;
                } else {
                    this._addCharacter(c);
                }
            default:
                if (ps.commentedLine) break;
                this._addCharacter(c);
        }
        ps.lastChar = c;
    }
};

CsvReader.prototype.end = function() {
    var ps = this.parsingStatus;
    if (ps.quotedField) {
        this.emit('error', new Error('Input stream ended but closing quotes expected'));
    } else {
        // dump open record
        if (ps.openField) {
            this._addField();
        }
        if (ps.openRecord.length > 0) {
            this._addRecord();
        }
        this.emit('end');
    }
}

CsvReader.prototype._isEscapable = function(c) {
    if ((c === this.escapechar) || (c === this.quotechar)) {
        return true;
    }
    return false;
};

CsvReader.prototype._addCharacter = function(c) {
    this.parsingStatus.openField += c;
};

CsvReader.prototype._addField = function() {
    var ps = this.parsingStatus;
    ps.openRecord.push(ps.openField);
    ps.openField = '';
    ps.quotedField = false;
};

CsvReader.prototype.setColumnNames = function(names) {
    this.columnNames = names;
};

CsvReader.prototype._addRecord = function() {
    var ps = this.parsingStatus;
    if (this.columnsFromHeader && ps.rows === 0) {
        this.setColumnNames(ps.openRecord);
    } else if (this.columnNames != null && this.columnNames.length > 0) {
        var objResult = {};
        for (var i = 0; i < this.columnNames.length; i++) {
            objResult[this.columnNames[i]] = ps.openRecord[i];
        }
        this.emit('data', objResult);
    } else {
        this.emit('data', ps.openRecord);
    }
    ps.rows++;
    ps.openRecord = [];
    ps.openField = '';
    ps.quotedField = false;
};

csv.createCsvFileReader = function(path, options) {
    options = options || {};
    var readStream = fs.createReadStream(path, {
        'flags': 'r'
    });
    if (options.encoding) {
        readStream.setEncoding(options.encoding);
    } else {
        readStream.setEncoding('utf8');
    }
    return new CsvReader(readStream, options);
};

csv.createCsvStreamReader = function(readStream, options) {
    if (options === undefined && typeof readStream === 'object') {
        options = readStream;
        readStream = undefined;
    }
    options = options || {};
    if (readStream)
       readStream.setEncoding(options.encoding ? options.encoding : 'utf8');
    return new CsvReader(readStream, options);
};

var CsvWriter = csv.CsvWriter = function(writeStream, options) {
    var self = this;
    self.writeStream = writeStream;
    options = options || {};
    _setOptions(self, options);
    self.encoding = options.encoding || 'utf8';

    if (typeof writeStream.setEncoding === 'function') {
        writeStream.setEncoding(self.encoding);
    }

    writeStream.addListener('drain', function() { self.emit('drain') });
    writeStream.addListener('error', function() { self.emit('error') });
    writeStream.addListener('close', function() { self.emit('close') });
};
sys.inherits(CsvWriter, events.EventEmitter);

CsvWriter.prototype.writeRecord = function(rec) {
    if (!rec) return; // ignore empty records
    if (typeof(rec) !== 'object') {
        throw new Error("CsvWriter.writeRecord takes an array as an argument");
    }
    if (rec.length || rec.length === 0) { // array
        _writeArray(this, rec);
    } else {          // hash
        throw new Error("CsvWriter.writeRecord takes an array as an argument, "
                      + "hashes are not supported.");
    }
};

function _writeArray(writer, arr) {
    var out = [];
    for (var i = 0; i < arr.length; i++) {
        if (i != 0) out.push(writer.separator);
        out.push(writer.quotechar);
        _appendField(out, writer, arr[i]);
        out.push(writer.quotechar);
    }
    out.push("\r\n");
    writer.writeStream.write(out.join(''), this.encoding);
};

function _appendField(outArr, writer, field) {
    if (field == null) {
        outArr.push('');
        return;
    }
    if (field.length == undefined){
       //deal with numbers
       field = '' + field;
    }
    for (var i = 0; i < field.length; i++) {
        if (field.charAt(i) === writer.quotechar || field.charAt(i) === writer.escapechar) {
            outArr.push(writer.escapechar);
        }
        outArr.push(field.charAt(i));
    }
};

csv.createCsvFileWriter = function(path, options) {
    var writeStream = fs.createWriteStream(path, {
        'flags': 'w'
    });
    return new CsvWriter(writeStream, options);
};

csv.createCsvStreamWriter = function(writeStream, options) {
    return new CsvWriter(writeStream, options);
};

// ===============
// =   utils     =
// ===============

function _setOptions(obj, options) {
    options = options || {};
    obj.separator   = options.separator   || ',';
    obj.quotechar   = options.quote       || '"';
    obj.escapechar  = options.escape      || '"';
    obj.commentchar = options.comment     || '';
    obj.columnNames = options.columnNames || [];
    obj.columnsFromHeader = options.columnsFromHeader || false;
    obj.nestedQuotes = options.nestedQuotes || false;
};

function _checkVersionNumber() {
    var supported = (function() {
        if (!process.version) return false;
        function version2fields(v) {
            var fields = v.split('.');
            return [ parseInt(fields[0]), parseInt(fields[1]), parseInt(fields[2]) ];
        }
        var r  = version2fields(REQUIRED_NODE_VERSION);
        var a  = version2fields(process.version.replace(/^v/, ''));
        if (a[0] > r[0]) {
            return true;
        } else if (a[0] === r[0]) {
            if (a[1] > r[1]) {
                return true;
            }  else if (a[1] === r[1]) {
                if (a[2] >= r[2]) return true;
            }
        }
        return false;
    })();
    if (! supported) {
        sys.debug("Unsupported Node.js version: expected "
                    + REQUIRED_NODE_VERSION + " or higher, got " + process.version);
    }
};
<commit_msg>NPM enforces the field for "engines" in package.json at install time, so there should not be any need for boilerplate code for checking the version of node.<commit_after>var sys    = require('sys'),
    events = require('events'),
    fs     = require('fs');

var csv = exports;

var CsvReader = csv.CsvReader = function(readStream, options) {
    var self = this;
    _setOptions(self, options);

    self.parsingStatus = {
        rows:          0,
        openRecord:    [],
        openField:     '',
        lastChar:      '',
        quotedField:   false,
        commentedLine: false
    };

    if (readStream) {
        readStream.addListener('data', function(data) { self.parse(data) });
        readStream.addListener('error', function() { self.emit('error') });
        readStream.addListener('end', function() { self.end() });
    }
};
sys.inherits(CsvReader, events.EventEmitter);

CsvReader.prototype.parse = function(data) {
    var ps = this.parsingStatus;
    for (var i = 0; i < data.length; i++) {
        var c = data.charAt(i);
        switch (c) {
            // escape and separator may be the same char, typically '"'
            case this.escapechar:
            case this.quotechar:
                if (ps.commentedLine) break;
                var isEscape = false;
                if (c === this.escapechar) {
                    var nextChar = data.charAt(i + 1);
                    if (this._isEscapable(nextChar)) {
                        this._addCharacter(nextChar);
                        i++;
                        isEscape = true;
                    }
                }
                if (!isEscape && (c === this.quotechar)) {
                    if (ps.openField && !ps.quotedField) {
                        ps.quotedField = true;
                        break;
                    }
                    if (ps.quotedField) {
                        // closing quote should be followed by separator unless the nested quotes option is set
                        var nextChar = data.charAt(i + 1);
                        if (nextChar && nextChar != '\r' && nextChar != '\n' && nextChar !== this.separator && this.nestedQuotes != true) {
                            throw new Error("separator expected after a closing quote; found " + nextChar);
                        } else {
                            ps.quotedField = false;
                        }
                    } else if (ps.openField === '') {
                        ps.quotedField = true;
                    }
                }
                break;
            case this.separator:
                if (ps.commentedLine) break;
                if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addField();
                }
                break;
            case '\n':
                // handle CRLF sequence
                if (!ps.quotedField && (ps.lastChar === '\r')) {
                    break;
                }
            case '\r':
                if (ps.commentedLine) {
                    ps.commentedLine = false;
                } else if (ps.quotedField) {
                    this._addCharacter(c);
                } else {
                    this._addField();
                    this._addRecord();
                }
                break;
            case this.commentchar:
                if (ps.commentedLine) break;
                if (ps.openRecord.length === 0 && ps.openField === '' && !ps.quotedField) {
                    ps.commentedLine = true;
                } else {
                    this._addCharacter(c);
                }
            default:
                if (ps.commentedLine) break;
                this._addCharacter(c);
        }
        ps.lastChar = c;
    }
};

CsvReader.prototype.end = function() {
    var ps = this.parsingStatus;
    if (ps.quotedField) {
        this.emit('error', new Error('Input stream ended but closing quotes expected'));
    } else {
        // dump open record
        if (ps.openField) {
            this._addField();
        }
        if (ps.openRecord.length > 0) {
            this._addRecord();
        }
        this.emit('end');
    }
}

CsvReader.prototype._isEscapable = function(c) {
    if ((c === this.escapechar) || (c === this.quotechar)) {
        return true;
    }
    return false;
};

CsvReader.prototype._addCharacter = function(c) {
    this.parsingStatus.openField += c;
};

CsvReader.prototype._addField = function() {
    var ps = this.parsingStatus;
    ps.openRecord.push(ps.openField);
    ps.openField = '';
    ps.quotedField = false;
};

CsvReader.prototype.setColumnNames = function(names) {
    this.columnNames = names;
};

CsvReader.prototype._addRecord = function() {
    var ps = this.parsingStatus;
    if (this.columnsFromHeader && ps.rows === 0) {
        this.setColumnNames(ps.openRecord);
    } else if (this.columnNames != null && this.columnNames.length > 0) {
        var objResult = {};
        for (var i = 0; i < this.columnNames.length; i++) {
            objResult[this.columnNames[i]] = ps.openRecord[i];
        }
        this.emit('data', objResult);
    } else {
        this.emit('data', ps.openRecord);
    }
    ps.rows++;
    ps.openRecord = [];
    ps.openField = '';
    ps.quotedField = false;
};

csv.createCsvFileReader = function(path, options) {
    options = options || {};
    var readStream = fs.createReadStream(path, {
        'flags': 'r'
    });
    if (options.encoding) {
        readStream.setEncoding(options.encoding);
    } else {
        readStream.setEncoding('utf8');
    }
    return new CsvReader(readStream, options);
};

csv.createCsvStreamReader = function(readStream, options) {
    if (options === undefined && typeof readStream === 'object') {
        options = readStream;
        readStream = undefined;
    }
    options = options || {};
    if (readStream)
       readStream.setEncoding(options.encoding ? options.encoding : 'utf8');
    return new CsvReader(readStream, options);
};

var CsvWriter = csv.CsvWriter = function(writeStream, options) {
    var self = this;
    self.writeStream = writeStream;
    options = options || {};
    _setOptions(self, options);
    self.encoding = options.encoding || 'utf8';

    if (typeof writeStream.setEncoding === 'function') {
        writeStream.setEncoding(self.encoding);
    }

    writeStream.addListener('drain', function() { self.emit('drain') });
    writeStream.addListener('error', function() { self.emit('error') });
    writeStream.addListener('close', function() { self.emit('close') });
};
sys.inherits(CsvWriter, events.EventEmitter);

CsvWriter.prototype.writeRecord = function(rec) {
    if (!rec) return; // ignore empty records
    if (typeof(rec) !== 'object') {
        throw new Error("CsvWriter.writeRecord takes an array as an argument");
    }
    if (rec.length || rec.length === 0) { // array
        _writeArray(this, rec);
    } else {          // hash
        throw new Error("CsvWriter.writeRecord takes an array as an argument, "
                      + "hashes are not supported.");
    }
};

function _writeArray(writer, arr) {
    var out = [];
    for (var i = 0; i < arr.length; i++) {
        if (i != 0) out.push(writer.separator);
        out.push(writer.quotechar);
        _appendField(out, writer, arr[i]);
        out.push(writer.quotechar);
    }
    out.push("\r\n");
    writer.writeStream.write(out.join(''), this.encoding);
};

function _appendField(outArr, writer, field) {
    if (field == null) {
        outArr.push('');
        return;
    }
    if (field.length == undefined){
       //deal with numbers
       field = '' + field;
    }
    for (var i = 0; i < field.length; i++) {
        if (field.charAt(i) === writer.quotechar || field.charAt(i) === writer.escapechar) {
            outArr.push(writer.escapechar);
        }
        outArr.push(field.charAt(i));
    }
};

csv.createCsvFileWriter = function(path, options) {
    var writeStream = fs.createWriteStream(path, {
        'flags': 'w'
    });
    return new CsvWriter(writeStream, options);
};

csv.createCsvStreamWriter = function(writeStream, options) {
    return new CsvWriter(writeStream, options);
};

// ===============
// =   utils     =
// ===============

function _setOptions(obj, options) {
    options = options || {};
    obj.separator   = options.separator   || ',';
    obj.quotechar   = options.quote       || '"';
    obj.escapechar  = options.escape      || '"';
    obj.commentchar = options.comment     || '';
    obj.columnNames = options.columnNames || [];
    obj.columnsFromHeader = options.columnsFromHeader || false;
    obj.nestedQuotes = options.nestedQuotes || false;
};
<|endoftext|>


<commit_before>/*
 * Flush stats to zabbix (http://www.zabbix.com/).
 *
 * To enable this backend, include 'statsd-zabbix-backend'
 * in the backends * configuration array:
 *
 *   backends: ['statsd-zabbix-backend']
 *
 * This backend supports the following config options:
 *
 *   zabbixHost: Hostname of zabbix server.
 *   zabbixPort: Port to contact zabbix server at.
 *   zabbixSender: Path to zabbix_sender utility. (leave blank to use node-zabbix-sender module instead)
 *
 *   Optional
 *   hostname: Static hostname associated with the stats to send to zabbix
 *             If provided, StatsD Zabbix backend will not attempt to decode a
 *             hostname from each key
 *
 */

var util = require('util'),
    proc = require('child_process');

var debug;
var flushInterval;
var zabbixHost;
var zabbixPort;
var zabbixCmd;
var zabbixSender = null;
var senderModule;

var zabbixStats = {};

var post_stats = function zabbix_post_stats(statString) {
  if (zabbixHost) {
    if (debug) {
      util.log('statsString: ' + statString);
    }

    if(zabbixCmd) {
      // we're spawning a child process to run the shell zabbix_sender command
      try {
        var zabbixExec = proc.exec(zabbixCmd, function (error, stdout, stderr) {
          if (error && error.code !== 0 && debug) {
            util.log(zabbixSender + ': ' + stderr);
          }
        });

        zabbixExec.stdin.write(statString);
        zabbixExec.stdin.end();
      } catch (e) {
        if (debug) {
          util.log(e);
        }
        zabbixStats.last_exception = Math.round(new Date().getTime() / 1000);
      }
    }
    else {
      // we're using the module, not a shell command, so no child process
      try {
        var Sender = new senderModule({host: zabbixHost, with_timestamps: true, items_host: '68.226.99.8'});
        // statString is a bunch of lines to be parsed and added one at a time.
        var statArray = statString.split('\n');
        statArray.forEach(function (v, i, array) {
          var data = v.split(' ', 4);
          // third one is always the timestamp so leave that out.
          Sender.addItem([data[0], data[1]].join('.'), data[3]);
          if (debug) {
            util.log([data[0], data[1]].join('.'), data[3]);
          }
        });
        Sender.send(function (err, res) {
          if (err) {
            throw err;
          }

          // print the response object - for testing
          if (debug) {
            util.log(res);
          }
        });
      } catch (e) {
        if (debug) {
          util.log('node-zabbix-sender error: ' + e);
        }
      }
    }
  }
}

var zabbix_host_key_from_encoding = function (key) {
    // Logstash uses a . separator, but what is standard?
    var host_key = key.split('.');

    // Handle a namespace in front of host.key
    if (host_key.length >= 3) {
      var namespace = host_key[0];
      var host = host_key[1];
      var remaining = host_key.slice(2);

      // When the key is greater than 3 then we join the tail of host key
      var key = remaining.join('_');

      // Replace underscores with periods
      if (namespace === "logstash") {
        host = host.replace(/_/g, '.');
        key = remaining.join('.').replace(/_/g, '.');
      }

      if (namespace === "kamon") {
        host = host.replace(/_/g, '.');
        key = remaining.join('_');
      }
    } else {
      // Split on host_key by default separator
      host_key = key.split('_');
      var host = host_key[0];
      var key = host_key[1];
    }

    return {
      'host': host,
      'key': key
    }
}

var zabbix_host_key_from_config = function (host, key) {
    return {
        'host': host,
        'key': key
    };
}

var flush_stats = function zabbix_flush(zabbix_host_key, ts, metrics) {
  console.log('flushing stats...');
  var statString = '';
  var numStats = 0;
  var key;
  var zabbix;

  var counters = metrics.counters;
  var gauges = metrics.gauges;
  var timers = metrics.timers;
  var pctThreshold = metrics.pctThreshold;

  for (key in counters) {
    var value = counters[key];
    var valuePerSecond = value / (flushInterval / 1000); // calculate "per second" rate

    zabbix = zabbix_host_key(key);

    statString += zabbix.host + ' ' + zabbix.key + '[total] ' + ts + ' ' + value          + "\n";
    statString += zabbix.host + ' ' + zabbix.key + '[avg] '   + ts + ' ' + valuePerSecond + "\n";

    numStats += 1;
  }

  for (key in timers) {
    if (timers[key].length > 0) {
      var values = timers[key].sort(function (a,b) { return a-b; });
      var count = values.length;
      var min = values[0];
      var max = values[count - 1];

      var mean = min;
      var maxAtThreshold = max;

      var message = "";

      zabbix = zabbix_host_key(key);

      var key2;

      for (key2 in pctThreshold) {
        var pct = pctThreshold[key2];
        if (count > 1) {
          var thresholdIndex = Math.round(((100 - pct) / 100) * count);
          var numInThreshold = count - thresholdIndex;
          var pctValues = values.slice(0, numInThreshold);
          maxAtThreshold = pctValues[numInThreshold - 1];

          // average the remaining timings
          var sum = 0;
          for (var i = 0; i < numInThreshold; i++) {
            sum += pctValues[i];
          }

          mean = sum / numInThreshold;
        }

        var clean_pct = '' + pct;
        clean_pct.replace('.', '_');
        message += zabbix.host + ' ' + zabbix.key + '[mean]['  + clean_pct + '] ' + ts + ' ' + mean           + "\n";
        message += zabbix.host + ' ' + zabbix.key + '[upper][' + clean_pct + '] ' + ts + ' ' + maxAtThreshold + "\n";
      }

      message += zabbix.host + ' ' + zabbix.key + '[upper] ' + ts + ' ' + max   + "\n";
      message += zabbix.host + ' ' + zabbix.key + '[lower] ' + ts + ' ' + min   + "\n";
      message += zabbix.host + ' ' + zabbix.key + '[count] ' + ts + ' ' + count + "\n";
      statString += message;

      numStats += 1;
    }
  }

  for (key in gauges) {
    zabbix = zabbix_host_key(key);

    statString += zabbix.host + ' ' + zabbix.key + ' ' + ts + ' ' + gauges[key] + "\n";
    numStats += 1;
  }

  post_stats(statString);
};

var backend_status = function zabbix_status(writeCb) {
  for (stat in zabbixStats) {
    writeCb(null, 'zabbix', stat, zabbixStats[stat]);
  }
};

exports.zabbix_host_key_from_encoding = zabbix_host_key_from_encoding;
exports.zabbix_host_key_from_config = zabbix_host_key_from_config;

exports.init = function zabbix_init(startup_time, config, events) {
  debug = config.debug;
  zabbixHost = config.zabbixHost;
  zabbixPort = config.zabbixPort;
  zabbixSender = config.zabbixSender;
  zabbix_host_key = config.hostname ? zabbix_host_key_from_config.bind(undefined, config.hostname) : zabbix_host_key_from_encoding;

  if(zabbixSender) {
    zabbixCmd = zabbixSender + ' -T -i - -z ' + zabbixHost + ' -p ' + zabbixPort;
  }
  else {
    senderModule = require('node-zabbix-sender');
  }

  zabbixStats.last_flush = startup_time;
  zabbixStats.last_exception = startup_time;

  flushInterval = config.flushInterval;

  events.on('flush', flush_stats.bind(undefined, zabbix_host_key));
  events.on('status', backend_status);

  return true;
};

<commit_msg>even more cleaning and tidying.<commit_after>/*
 * Flush stats to zabbix (http://www.zabbix.com/).
 *
 * To enable this backend, include 'statsd-zabbix-backend'
 * in the backends * configuration array:
 *
 *   backends: ['statsd-zabbix-backend']
 *
 * This backend supports the following config options:
 *
 *   zabbixHost: Hostname of zabbix server.
 *   zabbixPort: Port to contact zabbix server at.
 *   zabbixSender: Path to zabbix_sender utility. (leave blank to use node-zabbix-sender module instead)
 *
 *   Optional
 *   hostname: Static hostname associated with the stats to send to zabbix
 *             If provided, StatsD Zabbix backend will not attempt to decode a
 *             hostname from each key
 *
 */

var util = require('util'),
    proc = require('child_process');

var debug;
var flushInterval;
var zabbixHost;
var zabbixPort;
var zabbixCmd;
var zabbixSender = null;
var senderModule;

var zabbixStats = {};

var post_stats = function zabbix_post_stats(statString) {
  if (zabbixHost) {
    if(zabbixCmd) {
      // we're spawning a child process to run the shell zabbix_sender command
      try {
        var zabbixExec = proc.exec(zabbixCmd, function (error, stdout, stderr) {
          if (error && error.code !== 0 && debug) {
            util.log(zabbixSender + ': ' + stderr);
          }
        });

        zabbixExec.stdin.write(statString);
        zabbixExec.stdin.end();
      } catch (e) {
        if (debug) {
          util.log(e);
        }
        zabbixStats.last_exception = Math.round(new Date().getTime() / 1000);
      }
    }
    else {
      // we're using the module, not a shell command, so no child process
      try {
        var Sender = new senderModule({host: zabbixHost, with_timestamps: true, items_host: '68.226.99.8'});
        // statString is a bunch of lines to be parsed and added one at a time.
        var statArray = statString.split('\n');
        statArray.forEach(function (v, i, array) {
          var data = v.split(' ', 4);
          if (data[1]) {  // there might be a blank line at the end.
            // third one is always the timestamp so leave that out.
            Sender.addItem([data[0], data[1]].join('.'), data[3]);
            if (debug) {
              util.log([data[0], data[1]].join('.'), data[3]);
            }
          }
        });

        Sender.send(function (err, res) {
          if (err) {
            throw err;
          }

          // print the response object - for testing
          if (debug) {
            util.log(res);
          }
        });

      } catch (e) {
        if (debug) {
          util.log('node-zabbix-sender error: ' + e);
        }
      }
    }
  }
}

var zabbix_host_key_from_encoding = function (key) {
    // Logstash uses a . separator, but what is standard?
    var host_key = key.split('.');

    // Handle a namespace in front of host.key
    if (host_key.length >= 3) {
      var namespace = host_key[0];
      var host = host_key[1];
      var remaining = host_key.slice(2);

      // When the key is greater than 3 then we join the tail of host key
      var key = remaining.join('_');

      // Replace underscores with periods
      if (namespace === "logstash") {
        host = host.replace(/_/g, '.');
        key = remaining.join('.').replace(/_/g, '.');
      }

      if (namespace === "kamon") {
        host = host.replace(/_/g, '.');
        key = remaining.join('_');
      }
    } else {
      // Split on host_key by default separator
      host_key = key.split('_');
      var host = host_key[0];
      var key = host_key[1];
    }

    return {
      'host': host,
      'key': key
    }
}

var zabbix_host_key_from_config = function (host, key) {
    return {
        'host': host,
        'key': key
    };
}

var flush_stats = function zabbix_flush(zabbix_host_key, ts, metrics) {
  console.log('flushing stats...');
  var statString = '';
  var numStats = 0;
  var key;
  var zabbix;

  var counters = metrics.counters;
  var gauges = metrics.gauges;
  var timers = metrics.timers;
  var pctThreshold = metrics.pctThreshold;

  for (key in counters) {
    var value = counters[key];
    var valuePerSecond = value / (flushInterval / 1000); // calculate "per second" rate

    zabbix = zabbix_host_key(key);

    statString += zabbix.host + ' ' + zabbix.key + '[total] ' + ts + ' ' + value          + "\n";
    statString += zabbix.host + ' ' + zabbix.key + '[avg] '   + ts + ' ' + valuePerSecond + "\n";

    numStats += 1;
  }

  for (key in timers) {
    if (timers[key].length > 0) {
      var values = timers[key].sort(function (a,b) { return a-b; });
      var count = values.length;
      var min = values[0];
      var max = values[count - 1];

      var mean = min;
      var maxAtThreshold = max;

      var message = "";

      zabbix = zabbix_host_key(key);

      var key2;

      for (key2 in pctThreshold) {
        var pct = pctThreshold[key2];
        if (count > 1) {
          var thresholdIndex = Math.round(((100 - pct) / 100) * count);
          var numInThreshold = count - thresholdIndex;
          var pctValues = values.slice(0, numInThreshold);
          maxAtThreshold = pctValues[numInThreshold - 1];

          // average the remaining timings
          var sum = 0;
          for (var i = 0; i < numInThreshold; i++) {
            sum += pctValues[i];
          }

          mean = sum / numInThreshold;
        }

        var clean_pct = '' + pct;
        clean_pct.replace('.', '_');
        message += zabbix.host + ' ' + zabbix.key + '[mean]['  + clean_pct + '] ' + ts + ' ' + mean           + "\n";
        message += zabbix.host + ' ' + zabbix.key + '[upper][' + clean_pct + '] ' + ts + ' ' + maxAtThreshold + "\n";
      }

      message += zabbix.host + ' ' + zabbix.key + '[upper] ' + ts + ' ' + max   + "\n";
      message += zabbix.host + ' ' + zabbix.key + '[lower] ' + ts + ' ' + min   + "\n";
      message += zabbix.host + ' ' + zabbix.key + '[count] ' + ts + ' ' + count + "\n";
      statString += message;

      numStats += 1;
    }
  }

  for (key in gauges) {
    zabbix = zabbix_host_key(key);

    statString += zabbix.host + ' ' + zabbix.key + ' ' + ts + ' ' + gauges[key] + "\n";
    numStats += 1;
  }

  post_stats(statString);
};

var backend_status = function zabbix_status(writeCb) {
  for (stat in zabbixStats) {
    writeCb(null, 'zabbix', stat, zabbixStats[stat]);
  }
};

exports.zabbix_host_key_from_encoding = zabbix_host_key_from_encoding;
exports.zabbix_host_key_from_config = zabbix_host_key_from_config;

exports.init = function zabbix_init(startup_time, config, events) {
  debug = config.debug;
  zabbixHost = config.zabbixHost;
  zabbixPort = config.zabbixPort;
  zabbixSender = config.zabbixSender;
  zabbix_host_key = config.hostname ? zabbix_host_key_from_config.bind(undefined, config.hostname) : zabbix_host_key_from_encoding;

  if(zabbixSender) {
    zabbixCmd = zabbixSender + ' -T -i - -z ' + zabbixHost + ' -p ' + zabbixPort;
  }
  else {
    senderModule = require('node-zabbix-sender');
  }

  zabbixStats.last_flush = startup_time;
  zabbixStats.last_exception = startup_time;

  flushInterval = config.flushInterval;

  events.on('flush', flush_stats.bind(undefined, zabbix_host_key));
  events.on('status', backend_status);

  return true;
};

<|endoftext|>


<commit_before>var git = require( '../' ),
  success = require('./utilities').success,
  events = require('events');

/**
 * Convenience commit constructor.
 *
 * @constructor
 * @param  {RawCommit|Null} rawCommit
 * @return {Commit}
 */
var Commit = function(rawRepo, rawCommit) {
  if (!(rawRepo instanceof git.raw.Repo)) {
    throw git.error('First parameter for Commit must be a raw repo');
  }

  this.rawRepo = rawRepo;

  if (rawCommit instanceof git.raw.Commit) {
    this.rawCommit = rawCommit;
  } else {
    this.rawCommit = new git.raw.Commit();
  }
};

/**
 * Look up the commit referenced by oid, replace this.commit with the result.
 *
 * @param  {git.oid|git.raw.Oid|String} oid
 * @param  {Function} callback
 */
Commit.prototype.lookup = function(oid, callback) {
  if (typeof oid !== 'undefined' &&
      typeof oid !== 'string' &&
      !(oid instanceof git.raw.Oid)) {
    oid = oid.getRawOid();
  }
  var self = this;
  self.rawCommit.lookup(self.rawRepo, oid, function commitLookup(error, rawCommit) {
    if (success(error, callback)) {
      self.rawCommit = rawCommit;
      callback(null, self);
    }
  });
};

/**
 * Retrieve the commit's Oid
 *
 * @param  {Function} callback
 */
Commit.prototype.oid = function(callback) {
  callback(null, new git.oid(this.rawCommit.oid()));
};

/**
 * Retrieve the SHA
 *
 * @param  {Function} callback
 */
Commit.prototype.sha = function(callback) {
  this.rawCommit.sha(function(error, sha) {
    if (success(error, callback)) {
      callback(null, sha);
    }
  });
};

/**
 * Retrieve the message
 *
 * @param  {Function} callback
 */
Commit.prototype.message = function(callback) {
  this.rawCommit.message(function(error, message) {
    if (success(error, callback)) {
      callback(null, message);
    }
  });
};

/**
 * Retrieve the commit unix timestamp.
 *
 * @param  {Function} callback
 */
Commit.prototype.time = function(callback) {
  this.rawCommit.time(function(error, time) {
    if (success(error, callback)) {
      callback(null, time);
    }
  });
};

/**
 * Retrieve the commit's positive or negative timezone offset, in minutes from UTC.
 *
 * @param  {Function} callback
 */
Commit.prototype.offset = function(callback) {
  this.rawCommit.offset(function(error, offset) {
    if (success(error, callback)) {
      callback(null, offset);
    }
  });
};

/**
 * Retrieve the commit's author.
 *
 * @param  {Function} callback
 */
Commit.prototype.author = function(callback) {
  this.rawCommit.author(function(error, rawSignature) {
    if (success(error, callback)) {
      callback(null, new git.signature(rawSignature));
    }
  });
};

/**
 * Retrieve the commit's committer.
 *
 * @param  {Function} callback
 */
Commit.prototype.committer = function(callback) {
  this.rawCommit.committer(function(error, rawSignature) {
    if (success(error, callback)) {
      callback(null, new git.signature(rawSignature));
    }
  });
};

/**
 * Retrieve the tree for this commit.
 *
 * @param  {Function} callback
 */
Commit.prototype.tree = function(callback) {
  var self = this;
  self.rawCommit.tree(function commitTree(error, rawTree) {
    if (success(error, callback)) {
      callback(null, new git.tree(self.rawRepo, rawTree));
    }
  });
};

/**
 * Retrieve the file represented by path for this commit.
 *
 * @param  {String} path
 * @param  {Function} callback
 */
Commit.prototype.file = function(path, callback) {
  this.tree(function commitFile(error, tree) {
    if (!success(error, callback)) {
      return;
    }
    tree.entry(path, function(error, entry) {
      if (success(error, callback)) {
        callback(null, entry);
      }
    });
  });
};

/**
 * Walk the history of this commit.
 *
 * @return {Event} Event emits 'commit', with error, commit and 'end', with
 *                       error, commits[]
 */
Commit.prototype.history = function() {
  var event = new events.EventEmitter(),
      self = this;

  self.oid(function commitOid(error, oid) {
    (new git.revwalk(self.rawRepo)).allocate(function createRevwalk(error, revwalk) {
      var commits = [];
      revwalk.walk(oid, function commitRevWalk(error, index, commit, noMoreCommits) {
        if(error) {
          event.emit('end', error, commits);
          return false;
        }

        if (noMoreCommits) {
          event.emit('end', null, commits);
          return;
        }
        event.emit('commit', null, commit);
        commits.push(commit);
      });
    });
  });

  return event;
};

/**
 * Retrieve the commit's parents.
 *
 * @param {Function} callback
 */
Commit.prototype.parents = function(callback) {
  var self = this;
  self.rawCommit.parents(function processParent(error, rawParents) {
    if (success(error, callback)) {
      var parents = [];
      rawParents.forEach(function eachParent(rawParent) {
        parents.push(new Commit(self.rawRepo, rawParent));
      });
      callback(null, parents);
    }
  });
};

/**
 * Get a diff tree showing changes between this commit and its parent(s).
 *
 * @param  {Function} callback
 */
Commit.prototype.parentsDiffTrees = function(callback) {
  var self = this;
  self.sha(function(error, commitSha) {
    if (!success(error, callback)) {
      return;
    }
    self.parents(function commitParents(error, parents) {
      if (!success(error, callback)) {
        return;
      }
      var parentDiffLists = [];
      parents.forEach(function commitEachParent(parent) {
        parent.sha(function commitParentSha(error, parentSha) {
          (new git.diffList(self.repo)).treeToTree(parentSha, commitSha, function walkDiffList(error, diffList) {
            if (!success(error, callback)) {
              return;
            }
            parentDiffLists.push(diffList);
            if (parentDiffLists.length === parents.length) {
              callback(null, parentDiffLists);
            }
          });
        });
      });
    });
  });
};

exports.commit = Commit;
<commit_msg>Fixed typo in parentsDiffTrees<commit_after>var git = require( '../' ),
  success = require('./utilities').success,
  events = require('events');

/**
 * Convenience commit constructor.
 *
 * @constructor
 * @param  {RawCommit|Null} rawCommit
 * @return {Commit}
 */
var Commit = function(rawRepo, rawCommit) {
  if (!(rawRepo instanceof git.raw.Repo)) {
    throw git.error('First parameter for Commit must be a raw repo');
  }

  this.rawRepo = rawRepo;

  if (rawCommit instanceof git.raw.Commit) {
    this.rawCommit = rawCommit;
  } else {
    this.rawCommit = new git.raw.Commit();
  }
};

/**
 * Look up the commit referenced by oid, replace this.commit with the result.
 *
 * @param  {git.oid|git.raw.Oid|String} oid
 * @param  {Function} callback
 */
Commit.prototype.lookup = function(oid, callback) {
  if (typeof oid !== 'undefined' &&
      typeof oid !== 'string' &&
      !(oid instanceof git.raw.Oid)) {
    oid = oid.getRawOid();
  }
  var self = this;
  self.rawCommit.lookup(self.rawRepo, oid, function commitLookup(error, rawCommit) {
    if (success(error, callback)) {
      self.rawCommit = rawCommit;
      callback(null, self);
    }
  });
};

/**
 * Retrieve the commit's Oid
 *
 * @param  {Function} callback
 */
Commit.prototype.oid = function(callback) {
  callback(null, new git.oid(this.rawCommit.oid()));
};

/**
 * Retrieve the SHA
 *
 * @param  {Function} callback
 */
Commit.prototype.sha = function(callback) {
  this.rawCommit.sha(function(error, sha) {
    if (success(error, callback)) {
      callback(null, sha);
    }
  });
};

/**
 * Retrieve the message
 *
 * @param  {Function} callback
 */
Commit.prototype.message = function(callback) {
  this.rawCommit.message(function(error, message) {
    if (success(error, callback)) {
      callback(null, message);
    }
  });
};

/**
 * Retrieve the commit unix timestamp.
 *
 * @param  {Function} callback
 */
Commit.prototype.time = function(callback) {
  this.rawCommit.time(function(error, time) {
    if (success(error, callback)) {
      callback(null, time);
    }
  });
};

/**
 * Retrieve the commit's positive or negative timezone offset, in minutes from UTC.
 *
 * @param  {Function} callback
 */
Commit.prototype.offset = function(callback) {
  this.rawCommit.offset(function(error, offset) {
    if (success(error, callback)) {
      callback(null, offset);
    }
  });
};

/**
 * Retrieve the commit's author.
 *
 * @param  {Function} callback
 */
Commit.prototype.author = function(callback) {
  this.rawCommit.author(function(error, rawSignature) {
    if (success(error, callback)) {
      callback(null, new git.signature(rawSignature));
    }
  });
};

/**
 * Retrieve the commit's committer.
 *
 * @param  {Function} callback
 */
Commit.prototype.committer = function(callback) {
  this.rawCommit.committer(function(error, rawSignature) {
    if (success(error, callback)) {
      callback(null, new git.signature(rawSignature));
    }
  });
};

/**
 * Retrieve the tree for this commit.
 *
 * @param  {Function} callback
 */
Commit.prototype.tree = function(callback) {
  var self = this;
  self.rawCommit.tree(function commitTree(error, rawTree) {
    if (success(error, callback)) {
      callback(null, new git.tree(self.rawRepo, rawTree));
    }
  });
};

/**
 * Retrieve the file represented by path for this commit.
 *
 * @param  {String} path
 * @param  {Function} callback
 */
Commit.prototype.file = function(path, callback) {
  this.tree(function commitFile(error, tree) {
    if (!success(error, callback)) {
      return;
    }
    tree.entry(path, function(error, entry) {
      if (success(error, callback)) {
        callback(null, entry);
      }
    });
  });
};

/**
 * Walk the history of this commit.
 *
 * @return {Event} Event emits 'commit', with error, commit and 'end', with
 *                       error, commits[]
 */
Commit.prototype.history = function() {
  var event = new events.EventEmitter(),
      self = this;

  self.oid(function commitOid(error, oid) {
    (new git.revwalk(self.rawRepo)).allocate(function createRevwalk(error, revwalk) {
      var commits = [];
      revwalk.walk(oid, function commitRevWalk(error, index, commit, noMoreCommits) {
        if(error) {
          event.emit('end', error, commits);
          return false;
        }

        if (noMoreCommits) {
          event.emit('end', null, commits);
          return;
        }
        event.emit('commit', null, commit);
        commits.push(commit);
      });
    });
  });

  return event;
};

/**
 * Retrieve the commit's parents.
 *
 * @param {Function} callback
 */
Commit.prototype.parents = function(callback) {
  var self = this;
  self.rawCommit.parents(function processParent(error, rawParents) {
    if (success(error, callback)) {
      var parents = [];
      rawParents.forEach(function eachParent(rawParent) {
        parents.push(new Commit(self.rawRepo, rawParent));
      });
      callback(null, parents);
    }
  });
};

/**
 * Get a diff tree showing changes between this commit and its parent(s).
 *
 * @param  {Function} callback
 */
Commit.prototype.parentsDiffTrees = function(callback) {
  var self = this;
  self.sha(function(error, commitSha) {
    if (!success(error, callback)) {
      return;
    }
    self.parents(function commitParents(error, parents) {
      if (!success(error, callback)) {
        return;
      }
      var parentDiffLists = [];
      parents.forEach(function commitEachParent(parent) {
        parent.sha(function commitParentSha(error, parentSha) {
          (new git.diffList(self.rawRepo)).treeToTree(parentSha, commitSha, function walkDiffList(error, diffList) {
            if (!success(error, callback)) {
              return;
            }
            parentDiffLists.push(diffList);
            if (parentDiffLists.length === parents.length) {
              callback(null, parentDiffLists);
            }
          });
        });
      });
    });
  });
};

exports.commit = Commit;
<|endoftext|>


<commit_before>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var is = require('is');
var css = require('css');
var path = require('path');
var join = path.join;
var extname = path.extname;
var rename = require('./rename');
var udeps = require('umd-deps');
var cdeps = require('./css-deps');
var util = require('./util');
var debug = util.debug;
var colors = util.colors;

/**
 * Transport vinyl id
 * - vinyl: vinyl object
 * - required options: idleading, rename
 */

function transportId(vinyl, options){
  var id;
  var pkg = util.parsePackage(vinyl, options.wwwroot);
  var idleading = resolveIdleading(options.idleading, vinyl.path, pkg);

  // get id
  id = util.template(idleading, pkg);
  // rename id
  id = util.addExt(id);
  id = rename(id, options.rename);
  id = util.hideExt(id);

  // seajs has hacked css before 3.0.0
  // https://github.com/seajs/seajs/blob/2.2.1/src/util-path.js#L49
  // demo https://github.com/popomore/seajs-test/tree/master/css-deps
  if (extname(id) === '.css') {
    id += '.js';
  }

  // normalize id
  id = util.normalize(id);

  // debug
  debug('transport id: %s', colors.data(id));

  // rewrite vinyl path
  if (path.isAbsolute(id)) {
    vinyl.path = join(options.wwwroot, util.addExt(id));
  } else {
    vinyl.path = join(vinyl.cwd, vinyl.base, util.addExt(id));
  }

  // set vinyl package info
  vinyl.package = util.extend(pkg, { id: id });

  return id;
}

/**
 * Transport cmd dependencies.
 * - vinyl: vinyl object
 * - required options: idleading
 */

function transportDeps(vinyl, options){
  var deps = [];
  var include = [];
  var vars = options.vars;
  var alias = options.alias;
  var paths = options.paths;
  var pkg = vinyl.package || {};

  // replace require and collect dependencies
  vinyl.contents = new Buffer(udeps(vinyl.contents.toString(), function (id, flag){
    // parse id form alias, paths, vars
    id = util.parseAlias(id, alias);
    id = util.parsePaths(id, paths);
    id = util.parseAlias(id, alias);
    id = util.parseVars(id, vars);
    id = util.parseAlias(id, alias);

    // id is not a local file
    if (!util.isLocal(id)) {
      // cache dependencie id
      deps.push(id);

      return id;
    }

    var path;

    // normalize id
    id = util.normalize(id);

    // if end with /, find index file
    if (id.substring(id.length - 1) === '/') {
      id += 'index';
    }

    // debug
    debug('transport%s deps: %s', flag ? ' ' + flag : '', colors.data(id));

    // add extname
    path = util.addExt(id);
    // rename id
    id = rename(path, options.rename);
    // hide extname
    id = util.hideExt(id);

    // seajs has hacked css before 3.0.0
    // https://github.com/seajs/seajs/blob/2.2.1/src/util-path.js#L49
    // demo https://github.com/popomore/seajs-test/tree/master/css-deps
    if (extname(id) === '.css') {
      id += '.js';
    }

    // normalize id
    id = util.normalize(id);

    // cache dependencie id and path
    if (flag === null) {
      // cache dependencie id
      deps.push(id);

      // get absolute path
      path = util.resolve(path, vinyl, options.wwwroot);

      // cache dependencie absolute path
      include.push({
        id: id,
        path: path
      });
    }

    return id;
  }, true));

  // Cache file dependencies
  vinyl.package = util.extend(pkg, {
    include: include,
    dependencies: deps
  });

  return deps;
}

/**
 * Transport css dependencies.
 * - vinyl: vinyl object
 */

function transportCssDeps(vinyl, options){
  var deps = [];
  var include = [];
  var prefix = options.prefix;
  var pkg = vinyl.package || {};

  // compute prefix
  prefix = is.fn(prefix) ? prefix(pkg.id || null, vinyl.path) : prefix;

  // replace imports and collect dependencies
  vinyl.contents = new Buffer(cdeps(vinyl.contents, function (id){
    var path;

    // id is not a local file
    if (!util.isLocal(id)) {
      // cache dependencie id
      deps.push(id);

      // keep import
      return id;
    }

    // normalize id
    id = util.normalize(id);

    var isRelative = util.isRelative(id);
    var isAbsolute = util.isAbsolute(id);

    // css import parsing rules using html
    if (!isAbsolute && !isRelative) {
      id = './' + id;
    }

    // if end with /, find index file
    if (id.substring(id.length - 1) === '/') {
      id += 'index.css';
    }

    // add extname
    path = util.addExt(id);
    // rename id
    id = rename(path, options.rename);
    // hide extname
    id = util.hideExt(id);

    // seajs has hacked css before 3.0.0
    // https://github.com/seajs/seajs/blob/2.2.1/src/util-path.js#L49
    // demo https://github.com/popomore/seajs-test/tree/master/css-deps
    if (extname(id) === '.css') {
      id += '.js';
    }

    // normalize id
    id = util.normalize(id);

    // debug
    debug('transport deps: %s', colors.data(id));

    // get absolute path
    path = util.resolve(path, vinyl, options.wwwroot);

    // cache dependencie id
    deps.push(id);
    // cache dependencie absolute path
    include.push({
      id: id,
      path: path
    });

    // delete all import
    return false;
  }, options.oncsspath, prefix));

  // Cache file dependencies
  vinyl.package = util.extend(pkg, {
    include: include,
    dependencies: deps
  });

  return deps;
}

/*
 Create a parser in lib/parser
 */

function plugin(type, transport){
  return function (vinyl, options){
    // debug
    debug('read %s: %s', type, colors.data(util.pathFromCwd(vinyl.path)));

    vinyl = transport(vinyl, options);

    return vinyl;
  };
}

/**
 * resolve id leading
 * @param idleading
 * @param path
 * @param pkg
 * @returns {*}
 */

function resolveIdleading(idleading, path, pkg){
  return is.fn(idleading) ? idleading(path, pkg) : idleading;
}

/**
 * Exports module.
 */

exports.plugin = plugin;
exports.transportId = transportId;
exports.transportDeps = transportDeps;
exports.transportCssDeps = transportCssDeps;
exports.resolveIdleading = resolveIdleading;
<commit_msg>add source files<commit_after>/**
 * Created by nuintun on 2015/4/27.
 */

'use strict';

var is = require('is');
var css = require('css');
var path = require('path');
var join = path.join;
var extname = path.extname;
var rename = require('./rename');
var udeps = require('umd-deps');
var cdeps = require('./css-deps');
var util = require('./util');
var debug = util.debug;
var colors = util.colors;

/**
 * Transport vinyl id
 * - vinyl: vinyl object
 * - required options: idleading, rename
 */

function transportId(vinyl, options){
  var id;
  var pkg = util.parsePackage(vinyl, options.wwwroot);
  var idleading = resolveIdleading(options.idleading, vinyl.path, pkg);

  // get id
  id = util.template(idleading, pkg);
  // rename id
  id = util.addExt(id);
  id = rename(id, options.rename);
  id = util.hideExt(id);

  // seajs has hacked css before 3.0.0
  // https://github.com/seajs/seajs/blob/2.2.1/src/util-path.js#L49
  // demo https://github.com/popomore/seajs-test/tree/master/css-deps
  if (extname(id) === '.css') {
    id += '.js';
  }

  // normalize id
  id = util.normalize(id);

  // debug
  debug('transport id: %s', colors.data(id));

  // rewrite vinyl path
  if (path.isAbsolute(id)) {
    vinyl.path = join(options.wwwroot, util.addExt(id));
  } else {
    vinyl.path = join(vinyl.cwd, vinyl.base, util.addExt(id));
  }

  // set vinyl package info
  vinyl.package = util.extend(pkg, { id: id });

  return id;
}

/**
 * Transport cmd dependencies.
 * - vinyl: vinyl object
 * - required options: idleading
 */

function transportDeps(vinyl, options){
  var deps = [];
  var include = [];
  var vars = options.vars;
  var alias = options.alias;
  var paths = options.paths;
  var pkg = vinyl.package || {};

  // replace require and collect dependencies
  vinyl.contents = new Buffer(udeps(vinyl.contents.toString(), function (id, flag){
    // parse id form alias, paths, vars
    id = util.parseAlias(id, alias);
    id = util.parsePaths(id, paths);
    id = util.parseAlias(id, alias);
    id = util.parseVars(id, vars);
    id = util.parseAlias(id, alias);

    // id is not a local file
    if (!util.isLocal(id)) {
      // cache dependencie id
      deps.push(id);

      return id;
    }

    var path;

    // normalize id
    id = util.normalize(id);

    // if end with /, find index file
    if (id.substring(id.length - 1) === '/') {
      id += 'index';
    }

    // debug
    debug('transport%s deps: %s', flag ? ' ' + flag : '', colors.data(id));

    // add extname
    path = util.addExt(id);
    // rename id
    id = rename(path, options.rename);
    // hide extname
    id = util.hideExt(id);

    // seajs has hacked css before 3.0.0
    // https://github.com/seajs/seajs/blob/2.2.1/src/util-path.js#L49
    // demo https://github.com/popomore/seajs-test/tree/master/css-deps
    if (extname(id) === '.css') {
      id += '.js';
    }

    // normalize id
    id = util.normalize(id);

    // cache dependencie id and path
    if (flag === null) {
      // cache dependencie id
      deps.push(id);

      // get absolute path
      path = util.resolve(path, vinyl, options.wwwroot);

      // cache dependencie absolute path
      include.push({
        id: id,
        path: path
      });
    }

    return id;
  }, true));

  // Cache file dependencies
  vinyl.package = util.extend(pkg, {
    include: include,
    dependencies: deps
  });

  return deps;
}

/**
 * Transport css dependencies.
 * - vinyl: vinyl object
 */

function transportCssDeps(vinyl, options){
  var deps = [];
  var include = [];
  var prefix = options.prefix;
  var pkg = vinyl.package || {};

  // compute prefix
  prefix = is.fn(prefix) ? prefix(pkg.id || null, vinyl.path) : prefix;

  // replace imports and collect dependencies
  vinyl.contents = new Buffer(cdeps(vinyl.contents, function (id){
    var path;

    // id is not a local file
    if (!util.isLocal(id)) {
      // cache dependencie id
      deps.push(id);

      // keep import
      return id;
    }

    // normalize id
    id = util.normalize(id);

    var isRelative = util.isRelative(id);
    var isAbsolute = util.isAbsolute(id);

    // css import parsing rules using html
    if (!isAbsolute && !isRelative) {
      id = './' + id;
    }

    // if end with /, find index file
    if (id.substring(id.length - 1) === '/') {
      id += 'index.css';
    }

    // add extname
    path = util.addExt(id);
    // rename id
    id = rename(path, options.rename);
    // hide extname
    id = util.hideExt(id);

    // seajs has hacked css before 3.0.0
    // https://github.com/seajs/seajs/blob/2.2.1/src/util-path.js#L49
    // demo https://github.com/popomore/seajs-test/tree/master/css-deps
    if (extname(id) === '.css') {
      id += '.js';
    }

    // normalize id
    id = util.normalize(id);

    // debug
    debug('transport deps: %s', colors.data(id));

    // get absolute path
    path = util.resolve(path, vinyl, options.wwwroot);

    // cache dependencie id
    deps.push(id);
    // cache dependencie absolute path
    include.push({
      id: id,
      path: path
    });

    // delete all import
    return false;
  }, options.oncsspath, prefix));

  // Cache file dependencies
  vinyl.package = util.extend(pkg, {
    include: include,
    dependencies: deps
  });

  return deps;
}

/*
 Create a plugin
 */

function plugin(type, transport){
  return function (vinyl, options){
    // debug
    debug('read %s: %s', type, colors.data(util.pathFromCwd(vinyl.path)));

    vinyl = transport(vinyl, options);

    return vinyl;
  };
}

/**
 * resolve id leading
 * @param idleading
 * @param path
 * @param pkg
 * @returns {*}
 */

function resolveIdleading(idleading, path, pkg){
  return is.fn(idleading) ? idleading(path, pkg) : idleading;
}

/**
 * Exports module.
 */

exports.plugin = plugin;
exports.transportId = transportId;
exports.transportDeps = transportDeps;
exports.transportCssDeps = transportCssDeps;
exports.resolveIdleading = resolveIdleading;
<|endoftext|>


<commit_before>'use strict';

var OFF = 'off';
var ERROR = 'error';
var WARN = 'warn';

module.exports = {
  extends: 'eslint:recommended',
  env: {
    node: true,
  },
  globals: {
    require: false,
    module: false,
  },
  parserOptions: {
    ecmaVersion: 6,
    sourceType: 'script',
    arrowFunctions: true,
    binaryLiterals: true,
    blockBindings: true,
    classes: false,
    defaultParams: true,
    destructuring: true,
    forOf: true,
    generators: false,
    modules: false,
    objectLiteralComputedProperties: true,
    objectLiteralDuplicateProperties: true,
    objectLiteralShorthandMethods: true,
    objectLiteralShorthandProperties: true,
    octalLiterals: false,
    regexUFlag: true,
    regexYFlag: true,
    restParams: true,
    spread: true,
    superInFunctions: true,
    templateStrings: true,
    unicodeCodePointEscapes: true,
  },
  rules: {
    'accessor-pairs': [
      ERROR,
      { getWithoutSet: false, setWithoutGet: true },
    ],
    'array-bracket-spacing': [
      ERROR,
      'never',
    ],
    'arrow-parens': ERROR,
    'arrow-spacing': ERROR,
    'block-spacing': [
      ERROR,
      'always',
    ],
    'brace-style': OFF,
    'callback-return': [
      ERROR, [
        'callback',
        'cb',
        'next',
        'done',
      ],
    ],
    camelcase: OFF,
    'comma-dangle': [
      ERROR,
      'always-multiline',
    ],
    'comma-spacing': [
      ERROR,
      { before: false, after: true },
    ],
    'comma-style': [
      ERROR,
      'last',
    ],
    complexity: [
      WARN,
      5,
    ],
    'computed-property-spacing': [
      ERROR,
      'never',
    ],
    'consistent-return': ERROR,
    'consistent-this': [
      ERROR,
      '_this',
    ],
    curly: ERROR,
    'default-case': ERROR,
    'dot-location': [
      ERROR,
      'property',
    ],
    'dot-notation': ERROR,
    'eol-last': ERROR,
    eqeqeq: [
      ERROR,
      'smart',
    ],
    'func-names': WARN,
    'func-style': [
      ERROR,
      'declaration',
    ],
    'global-require': ERROR,
    'guard-for-in': ERROR,
    'handle-callback-err': ERROR,
    'id-length': OFF,
    'id-match': OFF,
    indent: [
      ERROR,
      2,
      { SwitchCase: 1 },
    ],
    'init-declarations': OFF,
    'jsx-quotes': OFF,
    'key-spacing': [
      ERROR,
      { beforeColon: false, afterColon: true },
    ],
    'linebreak-style': [
      ERROR,
      'unix',
    ],
    'lines-around-comment': OFF,
    'max-len': [
      ERROR,
      100,
      2,
    ],
    'max-nested-callbacks': [
      ERROR,
      4,
    ],
    'max-params': [
      ERROR,
      4,
    ],
    'new-cap': [
      ERROR,
      { newIsCap: true, capIsNew: true },
    ],
    'new-parens': ERROR,
    'newline-after-var': WARN,
    'no-alert': ERROR,
    'no-array-constructor': ERROR,
    'no-caller': ERROR,
    'no-catch-shadow': ERROR,
    'no-class-assign': ERROR,
    'no-cond-assign': ERROR,
    'no-console': ERROR,
    'no-const-assign': ERROR,
    'no-constant-condition': ERROR,
    'no-continue': OFF,
    'no-control-regex': ERROR,
    'no-debugger': ERROR,
    'no-delete-var': ERROR,
    'no-div-regex': ERROR,
    'no-dupe-args': ERROR,
    'no-dupe-class-members': OFF,
    'no-dupe-keys': ERROR,
    'no-duplicate-case': ERROR,
    'no-else-return': ERROR,
    'no-empty': ERROR,
    'no-empty-character-class': ERROR,
    'no-labels': ERROR,
    'no-eq-null': ERROR,
    'no-eval': ERROR,
    'no-ex-assign': ERROR,
    'no-extend-native': ERROR,
    'no-extra-bind': ERROR,
    'no-extra-boolean-cast': ERROR,
    'no-extra-parens': OFF,
    'no-extra-semi': ERROR,
    'no-fallthrough': ERROR,
    'no-floating-decimal': ERROR,
    'no-func-assign': ERROR,
    'no-implicit-coercion': OFF,
    'no-implied-eval': ERROR,
    'no-inline-comments': OFF,
    'no-inner-declarations': ERROR,
    'no-invalid-regexp': ERROR,
    'no-invalid-this': WARN,
    'no-irregular-whitespace': ERROR,
    'no-iterator': ERROR,
    'no-label-var': ERROR,
    'no-lone-blocks': ERROR,
    'no-lonely-if': ERROR,
    'no-loop-func': ERROR,
    'no-mixed-requires': OFF,
    'no-mixed-spaces-and-tabs': ERROR,
    'no-multi-spaces': ERROR,
    'no-multi-str': ERROR,
    'no-multiple-empty-lines': [
      ERROR,
      { max: 2 },
    ],
    'no-native-reassign': ERROR,
    'no-negated-condition': OFF,
    'no-negated-in-lhs': ERROR,
    'no-nested-ternary': OFF,
    'no-new': WARN,
    'no-new-func': ERROR,
    'no-new-object': ERROR,
    'no-new-require': ERROR,
    'no-obj-calls': ERROR,
    'no-octal': ERROR,
    'no-octal-escape': ERROR,
    'no-param-reassign': OFF,
    'no-path-concat': ERROR,
    'no-process-env': OFF,
    'no-process-exit': OFF,
    'no-proto': ERROR,
    'no-redeclare': ERROR,
    'no-regex-spaces': ERROR,
    'no-reserved-keys': OFF,
    'no-restricted-modules': OFF,
    'no-restricted-syntax': OFF,
    'no-return-assign': ERROR,
    'no-script-url': ERROR,
    'no-self-compare': ERROR,
    'no-sequences': ERROR,
    'no-shadow': WARN,
    'no-shadow-restricted-names': ERROR,
    'no-spaced-func': ERROR,
    'no-sparse-arrays': ERROR,
    'no-sync': OFF,
    'no-ternary': OFF,
    'no-throw-literal': ERROR,
    'no-trailing-spaces': ERROR,
    'no-undef': ERROR,
    'no-undef-init': ERROR,
    'no-undefined': ERROR,
    'no-underscore-dangle': OFF,
    'no-unexpected-multiline': ERROR,
    'no-unneeded-ternary': ERROR,
    'no-unreachable': ERROR,
    'no-unused-expressions': ERROR,
    'no-unused-vars': ERROR,
    'no-use-before-define': [
      ERROR,
      'nofunc',
    ],
    'no-useless-call': ERROR,
    'no-useless-concat': ERROR,
    'no-void': ERROR,
    'no-warning-comments': OFF,
    'no-with': ERROR,
    'object-curly-spacing': [
      ERROR,
      'always',
    ],
    'one-var': [
      ERROR,
      'never',
    ],
    'operator-assignment': [
      ERROR,
      'always',
    ],
    'operator-linebreak': [
      ERROR,
      'after',
    ],
    'padded-blocks': OFF,
    'prefer-arrow-callback': OFF,
    'prefer-reflect': OFF,
    'prefer-spread': OFF,
    'prefer-template': OFF,
    'quote-props': [
      ERROR,
      'as-needed',
    ],
    quotes: [
      ERROR,
      'single',
    ],
    radix: ERROR,
    'require-jsdoc': OFF,
    'require-yield': ERROR,
    semi: [
      ERROR,
      'always',
    ],
    'semi-spacing': [
      ERROR,
      { before: false, after: true },
    ],
    'sort-vars': OFF,
    'space-after-keywords': OFF,
    'space-before-blocks': [
      ERROR,
      'always',
    ],
    'space-before-function-paren': [
      ERROR,
      'never',
    ],
    'keyword-spacing': [
      'error',
      { before: true, after: true, overrides: {
        if: { after: false },
        for: { after: false },
        while: { after: false },
      } },
    ],
    'space-in-parens': [
      ERROR,
      'never',
    ],
    'space-infix-ops': ERROR,
    'space-unary-ops': ERROR,
    'spaced-comment': [
      ERROR,
      'always',
    ],
    'valid-jsdoc': ERROR,
    'valid-typeof': ERROR,
    'vars-on-top': ERROR,
    'wrap-iife': ERROR,
    'wrap-regex': ERROR,
    yoda: [
      ERROR,
      'always',
    ],
  },
};
<commit_msg>feat(rules): add eslint v1.7 rules<commit_after>'use strict';

var OFF = 'off';
var ERROR = 'error';
var WARN = 'warn';

module.exports = {
  extends: 'eslint:recommended',
  env: {
    node: true,
  },
  globals: {
    require: false,
    module: false,
  },
  parserOptions: {
    ecmaVersion: 6,
    sourceType: 'script',
    arrowFunctions: true,
    binaryLiterals: true,
    blockBindings: true,
    classes: false,
    defaultParams: true,
    destructuring: true,
    forOf: true,
    generators: false,
    modules: false,
    objectLiteralComputedProperties: true,
    objectLiteralDuplicateProperties: true,
    objectLiteralShorthandMethods: true,
    objectLiteralShorthandProperties: true,
    octalLiterals: false,
    regexUFlag: true,
    regexYFlag: true,
    restParams: true,
    spread: true,
    superInFunctions: true,
    templateStrings: true,
    unicodeCodePointEscapes: true,
  },
  rules: {
    'accessor-pairs': [
      ERROR,
      { getWithoutSet: false, setWithoutGet: true },
    ],
    'array-bracket-spacing': [
      ERROR,
      'never',
    ],
    'arrow-parens': ERROR,
    'arrow-spacing': ERROR,
    'block-spacing': [
      ERROR,
      'always',
    ],
    'brace-style': OFF,
    'callback-return': [
      ERROR, [
        'callback',
        'cb',
        'next',
        'done',
      ],
    ],
    camelcase: OFF,
    'comma-dangle': [
      ERROR,
      'always-multiline',
    ],
    'comma-spacing': [
      ERROR,
      { before: false, after: true },
    ],
    'comma-style': [
      ERROR,
      'last',
    ],
    complexity: [
      WARN,
      5,
    ],
    'computed-property-spacing': [
      ERROR,
      'never',
    ],
    'consistent-return': ERROR,
    'consistent-this': [
      ERROR,
      '_this',
    ],
    curly: ERROR,
    'default-case': ERROR,
    'dot-location': [
      ERROR,
      'property',
    ],
    'dot-notation': ERROR,
    'eol-last': ERROR,
    eqeqeq: [
      ERROR,
      'smart',
    ],
    'func-names': WARN,
    'func-style': [
      ERROR,
      'declaration',
    ],
    'global-require': ERROR,
    'guard-for-in': ERROR,
    'handle-callback-err': ERROR,
    'id-length': OFF,
    'id-match': OFF,
    indent: [
      ERROR,
      2,
      { SwitchCase: 1 },
    ],
    'init-declarations': OFF,
    'jsx-quotes': OFF,
    'key-spacing': [
      ERROR,
      { beforeColon: false, afterColon: true },
    ],
    'linebreak-style': [
      ERROR,
      'unix',
    ],
    'lines-around-comment': OFF,
    'max-len': [
      ERROR,
      100,
      2,
    ],
    'max-nested-callbacks': [
      ERROR,
      4,
    ],
    'max-params': [
      ERROR,
      4,
    ],
    'new-cap': [
      ERROR,
      { newIsCap: true, capIsNew: true },
    ],
    'new-parens': ERROR,
    'newline-after-var': WARN,
    'no-alert': ERROR,
    'no-array-constructor': ERROR,
    'no-caller': ERROR,
    'no-catch-shadow': ERROR,
    'no-class-assign': ERROR,
    'no-cond-assign': ERROR,
    'no-console': ERROR,
    'no-const-assign': ERROR,
    'no-constant-condition': ERROR,
    'no-continue': OFF,
    'no-control-regex': ERROR,
    'no-debugger': ERROR,
    'no-delete-var': ERROR,
    'no-div-regex': ERROR,
    'no-dupe-args': ERROR,
    'no-dupe-class-members': OFF,
    'no-dupe-keys': ERROR,
    'no-duplicate-case': ERROR,
    'no-else-return': ERROR,
    'no-empty': ERROR,
    'no-empty-character-class': ERROR,
    'no-empty-pattern': ERROR,
    'no-labels': ERROR,
    'no-eq-null': ERROR,
    'no-eval': ERROR,
    'no-ex-assign': ERROR,
    'no-extend-native': ERROR,
    'no-extra-bind': ERROR,
    'no-extra-boolean-cast': ERROR,
    'no-extra-parens': OFF,
    'no-extra-semi': ERROR,
    'no-fallthrough': ERROR,
    'no-floating-decimal': ERROR,
    'no-func-assign': ERROR,
    'no-implicit-coercion': OFF,
    'no-implied-eval': ERROR,
    'no-inline-comments': OFF,
    'no-inner-declarations': ERROR,
    'no-invalid-regexp': ERROR,
    'no-invalid-this': WARN,
    'no-irregular-whitespace': ERROR,
    'no-iterator': ERROR,
    'no-label-var': ERROR,
    'no-lone-blocks': ERROR,
    'no-lonely-if': ERROR,
    'no-loop-func': ERROR,
    'no-magic-numbers': OFF,
    'no-mixed-requires': OFF,
    'no-mixed-spaces-and-tabs': ERROR,
    'no-multi-spaces': ERROR,
    'no-multi-str': ERROR,
    'no-multiple-empty-lines': [
      ERROR,
      { max: 2 },
    ],
    'no-native-reassign': ERROR,
    'no-negated-condition': OFF,
    'no-negated-in-lhs': ERROR,
    'no-nested-ternary': OFF,
    'no-new': WARN,
    'no-new-func': ERROR,
    'no-new-object': ERROR,
    'no-new-require': ERROR,
    'no-obj-calls': ERROR,
    'no-octal': ERROR,
    'no-octal-escape': ERROR,
    'no-param-reassign': OFF,
    'no-path-concat': ERROR,
    'no-process-env': OFF,
    'no-process-exit': OFF,
    'no-proto': ERROR,
    'no-redeclare': ERROR,
    'no-regex-spaces': ERROR,
    'no-reserved-keys': OFF,
    'no-restricted-modules': OFF,
    'no-restricted-syntax': OFF,
    'no-return-assign': ERROR,
    'no-script-url': ERROR,
    'no-self-compare': ERROR,
    'no-sequences': ERROR,
    'no-shadow': WARN,
    'no-shadow-restricted-names': ERROR,
    'no-spaced-func': ERROR,
    'no-sparse-arrays': ERROR,
    'no-sync': OFF,
    'no-ternary': OFF,
    'no-throw-literal': ERROR,
    'no-trailing-spaces': ERROR,
    'no-undef': ERROR,
    'no-undef-init': ERROR,
    'no-undefined': ERROR,
    'no-underscore-dangle': OFF,
    'no-unexpected-multiline': ERROR,
    'no-unneeded-ternary': ERROR,
    'no-unreachable': ERROR,
    'no-unused-expressions': ERROR,
    'no-unused-vars': ERROR,
    'no-use-before-define': [
      ERROR,
      'nofunc',
    ],
    'no-useless-call': ERROR,
    'no-useless-concat': ERROR,
    'no-void': ERROR,
    'no-warning-comments': OFF,
    'no-with': ERROR,
    'object-curly-spacing': [
      ERROR,
      'always',
    ],
    'one-var': [
      ERROR,
      'never',
    ],
    'operator-assignment': [
      ERROR,
      'always',
    ],
    'operator-linebreak': [
      ERROR,
      'after',
    ],
    'padded-blocks': OFF,
    'prefer-arrow-callback': OFF,
    'prefer-reflect': OFF,
    'prefer-spread': OFF,
    'prefer-template': OFF,
    'quote-props': [
      ERROR,
      'as-needed',
    ],
    quotes: [
      ERROR,
      'single',
    ],
    radix: ERROR,
    'require-jsdoc': OFF,
    'require-yield': ERROR,
    semi: [
      ERROR,
      'always',
    ],
    'semi-spacing': [
      ERROR,
      { before: false, after: true },
    ],
    'sort-vars': OFF,
    'space-after-keywords': OFF,
    'space-before-blocks': [
      ERROR,
      'always',
    ],
    'space-before-function-paren': [
      ERROR,
      'never',
    ],
    'keyword-spacing': [
      'error',
      { before: true, after: true, overrides: {
        if: { after: false },
        for: { after: false },
        while: { after: false },
      } },
    ],
    'space-in-parens': [
      ERROR,
      'never',
    ],
    'space-infix-ops': ERROR,
    'space-unary-ops': ERROR,
    'spaced-comment': [
      ERROR,
      'always',
    ],
    'valid-jsdoc': ERROR,
    'valid-typeof': ERROR,
    'vars-on-top': ERROR,
    'wrap-iife': ERROR,
    'wrap-regex': ERROR,
    yoda: [
      ERROR,
      'always',
    ],
  },
};
<|endoftext|>


<commit_before>/* NEW BSD LICENSE {{{
Copyright (c) 2009, anekos.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. The names of the authors may not be used to endorse or promote products
       derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

###################################################################################
# http://sourceforge.jp/projects/opensource/wiki/licenses%2Fnew_BSD_license       #
# に参考になる日本語訳がありますが、有効なのは上記英文となります。                #
###################################################################################

}}} */

// PLUGIN_INFO {{{
let PLUGIN_INFO =
<VimperatorPlugin>
  <name>Auto focus frame</name>
  <description>Automatically focus to largest frame.</description>
  <description lang="ja">最も大きなフレームに自動的にフォーカスする。</description>
  <version>1.0.10</version>
  <author mail="anekos@snca.net" homepage="http://d.hatena.ne.jp/nokturnalmortum/">anekos</author>
  <license>new BSD License (Please read the source code comments of this plugin)</license>
  <license lang="ja">修正BSDライセンス (ソースコードのコメントを参照してください)</license>
  <updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/auto-focus-frame.js</updateURL>
  <minVersion>2.3pre</minVersion>
  <maxVersion>2.3pre</maxVersion>
  <detail><![CDATA[
    == Usage ==
      Only install.
  ]]></detail>
  <detail lang="ja"><![CDATA[
    == Usage ==
      インストールするだけ
      一番面積の大きいフレームをフォーカスします
  ]]></detail>
</VimperatorPlugin>;
// }}}

(function () {

  function onLoad () {
    if (!(window.content.document instanceof HTMLDocument) || (content.frames.length <= 1))
      return;

    let targetFrames = [
      frame
      for (frame in util.Array.itervalues(content.frames))
      if (frame.frameElement instanceof HTMLFrameElement)
    ];

    let [maxSize, maxFrame] = [-1, null];
    targetFrames.forEach(function(frame) {
      if (frame.scrollMaxX <= 0 && frame.scrollMaxY <= 0)
        return;
      let size = frame.innerWidth * frame.innerHeight;
      if (maxSize < size)
        [maxSize, maxFrame] = [size, frame];
    });
    if (maxFrame)
      maxFrame.focus();
  }

  getBrowser().addEventListener("DOMContentLoaded", onLoad, true);

})();

// vim:sw=2 ts=2 et si fdm=marker:
<commit_msg>pentadactyl: Fix case for util.Array.iterValues<commit_after>/* NEW BSD LICENSE {{{
Copyright (c) 2009, anekos.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. The names of the authors may not be used to endorse or promote products
       derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

###################################################################################
# http://sourceforge.jp/projects/opensource/wiki/licenses%2Fnew_BSD_license       #
# に参考になる日本語訳がありますが、有効なのは上記英文となります。                #
###################################################################################

}}} */

// PLUGIN_INFO {{{
let PLUGIN_INFO =
<VimperatorPlugin>
  <name>Auto focus frame</name>
  <description>Automatically focus to largest frame.</description>
  <description lang="ja">最も大きなフレームに自動的にフォーカスする。</description>
  <version>1.0.10</version>
  <author mail="anekos@snca.net" homepage="http://d.hatena.ne.jp/nokturnalmortum/">anekos</author>
  <license>new BSD License (Please read the source code comments of this plugin)</license>
  <license lang="ja">修正BSDライセンス (ソースコードのコメントを参照してください)</license>
  <updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/auto-focus-frame.js</updateURL>
  <minVersion>2.3pre</minVersion>
  <maxVersion>2.3pre</maxVersion>
  <detail><![CDATA[
    == Usage ==
      Only install.
  ]]></detail>
  <detail lang="ja"><![CDATA[
    == Usage ==
      インストールするだけ
      一番面積の大きいフレームをフォーカスします
  ]]></detail>
</VimperatorPlugin>;
// }}}

(function () {

  function onLoad () {
    if (!(window.content.document instanceof HTMLDocument) || (content.frames.length <= 1))
      return;

    let targetFrames = [
      frame
      for (frame in util.Array.iterValues(content.frames))
      if (frame.frameElement instanceof HTMLFrameElement)
    ];

    let [maxSize, maxFrame] = [-1, null];
    targetFrames.forEach(function(frame) {
      if (frame.scrollMaxX <= 0 && frame.scrollMaxY <= 0)
        return;
      let size = frame.innerWidth * frame.innerHeight;
      if (maxSize < size)
        [maxSize, maxFrame] = [size, frame];
    });
    if (maxFrame)
      maxFrame.focus();
  }

  getBrowser().addEventListener("DOMContentLoaded", onLoad, true);

})();

// vim:sw=2 ts=2 et si fdm=marker:
<|endoftext|>


<commit_before>var path = require("path")
var home = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']
var npmbrew = path.join(home, ".npmbrew")

module.exports = {
  url : "http://registry.npmjs.org/npm/",
  pkg : require(path.join(__dirname, "../package.json")),
  dirname : {
    current : path.join(npmbrew, "current"),
    src : path.join(npmbrew, "src"),
    npm : path.join(npmbrew, "npm")
  }
}
<commit_msg>Add env check for test<commit_after>var path = require("path")
var home = process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']
var env = process.env.NODE_ENV || "production"
var dirname = (env === "development")
        ? path.join(__dirname, "../")
        : path.join(home, ".npmbrew")

module.exports = {
  env : env,
  url : "http://registry.npmjs.org/npm/",
  pkg : require(path.join(__dirname, "../package.json")),
  dirname : {
    current : path.join(dirname, "current"),
    src : path.join(dirname, "src"),
    npm : path.join(dirname, "npm")
  }
}

console.log(env)
<|endoftext|>