<commit_before>/**
 * Recursively encode an object as application/x-www-form-urlencoded.
 *
 * @param value Value to encode
 * @param key Key to encode (not required for top-level objects)
 * @return Encoded object
 */
var serialize = module.exports.serialize = function (value, key) {

	var output;

	if (!key && key !== 0)
		key = '';

    if (Array.isArray(value)) {
        output = [];
        value.forEach(function(val, index) {
            if (key != '') index = key + '[' + index + ']';
            output.push(serialize(val, index));
        }, this);
        return output.join('&');
    } else if (typeof(value) == 'object') {
        output = [];
        for (var name in value) {
            if (value[name] && value.hasOwnProperty(name)) {
                output.push(serialize(value[name], key != '' ? key + '[' + name + ']' : name));
            }
        }
        return output.join('&');
    } else {
        return key + '=' + encodeURIComponent(value);
    }

}

/**
 * Creates an Error with information received from MailChimp. In addition to an
 * error message it also includes an error code. A detailed list of known error
 * messages and codes can be found at the url below for version 1.3 of the API.
 *
 * @see http://apidocs.mailchimp.com/api/1.3/exceptions.field.php
 *
 * @param message The error message
 * @param code The error code
 * @return Instance of {@link Error}
 */
var createMailChimpError = module.exports.createMailChimpError = function (message, code) {

	error = new Error(message || (message = ''));

	if (code)
		error.code = code;

	return error;

}<commit_msg>Update helpers.js<commit_after>/**
 * Recursively encode an object as application/x-www-form-urlencoded.
 *
 * @param value Value to encode
 * @param key Key to encode (not required for top-level objects)
 * @return Encoded object
 */
var serialize = module.exports.serialize = function (value, key) {

	var output;

	if (!key && key !== 0)
		key = '';

    if (Array.isArray(value)) {
        output = [];
        value.forEach(function(val, index) {
            if (key != '') index = key + '[' + index + ']';
            output.push(serialize(val, index));
        }, this);
        return output.join('&');
    } else if (typeof(value) == 'object') {
        output = [];
        for (var name in value) {
            if (value[name] && value.hasOwnProperty(name)) {
                output.push(serialize(value[name], key != '' ? key + '[' + name + ']' : name));
            }
        }
        return output.join('&');
    } else {
        return key + '=' + encodeURIComponent(value);
    }

}

/**
 * Creates an Error with information received from MailChimp. In addition to an
 * error message it also includes an error code. A detailed list of known error
 * messages and codes can be found at the url below for version 1.3 of the API.
 *
 * @see http://apidocs.mailchimp.com/api/1.3/exceptions.field.php
 *
 * @param message The error message
 * @param code The error code
 * @return Instance of {@link Error}
 */
var createMailChimpError = module.exports.createMailChimpError = function (message, code) {

	var error = new Error(message || (message = ''));

	if (code)
		error.code = code;

	return error;

}
<|endoftext|>


<commit_before>'use strict';

function makeLexerState() {
    return {
        lineNumber :    0,
        charsRead  :    0, // all characters read, excluding the current line
        line       :   "",
        linePos    :    0,
        sym        : null,
        text       :   "",
        startCoord : null,
        set        : function (sym, text) {
            this.sym  = sym;
            this.text = text;
        }
    }
}

function cloneLexerState(old) {
    return {
        lineNumber : old.lineNumber,
        charsRead  : old.charsRead, // all characters read, excluding the current line
        line       : old.line,
        linePos    : old.linePos,
        sym        : old.sym,
        text       : old.text,
        startCoord : old.startCoord,
        set        : function (sym, text) {
            this.sym  = sym;
            this.text = text;
        }
    }
}

function Lexer(fileContent) {
    var SEPARATOR = "----",
        PRIMITIVE = "primitive",
        peekDone  = false,
        state     = makeLexerState(),
        stateAfterPeek = null,
        fileLines = fileContent.split('\n'),
        _this = this;

    function makeSourceCoordinate() {
        var startLine   = state.lineNumber,
            startColumn = state.linePos + 1,
            charIndex   = state.charsRead + state.linePos;

        return {
            get startLine()   { return startLine;   },
            get startColumn() { return startColumn; },
            get charIndex()   { return charIndex;   },
            toString: function() {
                return "SrcCoord(line: " + startLine + ", col: " + startColumn + ")";
            }
        };
    }

    this.getStartCoordinate = function () {
        return state.startCoord;
    };

    this.getSym = function () {
        if (peekDone) {
            peekDone = false;
            state = stateAfterPeek;
            stateAfterPeek = null;
            return state.sym;
        }

        state.startCoord = makeSourceCoordinate();

        do {
            if (!hasMoreInput()) {
                state.set(Sym.NONE, "");
                return state.sym;
            }
            skipWhiteSpace();
            skipComment();
        }
        while (endOfLine() || /\s/.test(currentChar())
            || currentChar() == '"');

        if (currentChar() == '\'') {
            lexString();
        } else if (currentChar() == '[') {
            match(Sym.NewBlock);
        } else if (currentChar() == ']') {
            match(Sym.EndBlock);
        } else if (currentChar() == ':') {
            if (bufchar(state.linePos + 1) == '=') {
                state.linePos += 2;
                state.set(Sym.Assign, ":=");
            } else {
                state.linePos++;
                state.set(Sym.Colon, ":");
            }
        } else if (currentChar() == '(') {
            match(Sym.NewTerm);
        } else if (currentChar() == ')') {
            match(Sym.EndTerm);
        } else if (currentChar() == '#') {
            match(Sym.Pound);
        } else if (currentChar() == '^') {
            match(Sym.Exit);
        } else if (currentChar() == '.') {
            match(Sym.Period);
        } else if (currentChar() == '-') {
            if (state.line.indexOf(SEPARATOR, state.linePos) == 0) {
                state.text = "";
                while (currentChar() == '-') {
                    state.text += bufchar(state.linePos++);
                }
                state.sym = Sym.Separator;
            } else {
                state.linePos++;
                state.set(Sym.Minus, "-");
            }
        } else if (isOperator(currentChar())) {
            lexOperator();
        } else if (nextWordInBufferIs(PRIMITIVE)) {
            state.linePos += PRIMITIVE.length;
            state.set(Sym.Primitive, PRIMITIVE);
        } else if (/[A-Za-z]/.test(currentChar())) {
            state.set(Sym.Identifier, "");
            while (isIdentifierChar(currentChar())) {
                state.text += bufchar(state.linePos++);
            }
            if (bufchar(state.linePos) == ':') {
                state.sym = Sym.Keyword;
                state.linePos++;
                state.text += ':';
                if (/[A-Za-z]/.test(currentChar())) {
                    state.sym = Sym.KeywordSequence;
                    while (/[A-Za-z]/.test(currentChar()) || currentChar() == ':') {
                        state.text += bufchar(state.linePos++);
                    }
                }
            }
        } else if (/\d/.test(currentChar())) {
            lexNumber();
        } else {
            state.set(Sym.NONE, currentChar());
        }

        return state.sym;
    };

    function lexNumber() {
        state.set(Sym.Integer, "");

        var sawDecimalMark = false;

        do {
            state.text += bufchar(state.linePos++);

            if (!sawDecimalMark      &&
                '.' == currentChar() &&
                /\d/.test(bufchar(state.linePos + 1))) {
                state.sym = Sym.Double;
                state.text += bufchar(state.linePos++);
            }
        } while (/\d/.test(currentChar()));
    }

    function lexString() {
        state.set(Sym.STString, "");

        do {
            state.text += bufchar(++state.linePos);
        }
        while (currentChar() != '\'');

        state.text = state.text.slice(0, -1);
        state.linePos++;
    }

    function lexOperator() {
        if (isOperator(bufchar(state.linePos + 1))) {
            state.set(Sym.OperatorSequence, "");
            while (isOperator(currentChar())) {
                state.text += bufchar(state.linePos++);
            }
        } else if (currentChar() == '~') {
            match(Sym.Not);
        } else if (currentChar() == '&') {
            match(Sym.And);
        } else if (currentChar() == '|') {
            match(Sym.Or);
        } else if (currentChar() == '*') {
            match(Sym.Star);
        } else if (currentChar() == '/') {
            match(Sym.Div);
        } else if (currentChar() == '\\') {
            match(Sym.Mod);
        } else if (currentChar() == '+') {
            match(Sym.Plus);
        } else if (currentChar() == '=') {
            match(Sym.Equal);
        } else if (currentChar() == '>') {
            match(Sym.More);
        } else if (currentChar() == '<') {
            match(Sym.Less);
        } else if (currentChar() == ',') {
            match(Sym.Comma);
        } else if (currentChar() == '@') {
            match(Sym.At);
        } else if (currentChar() == '%') {
            match(Sym.Per);
        }
    }

    this.peek = function () {
        var old = cloneLexerState(state);
        if (peekDone) {
            throw new IllegalStateException("SOM lexer: cannot peek twice!");
        }
        _this.getSym();
        var nextSym = state.sym;
        stateAfterPeek = state;
        state = old;

        peekDone = true;
        return nextSym;
    };

    this.getText = function () {
        return state.text;
    };

    this.getNextText = function () {
        return stateAfterPeek.text;
    };

    this.getLine = function () {
        return state.line;
    };

    this.getCurrentLineNumber = function () {
        return state.lineNumber;
    };

    this.getCurrentColumn = function () {
        return state.linePos + 1;
    };

    // All characters read and processed, including current line
    this.getNumberOfCharactersRead = function () {
        return state.startCoord.charIndex;
    };

    function readNextLine() {
        if (state.lineNumber >= fileLines.length) { return false; }

        var charCntOldLine = state.line.length;
        if (state.lineNumber > 0) { charCntOldLine++; } // add +1 for line break
        state.line = fileLines[state.lineNumber];
        state.charsRead = charCntOldLine;
        state.lineNumber++;
        state.linePos = 0;
        return true;
    }

    function hasMoreInput() {
        while (endOfLine()) {
            if (!readNextLine()) {
                return false;
            }
        }
        return true;
    }

    function skipWhiteSpace() {
        while (/\s/.test(currentChar())) {
            state.linePos++;
            while (endOfLine()) {
                if (!readNextLine()) {
                    return;
                }
            }
        }
    }

    function skipComment() {
        if (currentChar() == '"') {
            do {
                state.linePos++;
                while (endOfLine()) {
                    if (!readNextLine()) { return; }
                }
            } while (currentChar() != '"');
            state.linePos++;
        }
    }

    function currentChar() {
        return bufchar(state.linePos);
    }

    function endOfLine() {
        return state.linePos >= state.line.length;
    }

    function isOperator(c) {
        return c == '~'  || c == '&' || c == '|' || c == '*' || c == '/'
            || c == '\\' || c == '+' || c == '=' || c == '>' || c == '<'
            || c == ','  || c == '@' || c == '%';
    }

    function match(s) {
        state.set(s, currentChar());
        state.linePos++;
    }

    function bufchar(p) {
        return p >= state.line.length ? '\0' : state.line.charAt(p);
    }

    function isIdentifierChar(c) {
        return /[A-Za-z\d]/.test(c) || c == '_';
    }

    function nextWordInBufferIs(text) {
        if (state.line.indexOf(text, state.linePos) != 0) {
            return false;
        }
        return !isIdentifierChar(bufchar(state.linePos + text.length));
    }
}
<commit_msg>Fix broken condition<commit_after>'use strict';

function makeLexerState() {
    return {
        lineNumber :    0,
        charsRead  :    0, // all characters read, excluding the current line
        line       :   "",
        linePos    :    0,
        sym        : null,
        text       :   "",
        startCoord : null,
        set        : function (sym, text) {
            this.sym  = sym;
            this.text = text;
        }
    }
}

function cloneLexerState(old) {
    return {
        lineNumber : old.lineNumber,
        charsRead  : old.charsRead, // all characters read, excluding the current line
        line       : old.line,
        linePos    : old.linePos,
        sym        : old.sym,
        text       : old.text,
        startCoord : old.startCoord,
        set        : function (sym, text) {
            this.sym  = sym;
            this.text = text;
        }
    }
}

function Lexer(fileContent) {
    var SEPARATOR = "----",
        PRIMITIVE = "primitive",
        peekDone  = false,
        state     = makeLexerState(),
        stateAfterPeek = null,
        fileLines = fileContent.split('\n'),
        _this = this;

    function makeSourceCoordinate() {
        var startLine   = state.lineNumber,
            startColumn = state.linePos + 1,
            charIndex   = state.charsRead + state.linePos;

        return {
            get startLine()   { return startLine;   },
            get startColumn() { return startColumn; },
            get charIndex()   { return charIndex;   },
            toString: function() {
                return "SrcCoord(line: " + startLine + ", col: " + startColumn + ")";
            }
        };
    }

    this.getStartCoordinate = function () {
        return state.startCoord;
    };

    this.getSym = function () {
        if (peekDone) {
            peekDone = false;
            state = stateAfterPeek;
            stateAfterPeek = null;
            return state.sym;
        }

        state.startCoord = makeSourceCoordinate();

        do {
            if (!hasMoreInput()) {
                state.set(Sym.NONE, "");
                return state.sym;
            }
            skipWhiteSpace();
            skipComment();
        }
        while (endOfLine() || /\s/.test(currentChar())
            || currentChar() == '"');

        if (currentChar() == '\'') {
            lexString();
        } else if (currentChar() == '[') {
            match(Sym.NewBlock);
        } else if (currentChar() == ']') {
            match(Sym.EndBlock);
        } else if (currentChar() == ':') {
            if (bufchar(state.linePos + 1) == '=') {
                state.linePos += 2;
                state.set(Sym.Assign, ":=");
            } else {
                state.linePos++;
                state.set(Sym.Colon, ":");
            }
        } else if (currentChar() == '(') {
            match(Sym.NewTerm);
        } else if (currentChar() == ')') {
            match(Sym.EndTerm);
        } else if (currentChar() == '#') {
            match(Sym.Pound);
        } else if (currentChar() == '^') {
            match(Sym.Exit);
        } else if (currentChar() == '.') {
            match(Sym.Period);
        } else if (currentChar() == '-') {
            if (state.line.indexOf(SEPARATOR, state.linePos) == 0) {
                state.text = "";
                while (currentChar() == '-') {
                    state.text += bufchar(state.linePos++);
                }
                state.sym = Sym.Separator;
            } else {
                state.linePos++;
                state.set(Sym.Minus, "-");
            }
        } else if (isOperator(currentChar())) {
            lexOperator();
        } else if (nextWordInBufferIs(PRIMITIVE)) {
            state.linePos += PRIMITIVE.length;
            state.set(Sym.Primitive, PRIMITIVE);
        } else if (/[A-Za-z]/.test(currentChar())) {
            state.set(Sym.Identifier, "");
            while (isIdentifierChar(currentChar())) {
                state.text += bufchar(state.linePos++);
            }
            if (bufchar(state.linePos) == ':') {
                state.sym = Sym.Keyword;
                state.linePos++;
                state.text += ':';
                if (/[A-Za-z]/.test(currentChar())) {
                    state.sym = Sym.KeywordSequence;
                    while (/[A-Za-z]/.test(currentChar()) || currentChar() == ':') {
                        state.text += bufchar(state.linePos++);
                    }
                }
            }
        } else if (/\d/.test(currentChar())) {
            lexNumber();
        } else {
            state.set(Sym.NONE, currentChar());
        }

        return state.sym;
    };

    function lexNumber() {
        state.set(Sym.Integer, "");

        var sawDecimalMark = false;

        do {
            state.text += bufchar(state.linePos++);

            if (!sawDecimalMark      &&
                '.' == currentChar() &&
                /\d/.test(bufchar(state.linePos + 1))) {
                state.sym = Sym.Double;
                state.text += bufchar(state.linePos++);
            }
        } while (/\d/.test(currentChar()));
    }

    function lexString() {
        state.set(Sym.STString, "");

        do {
            state.text += bufchar(++state.linePos);
        }
        while (currentChar() != '\'');

        state.text = state.text.slice(0, -1);
        state.linePos++;
    }

    function lexOperator() {
        if (isOperator(bufchar(state.linePos + 1))) {
            state.set(Sym.OperatorSequence, "");
            while (isOperator(currentChar())) {
                state.text += bufchar(state.linePos++);
            }
        } else if (currentChar() == '~') {
            match(Sym.Not);
        } else if (currentChar() == '&') {
            match(Sym.And);
        } else if (currentChar() == '|') {
            match(Sym.Or);
        } else if (currentChar() == '*') {
            match(Sym.Star);
        } else if (currentChar() == '/') {
            match(Sym.Div);
        } else if (currentChar() == '\\') {
            match(Sym.Mod);
        } else if (currentChar() == '+') {
            match(Sym.Plus);
        } else if (currentChar() == '=') {
            match(Sym.Equal);
        } else if (currentChar() == '>') {
            match(Sym.More);
        } else if (currentChar() == '<') {
            match(Sym.Less);
        } else if (currentChar() == ',') {
            match(Sym.Comma);
        } else if (currentChar() == '@') {
            match(Sym.At);
        } else if (currentChar() == '%') {
            match(Sym.Per);
        }
    }

    this.peek = function () {
        var old = cloneLexerState(state);
        if (peekDone) {
            throw new IllegalStateException("SOM lexer: cannot peek twice!");
        }
        _this.getSym();
        var nextSym = state.sym;
        stateAfterPeek = state;
        state = old;

        peekDone = true;
        return nextSym;
    };

    this.getText = function () {
        return state.text;
    };

    this.getNextText = function () {
        return stateAfterPeek.text;
    };

    this.getLine = function () {
        return state.line;
    };

    this.getCurrentLineNumber = function () {
        return state.lineNumber;
    };

    this.getCurrentColumn = function () {
        return state.linePos + 1;
    };

    // All characters read and processed, including current line
    this.getNumberOfCharactersRead = function () {
        return state.startCoord.charIndex;
    };

    function readNextLine() {
        if (state.lineNumber >= fileLines.length) { return false; }

        var charCntOldLine = state.line.length;
        if (state.lineNumber > 0) { charCntOldLine++; } // add +1 for line break
        state.line = fileLines[state.lineNumber];
        state.charsRead = charCntOldLine;
        state.lineNumber++;
        state.linePos = 0;
        return true;
    }

    function hasMoreInput() {
        while (endOfLine()) {
            if (!readNextLine()) {
                return false;
            }
        }
        return true;
    }

    function skipWhiteSpace() {
        while (/\s/.test(currentChar())) {
            state.linePos++;
            while (endOfLine()) {
                if (!readNextLine()) {
                    return;
                }
            }
        }
    }

    function skipComment() {
        if (currentChar() == '"') {
            do {
                state.linePos++;
                while (endOfLine()) {
                    if (!readNextLine()) { return; }
                }
            } while (currentChar() != '"');
            state.linePos++;
        }
    }

    function currentChar() {
        return bufchar(state.linePos);
    }

    function endOfLine() {
        return state.linePos >= state.line.length;
    }

    function isOperator(c) {
        return c == '~'  || c == '&' || c == '|' || c == '*' || c == '/'
            || c == '\\' || c == '+' || c == '=' || c == '>' || c == '<'
            || c == ','  || c == '@' || c == '%';
    }

    function match(s) {
        state.set(s, currentChar());
        state.linePos++;
    }

    function bufchar(p) {
        return p >= state.line.length ? '\0' : state.line.charAt(p);
    }

    function isIdentifierChar(c) {
        return /[A-Za-z\d]/.test(c) || c == '_';
    }

    function nextWordInBufferIs(text) {
        if (state.line.indexOf(text, state.linePos) != state.linePos) {
            return false;
        }
        return !isIdentifierChar(bufchar(state.linePos + text.length));
    }
}
<|endoftext|>


<commit_before>import { File } from "./file";
import { diffVersion } from "./util";
import deepExtend from "deep-extend";

const yaml = require("js-yaml");

function difference(a, b) {
  return new Set([...a].filter(x => !b.has(x)));
}

const scriptSlots = [
  "before_install",
  "install",
  "before_script",
  "script",
  "before_cache",
  "after_success",
  "after_failure",
  "before_deploy",
  "deploy",
  "after_deploy",
  "after_script"
];

const deletableSlots = ["notifications.email"];

export class Travis extends File {
  static matchesFileName(name) {
    return name === ".travis.yml";
  }

  async mergeContent(context, original, template) {
    const ymlOptions = { schema: yaml.FAILSAFE_SCHEMA };

    const yml = yaml.safeLoad(original, ymlOptions) || {};
    const tyml = yaml.safeLoad(context.expand(template), ymlOptions);

    const savedScripts = scriptSlots.reduce((a, c) => {
      a[c] = yml[c];
      return a;
    }, {});

    const messages = [];

    const oldVersions = new Set(
      yml.node_js ? [...yml.node_js.map(s => String(s))] : []
    );
    const templateVersions = new Set(
      tyml.node_js ? [...tyml.node_js.map(s => String(s))] : []
    );
    const versions = new Set([...oldVersions, ...templateVersions]);
    const newVersions = new Set(versions);

    versions.forEach(v => {
      if (v.startsWith("-")) {
        const d = v.replace(/^\-\s*/, "");

        versions.forEach(v => {
          const x = v.replace(/^\-\s*/, "");
          //console.log(`${d}<>${v} => ${diffVersion(d, x) === 0 || x != v}`);
          if (diffVersion(d, x) === 0 || x != v) {
            if (templateVersions.has(x)) {
              return;
            }

            newVersions.delete(x);
            newVersions.delete(v);
          }
        });
      }
    });

    const r = difference(oldVersions, newVersions);
    if (r.size > 0) {
      messages.push(
        `chore(travis): remove node versions ${Array.from(new Set(r)).sort()}`
      );
    }

    const a = difference(newVersions, oldVersions);
    if (a.size > 0) {
      messages.push(
        `chore(travis): add node versions ${Array.from(new Set(a)).sort()}`
      );
    }

    deepExtend(yml, tyml);

    if (newVersions.size > 0) {
      yml.node_js = Array.from(new Set(newVersions))
        .sort()
        .map(s => (String(parseFloat(s)) == s ? parseFloat(s) : s));
    }

    scriptSlots.forEach(scriptName => {
      const cs = savedScripts[scriptName];

      if (cs != undefined) {
        cs.forEach(s => {
          if (!yml[scriptName].find(e => e === s)) {
            yml[scriptName].push(s);
          }
        });
      }

      if (yml[scriptName]) {
        yml[scriptName] = yml[scriptName].filter(
          s =>
            !tyml[scriptName].find(e => e === `-${s}`) && s.indexOf("-") !== 0
        );
      }
    });

    const content = yaml.safeDump(yml, {
      lineWidth: 128
    });

    if (messages.length === 0) {
      messages.push(`chore(travis): merge from template ${this.path}`);
    }

    return {
      content,
      changed: content !== original,
      messages
    };
  }
}
<commit_msg>fix(travis): do not insert to be removed entries<commit_after>import { File } from "./file";
import { diffVersion } from "./util";
import deepExtend from "deep-extend";

const yaml = require("js-yaml");

function difference(a, b) {
  return new Set([...a].filter(x => !b.has(x)));
}

const scriptSlots = [
  "before_install",
  "install",
  "before_script",
  "script",
  "before_cache",
  "after_success",
  "after_failure",
  "before_deploy",
  "deploy",
  "after_deploy",
  "after_script"
];

const deletableSlots = ["notifications.email"];

export class Travis extends File {
  static matchesFileName(name) {
    return name === ".travis.yml";
  }

  async mergeContent(context, original, template) {
    const ymlOptions = { schema: yaml.FAILSAFE_SCHEMA };

    const yml = yaml.safeLoad(original, ymlOptions) || {};
    const tyml = yaml.safeLoad(context.expand(template), ymlOptions);

    const savedScripts = scriptSlots.reduce((a, c) => {
      a[c] = yml[c];
      return a;
    }, {});

    const messages = [];

    const oldVersions = new Set(
      yml.node_js ? [...yml.node_js.map(s => String(s))] : []
    );
    const templateVersions = new Set(
      tyml.node_js ? [...tyml.node_js.map(s => String(s))] : []
    );
    const versions = new Set([...oldVersions, ...templateVersions]);
    const newVersions = new Set(versions);

    versions.forEach(v => {
      if (v.startsWith("-")) {
        const d = v.replace(/^\-\s*/, "");

        versions.forEach(v => {
          const x = v.replace(/^\-\s*/, "");
          //console.log(`${d}<>${v} => ${diffVersion(d, x) === 0 || x != v}`);
          if (diffVersion(d, x) === 0 || x != v) {
            if (templateVersions.has(x)) {
              return;
            }

            newVersions.delete(x);
            newVersions.delete(v);
          }
        });
      }
    });

    const r = difference(oldVersions, newVersions);
    if (r.size > 0) {
      messages.push(
        `chore(travis): remove node versions ${Array.from(new Set(r)).sort()}`
      );
    }

    const a = difference(newVersions, oldVersions);
    if (a.size > 0) {
      messages.push(
        `chore(travis): add node versions ${Array.from(new Set(a)).sort()}`
      );
    }

    deletableSlots.forEach(name => {
      const parts = name.split(/\./);

      if (tyml[parts[0]] !== undefined) {
        const v = tyml[parts[0]][parts[1]];

        //console.log(`${name} -> ${Array.isArray(v)} ${v[0]}`);

        if (Array.isArray(v)) {
          for (const vv of v) {
            if (vv.startsWith("-")) {
              delete tyml[parts[0]][parts[1]];

              if (Object.keys(tyml[parts[0]]).length === 0) {
                delete tyml[parts[0]];
              }
            }
          }
        }

        /*if (v !== undefined && v[0] === "-") {
          delete tyml[parts[0]][parts[1]];
        }
        */
      }
    });

    deepExtend(yml, tyml);

    if (newVersions.size > 0) {
      yml.node_js = Array.from(new Set(newVersions))
        .sort()
        .map(s => (String(parseFloat(s)) == s ? parseFloat(s) : s));
    }

    scriptSlots.forEach(scriptName => {
      const cs = savedScripts[scriptName];

      if (cs != undefined) {
        cs.forEach(s => {
          if (!yml[scriptName].find(e => e === s)) {
            yml[scriptName].push(s);
          }
        });
      }

      if (yml[scriptName]) {
        yml[scriptName] = yml[scriptName].filter(
          s =>
            !tyml[scriptName].find(e => e === `-${s}`) && s.indexOf("-") !== 0
        );
      }
    });

    const content = yaml.safeDump(yml, {
      lineWidth: 128
    });

    if (messages.length === 0) {
      messages.push(`chore(travis): merge from template ${this.path}`);
    }

    return {
      content,
      changed: content !== original,
      messages
    };
  }
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import * as array from 'd3-array'
import * as scale from 'd3-scale'
import * as shape from 'd3-shape'
import React, { PureComponent } from 'react'
import { View } from 'react-native'
import { Defs, G, Svg } from 'react-native-svg'
import Grid from './grid'
import Path from './animated-path'

class AreaStack extends PureComponent {

    static extractDataPoints(data, keys, order = shape.stackOrderNone, offset = shape.stackOffsetNone) {
        const series = shape.stack()
            .keys(keys)
            .order(order)
            .offset(offset)
            (data)

        //double merge arrays to extract just the values
        return array.merge(array.merge(series))
    }

    state = {
        height: 0,
        width: 0,
    }

    _onLayout(event) {
        const { nativeEvent: { layout: { height, width } } } = event
        this.setState({ height, width })
    }

    render() {

        const {
                  data,
                  keys,
                  colors,
                  animate,
                  animationDuration,
                  style,
                  renderGradient,
                  curve,
                  showGrid,
                  numberOfTicks,
                  contentInset: {
                      top    = 0,
                      bottom = 0,
                      left   = 0,
                      right  = 0,
                  },
                  gridMin,
                  gridMax,
                  gridProps,
                  renderDecorator,
                  extras,
                  renderExtra,
                  offset,
                  order,
              } = this.props

        const { height, width } = this.state

        if (data.length === 0) {
            return <View style={ style }/>
        }

        const series = shape.stack()
            .keys(keys)
            .order(order)
            .offset(offset)
            (data)

        //double merge arrays to extract just the values
        const values = array.merge(array.merge(series))

        const extent = array.extent([ ...values, gridMin, gridMax ])
        const ticks  = array.ticks(extent[ 0 ], extent[ 1 ], numberOfTicks)

        //invert range to support svg coordinate system
        const y = scale.scaleLinear()
            .domain([ extent[ 0 ], extent[ 1 ] ])
            .range([ height - bottom, top ])

        const x = scale.scaleLinear()
            .domain([ 0, data.length - 1 ])
            .range([ left, width - right ])

        const areas = series.map((serie, index) => {
            const path = shape.area()
                .x((d, index) => x(index))
                .y0(d => y(d[ 0 ]))
                .y1(d => y(d[ 1 ]))
                .curve(curve)
                (data.map((_, index) => serie[ index ]))

            return {
                path,
                key: keys[ index ],
                color: colors[ index ],
            }
        })

        return (
            <View style={ style }>
                <View
                    style={ { flex: 1 } }
                    onLayout={ event => this._onLayout(event) }
                >
                    <Svg style={ { flex: 1 } }>
                        { showGrid &&
                          <Grid
                              ticks={ ticks }
                              y={ y }
                              gridProps={ gridProps }
                          />
                        }
                        { areas.map((area, index) => (
                                <G key={ area.key }>
                                    <Defs>
                                        { renderGradient && renderGradient({
                                            id: `gradient-${area.key}`,
                                            width,
                                            height,
                                            x,
                                            y,
                                            index,
                                            key: area.key,
                                            color: area.color,
                                        }) }
                                    </Defs>
                                    <Path
                                        animate={ animate }
                                        animationDuration={ animationDuration }
                                        d={ area.path }
                                        fill={ renderGradient ? `url(#gradient-${area.key})` : area.color }
                                    />
                                </G>
                            )
                        ) }
                        { series.map((serie) => {
                            return data.map((key, index) => {
                                return renderDecorator({ x, y, index, value: serie[ index ][ 1 ] })
                            })
                        }) }
                        { extras.map((item, index) => renderExtra({ item, x, y, index, width, height })) }
                    </Svg>
                </View>
            </View>
        )
    }
}

AreaStack.propTypes = {
    data: PropTypes.arrayOf(PropTypes.object).isRequired,
    keys: PropTypes.arrayOf(PropTypes.string).isRequired,
    colors: PropTypes.arrayOf(PropTypes.string).isRequired,
    offset: PropTypes.func,
    order: PropTypes.func,
    renderGradient: PropTypes.func,
    style: PropTypes.any,
    animate: PropTypes.bool,
    animationDuration: PropTypes.number,
    contentInset: PropTypes.shape({
        top: PropTypes.number,
        left: PropTypes.number,
        right: PropTypes.number,
        bottom: PropTypes.number,
    }),
    numberOfTicks: PropTypes.number,
    showGrid: PropTypes.bool,
    extras: PropTypes.array,
    renderDecorator: PropTypes.func,
    renderExtra: PropTypes.func,
}

AreaStack.defaultProps = {
    curve: shape.curveLinear,
    offset: shape.stackOffsetNone,
    order: shape.stackOrderNone,
    strokeWidth: 2,
    contentInset: {},
    numberOfTicks: 10,
    showGrid: true,
    extras: [],
    renderDecorator: () => {
    },
    renderExtra: () => {
    },
}

export default AreaStack
<commit_msg>update extras prop of StackedAreaChart https://github.com/JesperLekland/react-native-svg-charts/issues/86<commit_after>import PropTypes from 'prop-types'
import * as array from 'd3-array'
import * as scale from 'd3-scale'
import * as shape from 'd3-shape'
import React, { PureComponent } from 'react'
import { View } from 'react-native'
import { Defs, G, Svg } from 'react-native-svg'
import Grid from './grid'
import Path from './animated-path'

class AreaStack extends PureComponent {

    static extractDataPoints(data, keys, order = shape.stackOrderNone, offset = shape.stackOffsetNone) {
        const series = shape.stack()
            .keys(keys)
            .order(order)
            .offset(offset)
            (data)

        //double merge arrays to extract just the values
        return array.merge(array.merge(series))
    }

    state = {
        height: 0,
        width: 0,
    }

    _onLayout(event) {
        const { nativeEvent: { layout: { height, width } } } = event
        this.setState({ height, width })
    }

    render() {

        const {
                  data,
                  keys,
                  colors,
                  animate,
                  animationDuration,
                  style,
                  renderGradient,
                  curve,
                  showGrid,
                  numberOfTicks,
                  contentInset: {
                      top    = 0,
                      bottom = 0,
                      left   = 0,
                      right  = 0,
                  },
                  gridMin,
                  gridMax,
                  gridProps,
                  renderDecorator,
                  extras,
                  renderExtra,
                  offset,
                  order,
              } = this.props

        const { height, width } = this.state

        if (data.length === 0) {
            return <View style={ style }/>
        }

        const series = shape.stack()
            .keys(keys)
            .order(order)
            .offset(offset)
            (data)

        //double merge arrays to extract just the values
        const values = array.merge(array.merge(series))

        const extent = array.extent([ ...values, gridMin, gridMax ])
        const ticks  = array.ticks(extent[ 0 ], extent[ 1 ], numberOfTicks)

        //invert range to support svg coordinate system
        const y = scale.scaleLinear()
            .domain([ extent[ 0 ], extent[ 1 ] ])
            .range([ height - bottom, top ])

        const x = scale.scaleLinear()
            .domain([ 0, data.length - 1 ])
            .range([ left, width - right ])

        const areas = series.map((serie, index) => {
            const path = shape.area()
                .x((d, index) => x(index))
                .y0(d => y(d[ 0 ]))
                .y1(d => y(d[ 1 ]))
                .curve(curve)
                (data.map((_, index) => serie[ index ]))

            return {
                path,
                key: keys[ index ],
                color: colors[ index ],
            }
        })

        const extraData = {
            x,
            y,
            width,
            height,
        }

        return (
            <View style={ style }>
                <View
                    style={ { flex: 1 } }
                    onLayout={ event => this._onLayout(event) }
                >
                    <Svg style={ { flex: 1 } }>
                        { showGrid &&
                          <Grid
                              ticks={ ticks }
                              y={ y }
                              gridProps={ gridProps }
                          />
                        }
                        { areas.map((area, index) => (
                                <G key={ area.key }>
                                    <Defs>
                                        { renderGradient && renderGradient({
                                            id: `gradient-${area.key}`,
                                            width,
                                            height,
                                            x,
                                            y,
                                            index,
                                            key: area.key,
                                            color: area.color,
                                        }) }
                                    </Defs>
                                    <Path
                                        animate={ animate }
                                        animationDuration={ animationDuration }
                                        d={ area.path }
                                        fill={ renderGradient ? `url(#gradient-${area.key})` : area.color }
                                    />
                                </G>
                            )
                        ) }
                        { series.map((serie) => {
                            return data.map((key, index) => {
                                return renderDecorator({ x, y, index, value: serie[ index ][ 1 ] })
                            })
                        }) }
                        { extras.map((item, index) => item({ ...extraData, index })) }
                    </Svg>
                </View>
            </View>
        )
    }
}

AreaStack.propTypes = {
    data: PropTypes.arrayOf(PropTypes.object).isRequired,
    keys: PropTypes.arrayOf(PropTypes.string).isRequired,
    colors: PropTypes.arrayOf(PropTypes.string).isRequired,
    offset: PropTypes.func,
    order: PropTypes.func,
    renderGradient: PropTypes.func,
    style: PropTypes.any,
    animate: PropTypes.bool,
    animationDuration: PropTypes.number,
    contentInset: PropTypes.shape({
        top: PropTypes.number,
        left: PropTypes.number,
        right: PropTypes.number,
        bottom: PropTypes.number,
    }),
    numberOfTicks: PropTypes.number,
    showGrid: PropTypes.bool,
    extras: PropTypes.array,
    renderDecorator: PropTypes.func,
    renderExtra: PropTypes.func,
}

AreaStack.defaultProps = {
    curve: shape.curveLinear,
    offset: shape.stackOffsetNone,
    order: shape.stackOrderNone,
    strokeWidth: 2,
    contentInset: {},
    numberOfTicks: 10,
    showGrid: true,
    extras: [],
    renderDecorator: () => {
    },
    renderExtra: () => {
    },
}

export default AreaStack
<|endoftext|>


<commit_before>// Enemy info
var level1TDamage = [20, 50]; // the damage for all turrets
var level1TRange = [100, 200]; // the range for all turrets
var level1TRate = [1, 1]; // time in between shots for turrets in seconds

var placing = "0"; // default, means we aren't placing anything
var placingID = -1;
var placeable = true;
var numTurrets = 0; // number of turrets on map

$('ul.turrets li div').each(function(){
    $(this).mouseover(function(){
        switch(this.id){
            case 'turretB1':
                $('.description').text("This little one has a little green thumb which she uses to clean up the world one thumb full at a time.")
                break;
            case 'turretB2':
                $('.description').text("A speedy little persistent robot who's whole purpose in life is to clean up any mess it can reach. (2x the range of PewPew)")
                break;
            case 'turretB3':
                $('.description').text("Puny algae machine that can be placed on the tracks to slow down or erase the remains of oil blobs and such")
        }
         $('.description').show();

    });
     $(this).mouseleave(function(){
        console.log(this.id);
         $('.description').hide();
    });

});

//set red cross to show if not enough money and disable click
function turretCheck(){
    if(money >= 50){
        $("#turretB1").css({"background-color" : "transparent", "pointerEvents" : "auto"});
       $("#redCross1").css({"visibility" : "hidden"});
    }
    else{
        $("#redCross1").css({"visibility" : "visible"});
       $("#turretB1").css({"pointerEvents" : "none"});
    }
    if(money >= 100){
        $("#turretB2").css({"background-color" : "transparent", "pointerEvents" : "auto"});
      $("#redCross2").css({"visibility" : "hidden"});
    }
    else{
        $("#turretB2").css({"pointerEvents" : "none"});
      $("#redCross2").css({"visibility" : "visible"});
    }
    if(money >= 150){
         $("#turretB3").css({"background-color" : "transparent", "pointerEvents" : "auto"});
      $("#redCross3").css({"visibility" : "hidden"});
    }
    else{
        $("#turretB3").css({"pointerEvents" : "none"});
      $("#redCross3").css({"visibility" : "visible"});
    }
}

function place(type, id) {
    switch (id){
        case 1:
            cost = 50;
            break;
        case 2:
            cost = 100;
            break;
        case 3:
            cost = 150;
            break;
    }
  if(money >= cost){
      hasMoney = true;
  placing = type;
  placingID = id;
  $('#lv1bgimg').css('cursor', 'url(img/placement/' + type + '.png) 16 16, auto');// places the image of the turret on the board
  $('.gridslot').show();
   }
}

$('#lv1bgimg').click(function(event) {
  if (placing != "0" && placeable == true && hasMoney) {
    money-=cost;
    $('.money').text(money.toString());
    $(this).append('
');
    var x = event.pageX - $('#lv1bgimg').offset().left;
    var y = event.pageY - $('#lv1bgimg').offset().top;
    var xx = Math.floor((x) / 40);
    var yy = Math.floor((y) / 40);
    grid[xx][yy] = placing;
    $('#turret' + numTurrets).css('left', xx * 40 + 4).css('top', yy * 40 + 4);
    placing = "0";
    placingID = -1;
    $('#lv1bgimg').css('cursor', 'default');
    initFiring(numTurrets);
    numTurrets += 1;
    $('.gridslot').hide();
    if(numTurrets == 1)
      achievementUnlocked("FIRST TURRET PLACED!");// first turret achievement
  }
});

$('#lv1bgimg').mousemove(function(event) {
  if (placing != "0") {
    var x = event.pageX - $('#lv1bgimg').offset().left;
    var xx = Math.floor(x / 40);
    var y = event.pageY - $('#lv1bgimg').offset().top;
    var yy = Math.floor(y / 40);

    $('.gridslot').css('left', xx * 40 + $('#lv1bgimg').offset().left  - $(window).scrollLeft()).css('top', yy * 40 + $('#lv1bgimg').offset().top - $(window).scrollTop());

    // debugging
   //$('.debug').html(xx + ", " + yy);

    if ((grid[xx][yy] != "empty" && placing != "turret3") || (grid[xx][yy] == "empty" && placing == "turret3") || xx < 0 || yy < 0 || xx >= 20 || yy >= 20) {
      $('#lv1bgimg').css('cursor', 'url(img/placement/reds/' + placing + '.png) 16 16, auto');
      $('.gridslot').css('background-color', 'rgba(255,0,0,0.5)');
      placeable = false;
    } else {
      $('#lv1bgimg').css('cursor', 'url(img/placement/' + placing + '.png) 16 16, auto');
      $('.gridslot').css('background-color', 'rgba(0,255,0,0.5)');
      placeable = true;
    }
  }

});

function cursorX(event) {
  return event.clientX;
}

function cursorY(event) {
  return event.clientY;
}
<commit_msg>turret damage<commit_after>// Enemy info
var level1TDamage = [30, 50]; // the damage for all turrets
var level1TRange = [100, 200]; // the range for all turrets
var level1TRate = [1, 1]; // time in between shots for turrets in seconds

var placing = "0"; // default, means we aren't placing anything
var placingID = -1;
var placeable = true;
var numTurrets = 0; // number of turrets on map

$('ul.turrets li div').each(function(){
    $(this).mouseover(function(){
        switch(this.id){
            case 'turretB1':
                $('.description').text("This little one has a little green thumb which she uses to clean up the world one thumb full at a time.")
                break;
            case 'turretB2':
                $('.description').text("A speedy little persistent robot who's whole purpose in life is to clean up any mess it can reach. (2x the range of PewPew)")
                break;
            case 'turretB3':
                $('.description').text("Puny algae machine that can be placed on the tracks to slow down or erase the remains of oil blobs and such")
        }
         $('.description').show();

    });
     $(this).mouseleave(function(){
        console.log(this.id);
         $('.description').hide();
    });

});

//set red cross to show if not enough money and disable click
function turretCheck(){
    if(money >= 50){
        $("#turretB1").css({"background-color" : "transparent", "pointerEvents" : "auto"});
       $("#redCross1").css({"visibility" : "hidden"});
    }
    else{
        $("#redCross1").css({"visibility" : "visible"});
       $("#turretB1").css({"pointerEvents" : "none"});
    }
    if(money >= 100){
        $("#turretB2").css({"background-color" : "transparent", "pointerEvents" : "auto"});
      $("#redCross2").css({"visibility" : "hidden"});
    }
    else{
        $("#turretB2").css({"pointerEvents" : "none"});
      $("#redCross2").css({"visibility" : "visible"});
    }
    if(money >= 150){
         $("#turretB3").css({"background-color" : "transparent", "pointerEvents" : "auto"});
      $("#redCross3").css({"visibility" : "hidden"});
    }
    else{
        $("#turretB3").css({"pointerEvents" : "none"});
      $("#redCross3").css({"visibility" : "visible"});
    }
}

function place(type, id) {
    switch (id){
        case 1:
            cost = 50;
            break;
        case 2:
            cost = 100;
            break;
        case 3:
            cost = 150;
            break;
    }
  if(money >= cost){
      hasMoney = true;
  placing = type;
  placingID = id;
  $('#lv1bgimg').css('cursor', 'url(img/placement/' + type + '.png) 16 16, auto');// places the image of the turret on the board
  $('.gridslot').show();
   }
}

$('#lv1bgimg').click(function(event) {
  if (placing != "0" && placeable == true && hasMoney) {
    money-=cost;
    $('.money').text(money.toString());
    $(this).append('
');
    var x = event.pageX - $('#lv1bgimg').offset().left;
    var y = event.pageY - $('#lv1bgimg').offset().top;
    var xx = Math.floor((x) / 40);
    var yy = Math.floor((y) / 40);
    grid[xx][yy] = placing;
    $('#turret' + numTurrets).css('left', xx * 40 + 4).css('top', yy * 40 + 4);
    placing = "0";
    placingID = -1;
    $('#lv1bgimg').css('cursor', 'default');
    initFiring(numTurrets);
    numTurrets += 1;
    $('.gridslot').hide();
    if(numTurrets == 1)
      achievementUnlocked("FIRST TURRET PLACED!");// first turret achievement
  }
});

$('#lv1bgimg').mousemove(function(event) {
  if (placing != "0") {
    var x = event.pageX - $('#lv1bgimg').offset().left;
    var xx = Math.floor(x / 40);
    var y = event.pageY - $('#lv1bgimg').offset().top;
    var yy = Math.floor(y / 40);

    $('.gridslot').css('left', xx * 40 + $('#lv1bgimg').offset().left  - $(window).scrollLeft()).css('top', yy * 40 + $('#lv1bgimg').offset().top - $(window).scrollTop());

    // debugging
   //$('.debug').html(xx + ", " + yy);

    if ((grid[xx][yy] != "empty" && placing != "turret3") || (grid[xx][yy] == "empty" && placing == "turret3") || xx < 0 || yy < 0 || xx >= 20 || yy >= 20) {
      $('#lv1bgimg').css('cursor', 'url(img/placement/reds/' + placing + '.png) 16 16, auto');
      $('.gridslot').css('background-color', 'rgba(255,0,0,0.5)');
      placeable = false;
    } else {
      $('#lv1bgimg').css('cursor', 'url(img/placement/' + placing + '.png) 16 16, auto');
      $('.gridslot').css('background-color', 'rgba(0,255,0,0.5)');
      placeable = true;
    }
  }

});

function cursorX(event) {
  return event.clientX;
}

function cursorY(event) {
  return event.clientY;
}
<|endoftext|>


<commit_before>function check_user(){
    $.ajax({url: "/user", success: function(result){
        var html = "";
        var side_html = "";
        if (result.login){
            // side_html = '
Logout
';
            if (result.avatar_url){
              $('#navPhoto').attr("src", result.avatar_url);
              html += "

";
          }
          html += "
Logout
";
          side_html += "
My Dashboard

Logout
";
        }else{
            html += "
Login
";
            side_html += html;
        }
        // Append new items to navigation
        $("#user_link").append(html).promise().done(function(){
            $('.tooltipped').tooltip();
            $(".dropdown-button").dropdown();
        });
        $("#side_user_link").append(side_html);
    }});
};

/* for reg_form.html */
function save_api(form, overwrite, savev2){
    $("#submit_mask").modal("open");
    var data = $(form).serialize();
    if (overwrite){
      data += "&overwrite=true";
    }
    if (savev2){
      data += "&save_v2=true";
    }
    $.ajax({
        url: "/api",
        type: "post",
        data: data,
        success: function(response) {
            $("#submit_mask").modal("close");
            //console.log(response);
            if (response.success){
                var msg = 'API metadata saved!';
                if (response.dryrun){
                  msg += '
Well, not really, because this is a dryrun.';
                  msg += ' If you do want to register your API, uncheck "dry run" and try again.
';
                }
                swal('Good job!', msg, 'success');

            }
            else{
              if (response.swagger_v2){
                // -----------
                swal({
                    title: "Version 2 Detected",
                    text: "Continue saving anyway?",
                    icon: "warning",
                    buttons: true,
                    dangerMode: true,
                  })
                  .then((willSave) => {
                    if (willSave) {
                      save_api(form, true, true);
                      swal("Your data has been saved!", {
                        icon: "success",
                      });
                    } else {
                      swal("Your data has not been saved");
                    }
                  });
                // ----------
              }
              if (response.error.indexOf("API exists") != -1){
                  swal({
                      title: 'API exists. Overwrite?',
                      text: "You won't be able to revert this!",
                      type: 'warning',
                      showCancelButton: true,
                      confirmButtonColor: '#3085d6',
                      cancelButtonColor: '#d33',
                      confirmButtonText: 'Yes, Overwrite it!'
                  }).then(function() {
                      save_api(form, true);
                  }, function(){});
              }
              else{
                  swal(
                      response.valid==false?'ValidationError':'Error',
                      response.error,
                      'error'
                  );
              }
            }
        }
    });
};

function initialize_form() {
    // initialize API registration form
    $('#apireg_form').validate({
        rules: {
            url: {
                required: true
            }
        },
        submitHandler: function(form){
            save_api(form);
        }
    });

    $('#api_search_form').validate({
        rules:{
            query: {
                required: true
            }
        }
    });
};

$(function(){
    // Initialize collapse button
    $('.button-collapse').sideNav({
          menuWidth: 240, // Default is 240
          edge: 'left', // Choose the horizontal origin
          closeOnClick: true // Closes side-nav on  clicks, useful for Angular/Meteor
        }
      );
    // Initialize dropdown button
    $(".dropdown-button").dropdown();
    // Initialize modal
    $('.modal').modal({dismissible: true});
    // Check user status
    check_user();

    // for reg_form.html
    initialize_form();
  });

  // Particles
<commit_msg>v2 again<commit_after>function check_user(){
    $.ajax({url: "/user", success: function(result){
        var html = "";
        var side_html = "";
        if (result.login){
            // side_html = '
Logout
';
            if (result.avatar_url){
              $('#navPhoto').attr("src", result.avatar_url);
              html += "

";
          }
          html += "
Logout
";
          side_html += "
My Dashboard

Logout
";
        }else{
            html += "
Login
";
            side_html += html;
        }
        // Append new items to navigation
        $("#user_link").append(html).promise().done(function(){
            $('.tooltipped').tooltip();
            $(".dropdown-button").dropdown();
        });
        $("#side_user_link").append(side_html);
    }});
};

/* for reg_form.html */
function save_api(form, overwrite, savev2){
    $("#submit_mask").modal("open");
    var data = $(form).serialize();
    if (overwrite){
      data += "&overwrite=true";
    }
    if (savev2){
      data += "&save_v2=true";
    }
    $.ajax({
        url: "/api",
        type: "post",
        data: data,
        success: function(response) {
            $("#submit_mask").modal("close");
            //console.log(response);
            if (response.success){
                var msg = 'API metadata saved!';
                if (response.dryrun){
                  msg += '
Well, not really, because this is a dryrun.';
                  msg += ' If you do want to register your API, uncheck "dry run" and try again.
';
                }
                swal('Good job!', msg, 'success');

            }
            else{
              if ( (response.error.indexOf("swagger_v2") != -1) && response.swagger_v2 ){
                // -----------
                swal({
                    title: "Version 2 Detected",
                    text: "Continue saving anyway?",
                    icon: "warning",
                    buttons: true,
                    dangerMode: true,
                  })
                  .then((willSave) => {
                    if (willSave) {
                      save_api(form, true, true);
                      swal("Your data has been saved!", {
                        icon: "success",
                      });
                    } else {
                      swal("Your data has not been saved");
                    }
                  });
                // ----------
              }
              if (response.error.indexOf("API exists") != -1){
                  swal({
                      title: 'API exists. Overwrite?',
                      text: "You won't be able to revert this!",
                      type: 'warning',
                      showCancelButton: true,
                      confirmButtonColor: '#3085d6',
                      cancelButtonColor: '#d33',
                      confirmButtonText: 'Yes, Overwrite it!'
                  }).then(function() {
                      save_api(form, true);
                  }, function(){});
              }
              else{
                  swal(
                      response.valid==false?'ValidationError':'Error',
                      response.error,
                      'error'
                  );
              }
            }
        }
    });
};

function initialize_form() {
    // initialize API registration form
    $('#apireg_form').validate({
        rules: {
            url: {
                required: true
            }
        },
        submitHandler: function(form){
            save_api(form);
        }
    });

    $('#api_search_form').validate({
        rules:{
            query: {
                required: true
            }
        }
    });
};

$(function(){
    // Initialize collapse button
    $('.button-collapse').sideNav({
          menuWidth: 240, // Default is 240
          edge: 'left', // Choose the horizontal origin
          closeOnClick: true // Closes side-nav on  clicks, useful for Angular/Meteor
        }
      );
    // Initialize dropdown button
    $(".dropdown-button").dropdown();
    // Initialize modal
    $('.modal').modal({dismissible: true});
    // Check user status
    check_user();

    // for reg_form.html
    initialize_form();
  });

  // Particles
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import styled from 'styled-components';
import './App.css';
import Dropdown from './Dropdown';
import Preview from './Preview';

// Working around electron imports from CRA app:
// https://medium.freecodecamp.com/building-an-electron-application-with-create-react-app-97945861647c
const {
  remote,
  ipcRenderer,
  clipboard
} = window.require('electron');
const fs = remote.require('fs');
const path = remote.require('path');
const settings = remote.require('electron-settings');
const SystemFonts = remote.require('system-font-families').default;
const { resolveStylesheetsDir } = remote.require('../../lib/');

const systemFonts = new SystemFonts();
const themeList = fs
  .readdirSync(path.join(resolveStylesheetsDir()))
  .map(stylesheet => stylesheet.replace(/\.css$/, ''));

const Wrapper = styled.div`
  padding: 15px;
  font-size: 10px;
`;

const fontList = systemFonts.getFontsSync();

class App extends Component {
  state = {
    selectedFont: settings.getSync('fontface'),
    selectedTheme: settings.getSync('theme')
  };

  showMenu = event => {
    const { left, bottom } = event.target.getBoundingClientRect();
    ipcRenderer.send('show-options-menu', { left, bottom });
    event.stopPropagation();
  };

  onFontChanged = event => {
    const selectedFont = event.target.value;
    settings.setSync('fontface', selectedFont);
    this.setState({ selectedFont });
  };

  onThemeChanged = event => {
    const selectedTheme = event.target.value;
    settings.setSync('theme', selectedTheme);
    this.setState({ selectedTheme });
  };

  render() {
    const { selectedFont, selectedTheme } = this.state;
    const themePath = path.join(
      resolveStylesheetsDir(),
      `${selectedTheme}.css`
    );
    const theme = fs.readFileSync(themePath, 'utf-8');
    return (
      <Wrapper>
        <Dropdown
          items={fontList}
          selectedItem={selectedFont}
          onChange={this.onFontChanged}
        />
        <Dropdown
          items={themeList}
          selectedItem={selectedTheme}
          onChange={this.onThemeChanged}
        />
        <button onClick={this.showMenu}>⚙</button>
        <Preview codeSnippet={clipboard.readText()} theme={theme} />
      </Wrapper>
    );
  }
}

export default App;
<commit_msg>Reformat code with prettier<commit_after>import React, { Component } from 'react';
import styled from 'styled-components';
import './App.css';
import Dropdown from './Dropdown';
import Preview from './Preview';

// Working around electron imports from CRA app:
// https://medium.freecodecamp.com/building-an-electron-application-with-create-react-app-97945861647c
const {
  remote,
  ipcRenderer,
  clipboard
} = window.require('electron');
const fs = remote.require('fs');
const path = remote.require('path');
const settings = remote.require('electron-settings');
const SystemFonts = remote.require('system-font-families').default;
const { resolveStylesheetsDir } = remote.require('../../lib/');

const systemFonts = new SystemFonts();
const themeList = fs
  .readdirSync(path.join(resolveStylesheetsDir()))
  .map(stylesheet => stylesheet.replace(/\.css$/, ''));

const Wrapper = styled.div`
  padding: 15px;
  font-size: 10px;
`;

const fontList = systemFonts.getFontsSync();

class App extends Component {
  state = {
    selectedFont: settings.getSync('fontface'),
    selectedTheme: settings.getSync('theme')
  };

  componentDidMount() {
    ipcRenderer.on('global-shortcut-pressed', () => {
      console.log(111);
      this.forceUpdate();
    });
  }

  componentWillUnmount() {
    ipcRenderer.off('global-shortcut-pressed', this.forceUpdate);
  }

  showMenu = event => {
    const { left, bottom } = event.target.getBoundingClientRect();
    ipcRenderer.send('show-options-menu', { left, bottom });
    event.stopPropagation();
  };

  onFontChanged = event => {
    const selectedFont = event.target.value;
    settings.setSync('fontface', selectedFont);
    this.setState({ selectedFont });
  };

  onThemeChanged = event => {
    const selectedTheme = event.target.value;
    settings.setSync('theme', selectedTheme);
    this.setState({ selectedTheme });
  };

  render() {
    const { selectedFont, selectedTheme } = this.state;
    const themePath = path.join(resolveStylesheetsDir(), `${selectedTheme}.css`);
    const theme = fs.readFileSync(themePath, 'utf-8');
    return (
      <Wrapper>
        <Dropdown items={fontList} selectedItem={selectedFont} onChange={this.onFontChanged} />
        <Dropdown items={themeList} selectedItem={selectedTheme} onChange={this.onThemeChanged} />
        <button onClick={this.showMenu}>⚙</button>
        <Preview codeSnippet={clipboard.readText()} theme={theme} />
      </Wrapper>
    );
  }
}

export default App;
<|endoftext|>


<commit_before>/**
 * @fileoverview Handles proper queueing of the jobs,
 *   publishing events to redis channels.
 *
 */

var _ = require('underscore');
var when = require('when');
var util = require('util');
var sequence = require('when/sequence');

var Model = require('./model');
var kconfig = require('../utility/config');
var Hotjob = require('./hotjob.model');
var kError = require('../utility/kerror');
var states = require('./states');

/**
 * The State Class.
 *
 * @param {Kickq.JobItem} jobItem the job item.
 * @constructor
 */
var QueueModel = module.exports = function( jobItem ) {

  Model.apply(this, arguments);

  /** @type {Kickq.JobItem} */
  this.job = jobItem;

};
util.inherits(QueueModel, Model);

/**
 * Add the job to the right queue, optionally emitting a publish redis event.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.save = function() {
  var def = when.defer();
  switch(this.job.state) {
    case states.Job.NEW:
      sequence([

        // new jobs get added to process queue and check for hotjob option.
        this.addToProcessQueue.bind(this),
        this.checkHotjob.bind(this)

      ]).then(def.resolve, def.reject);
    break;
    case states.Job.PROCESSING:
      // nothing todo here
      def.resolve();
    break;
    case states.Job.DELAYED:
    case states.Job.RETRY:
    case states.Job.GHOST:
      // schedule
      // when( this.schedule().bind(this) ).then(def.resolve, def.reject);
      if (this.job.state !== states.Job.DELAYED) {
        this._publish('fail');
      }
    break;
    case states.Job.SUCCESS:

      // emit complete event
      this._publish('complete');

      // BREAK OMITTED ON PURPOSE
    case states.Job.FAIL:

      // nuke schedule
      when( this.purgeSchedule().bind(this) ).then(def.resolve, def.reject);
    break;

    default:
      def.reject(new kError.InvalidState(this.job));
    break;
  }

  return def.promise;
};

/**
 * Add the job to the process queue, emit a publish event on redis.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.addToProcessQueue = function() {
  var def = when.defer();

  // kickq:queue:[ job name ]
  var queueKey = this.NS + ':queue:' + this.job.name;

  this.client.rpush( queueKey, this.job.id, function(err) {
    if (err) {
      var p = def.reject(new kError.QueueFail(this.job, err + ''));
      return p;
    }

    // shout out to my big b and iron ziz!
    this.client.publish( queueKey, this.job.id );

    return def.resolve();
  }.bind(this));

  return def.promise;
};

/**
 * Check if the job has the hotjob flag on and handle it.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.checkHotjob = function() {
  var hotjob = new Hotjob(this.job);
  return hotjob.check();
};

/**
 * Schedule the job.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.schedule = function() {

  // figure out when this job should move to the process queue
  var delay;
  switch(this.job.state) {
    case states.Job.DELAYED:
      delay = this.job.delay * 1000;
    break;
    case states.Job.RETRY:
      delay = this.job.retryInterval * 1000;
    break;
    case states.Job.GHOST:
      delay = kconfig.get('ghostInterval') * 1000;
    break;
  }

  return this._scheduleRedis('scheduled', delay);
};

/**
 * Schedule the job to get purged.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.purgeSchedule = function() {
  var delay = kconfig.get('purgeTimeout') * 1000;

  return this._scheduleRedis('scheduled-purge', delay);
};

/**
 * Create the actual scheduling record in redis.
 *
 * @param {string} queue The queue, one of 'scheduled', 'scheduled-purge'.
 * @param {number} delay delay in miliseconds.
 * @return {when.Promise} A promise.
 * @private
 */
QueueModel.prototype._scheduleRedis = function(queue, delay) {
  var def = when.defer();

  // save any bloopers with a 5' scheduling
  if (!_.isNumber(delay)) {
    delay = 300000;
  }
  var scheduleFor = Date.now() + delay;

  this.client.zset(this.NS + ':' + queue, scheduleFor, this.job.id, function(err) {
    if (err) {
      return def.reject(new kError.Database(err));
    }
    def.resolve();
  }.bind(this));

  return def.promise;
};

/**
 * Publish a redis message
 *
 * @param  {string} publishType 'complete' or 'fail'.
 * @private
 */
QueueModel.prototype._publish = function(publishType) {
  var publishKey = this.NS + ':' + publishType + ':' + this.job.name;
  var jobSerialized = this.job.getPublicJSON();
  this.client.publish( publishKey, jobSerialized );
};
<commit_msg>new linting rules for switch<commit_after>/**
 * @fileoverview Handles proper queueing of the jobs,
 *   publishing events to redis channels.
 *
 */

var _ = require('underscore');
var when = require('when');
var util = require('util');
var sequence = require('when/sequence');

var Model = require('./model');
var kconfig = require('../utility/config');
var Hotjob = require('./hotjob.model');
var kError = require('../utility/kerror');
var states = require('./states');

/**
 * The State Class.
 *
 * @param {Kickq.JobItem} jobItem the job item.
 * @constructor
 */
var QueueModel = module.exports = function( jobItem ) {

  Model.apply(this, arguments);

  /** @type {Kickq.JobItem} */
  this.job = jobItem;

};
util.inherits(QueueModel, Model);

/**
 * Add the job to the right queue, optionally emitting a publish redis event.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.save = function() {
  var def = when.defer();
  switch(this.job.state) {
  case states.Job.NEW:
    sequence([

      // new jobs get added to process queue and check for hotjob option.
      this.addToProcessQueue.bind(this),
      this.checkHotjob.bind(this)

    ]).then(def.resolve, def.reject);
    break;
  case states.Job.PROCESSING:
    // nothing todo here
    def.resolve();
    break;
  case states.Job.DELAYED:
  case states.Job.RETRY:
  case states.Job.GHOST:
    // schedule
    when( this.schedule().bind(this) ).then(def.resolve, def.reject);
    if (this.job.state !== states.Job.DELAYED) {
      this._publish('fail');
    }
    break;
  case states.Job.SUCCESS:

    // emit complete event
    // BREAK OMITTED ON PURPOSE
    this._publish('complete');
    // BREAK OMITTED ON PURPOSE
  case states.Job.FAIL:

    // nuke schedule
    when( this.purgeSchedule().bind(this) ).then(def.resolve, def.reject);
    break;

  default:
    def.reject(new kError.InvalidState(this.job));
    break;
  }

  return def.promise;
};

/**
 * Add the job to the process queue, emit a publish event on redis.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.addToProcessQueue = function() {
  var def = when.defer();

  // kickq:queue:[ job name ]
  var queueKey = this.NS + ':queue:' + this.job.name;

  this.client.rpush( queueKey, this.job.id, function(err) {
    if (err) {
      var p = def.reject(new kError.QueueFail(this.job, err + ''));
      return p;
    }

    // shout out to my big b and iron ziz!
    this.client.publish( queueKey, this.job.id );

    return def.resolve();
  }.bind(this));

  return def.promise;
};

/**
 * Check if the job has the hotjob flag on and handle it.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.checkHotjob = function() {
  var hotjob = new Hotjob(this.job);
  return hotjob.check();
};

/**
 * Schedule the job.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.schedule = function() {

  // figure out when this job should move back to the process queue
  var delay;
  switch(this.job.state) {
  case states.Job.DELAYED:
    delay = this.job.delay * 1000 >>> 0;
    break;
  case states.Job.RETRY:
    delay = this.job.retryInterval * 1000 >>> 0;
    break;
  case states.Job.GHOST:
    delay = kconfig.get('ghostInterval') * 1000 >>> 0;
    break;
  }

  return this._scheduleRedis('scheduled', delay);
};

/**
 * Schedule the job to get purged.
 *
 * @return {when.Promise} A promise.
 */
QueueModel.prototype.purgeSchedule = function() {
  var delay = kconfig.get('purgeTimeout') * 1000;

  return this._scheduleRedis('scheduled-purge', delay);
};

/**
 * Create the actual scheduling record in redis.
 *
 * @param {string} queue The queue, one of 'scheduled', 'scheduled-purge'.
 * @param {number} delay delay in miliseconds.
 * @return {when.Promise} A promise.
 * @private
 */
QueueModel.prototype._scheduleRedis = function(queue, delay) {
  var def = when.defer();

  // save any bloopers with a 5' scheduling
  if (!_.isNumber(delay)) {
    delay = 300000;
  }
  var scheduleFor = Date.now() + delay;

  this.client.zset(this.NS + ':' + queue, scheduleFor, this.job.id, function(err) {
    if (err) {
      return def.reject(new kError.Database(err));
    }
    def.resolve();
  }.bind(this));

  return def.promise;
};

/**
 * Publish a redis message
 *
 * @param  {string} publishType 'complete' or 'fail'.
 * @private
 */
QueueModel.prototype._publish = function(publishType) {
  var publishKey = this.NS + ':' + publishType + ':' + this.job.name;
  var jobSerialized = this.job.getPublicJSON();
  this.client.publish( publishKey, jobSerialized );
};
<|endoftext|>


<commit_before>angular.module('proxtop', ['ngMaterial', 'ui.router', 'angular-progress-arc', 'pascalprecht.translate'])
    .config(['$stateProvider', '$urlRouterProvider', '$translateProvider', function($stateProvider, $urlRouterProvider, $translateProvider) {
        $urlRouterProvider.otherwise('/');
        $translateProvider.useStaticFilesLoader({
            prefix: 'ui/locale/locale-',
            suffix: '.json'
        });

        $translateProvider.preferredLanguage('de');
        $translateProvider.useSanitizeValueStrategy('sanitizeParameters');
    }]);
<commit_msg>Use sanitization method that doesn't require more dependencies.<commit_after>angular.module('proxtop', ['ngMaterial', 'ui.router', 'angular-progress-arc', 'pascalprecht.translate'])
    .config(['$stateProvider', '$urlRouterProvider', '$translateProvider', function($stateProvider, $urlRouterProvider, $translateProvider) {
        $urlRouterProvider.otherwise('/');
        $translateProvider.useStaticFilesLoader({
            prefix: 'ui/locale/locale-',
            suffix: '.json'
        });

        $translateProvider.preferredLanguage('de');
        $translateProvider.useSanitizeValueStrategy('escape');
    }]);
<|endoftext|>


<commit_before>import Hunk from './hunk';
import {toGitPathSep} from '../helpers';

class File {
  constructor({path, mode, symlink}) {
    this.path = path;
    this.mode = mode;
    this.symlink = symlink;
  }

  getPath() {
    return this.path;
  }

  getMode() {
    return this.mode;
  }

  getSymlink() {
    return this.symlink;
  }

  clone(opts = {}) {
    return new File({
      path: opts.path !== undefined ? opts.path : this.path,
      mode: opts.mode !== undefined ? opts.mode : this.mode,
      symlink: opts.symlink !== undefined ? opts.symlink : this.symlink,
    });
  }
}

class Patch {
  constructor({status, hunks, typechange}) {
    this.status = status;
    this.hunks = hunks;
    this.typechange = !!typechange;
  }

  getStatus() {
    return this.status;
  }

  getHunks() {
    return this.hunks;
  }

  hasTypechange() {
    return this.typechange;
  }

  clone(opts = {}) {
    return new Patch({
      status: opts.status !== undefined ? opts.status : this.status,
      hunks: opts.hunks !== undefined ? opts.hunks : this.hunks,
    });
  }
}

export default class FilePatch {
  static File = File;
  static Patch = Patch;

  constructor(oldFile, newFile, patch) {
    this.oldFile = oldFile;
    this.newFile = newFile;
    this.patch = patch;

    this.changedLineCount = this.getHunks().reduce((acc, hunk) => {
      return acc + hunk.getLines().filter(line => line.isChanged()).length;
    }, 0);
  }

  clone(opts = {}) {
    const oldFile = opts.oldFile !== undefined ? opts.oldFile : this.getOldFile();
    const newFile = opts.newFile !== undefined ? opts.newFile : this.getNewFile();
    const patch = opts.patch !== undefined ? opts.patch : this.patch;
    return new FilePatch(oldFile, newFile, patch);
  }

  getOldFile() {
    return this.oldFile;
  }

  getNewFile() {
    return this.newFile;
  }

  getPatch() {
    return this.patch;
  }

  getOldPath() {
    return this.getOldFile().getPath();
  }

  getNewPath() {
    return this.getNewFile().getPath();
  }

  getOldMode() {
    return this.getOldFile().getMode();
  }

  getNewMode() {
    return this.getNewFile().getMode();
  }

  didChangeExecutableMode() {
    const oldMode = this.getOldMode();
    const newMode = this.getNewMode();
    return oldMode === '100755' && newMode !== '100755' ||
      oldMode !== '100755' && newMode === '100755';
  }

  didChangeSymlinkMode() {
    const oldMode = this.getOldMode();
    const newMode = this.getNewMode();
    return oldMode === '120000' && newMode !== '120000' ||
      oldMode !== '120000' && newMode === '120000';
  }

  hasSymlink() {
    return this.getOldFile().getSymlink() || this.getNewFile().getSymlink();
  }

  hasTypechange() {
    return this.getPatch().hasTypechange();
  }

  getPath() {
    return this.getOldPath() || this.getNewPath();
  }

  getStatus() {
    return this.getPatch().getStatus();
  }

  getHunks() {
    return this.getPatch().getHunks();
  }

  getStagePatchForHunk(selectedHunk) {
    return this.getStagePatchForLines(new Set(selectedHunk.getLines()));
  }

  getStagePatchForLines(selectedLines) {
    if (this.changedLineCount === [...selectedLines].filter(line => line.isChanged()).length) {
      return this;
    }

    let delta = 0;
    const hunks = [];
    for (const hunk of this.getHunks()) {
      const newStartRow = (hunk.getNewStartRow() || 1) + delta;
      let newLineNumber = newStartRow;
      const lines = [];
      let hunkContainsSelectedLines = false;
      for (const line of hunk.getLines()) {
        if (line.getStatus() === 'nonewline') {
          lines.push(line.copy({oldLineNumber: -1, newLineNumber: -1}));
        } else if (selectedLines.has(line)) {
          hunkContainsSelectedLines = true;
          if (line.getStatus() === 'deleted') {
            lines.push(line.copy());
          } else {
            lines.push(line.copy({newLineNumber: newLineNumber++}));
          }
        } else if (line.getStatus() === 'deleted') {
          lines.push(line.copy({newLineNumber: newLineNumber++, status: 'unchanged'}));
        } else if (line.getStatus() === 'unchanged') {
          lines.push(line.copy({newLineNumber: newLineNumber++}));
        }
      }
      const newRowCount = newLineNumber - newStartRow;
      if (hunkContainsSelectedLines) {
        // eslint-disable-next-line max-len
        hunks.push(new Hunk(hunk.getOldStartRow(), newStartRow, hunk.getOldRowCount(), newRowCount, hunk.getSectionHeading(), lines));
      }
      delta += newRowCount - hunk.getNewRowCount();
    }

    return this.clone({
      newFile: this.getNewPath() ? this.getNewFile() : this.getOldFile(),
      patch: this.getPatch().clone({hunks}),
    });
  }

  getUnstagePatch() {
    let invertedStatus;
    switch (this.getStatus()) {
      case 'modified':
        invertedStatus = 'modified';
        break;
      case 'added':
        invertedStatus = 'deleted';
        break;
      case 'deleted':
        invertedStatus = 'added';
        break;
      default:
        // throw new Error(`Unknown Status: ${this.getStatus()}`);
    }
    const invertedHunks = this.getHunks().map(h => h.invert());
    return this.clone({
      oldFile: this.getNewFile(),
      newFile: this.getOldFile(),
      patch: this.getPatch().clone({
        status: invertedStatus,
        hunks: invertedHunks,
      }),
    });
  }

  getUnstagePatchForHunk(hunk) {
    return this.getUnstagePatchForLines(new Set(hunk.getLines()));
  }

  getUnstagePatchForLines(selectedLines) {
    if (this.changedLineCount === [...selectedLines].filter(line => line.isChanged()).length) {
      return this.getUnstagePatch();
    }

    let delta = 0;
    const hunks = [];
    for (const hunk of this.getHunks()) {
      const oldStartRow = (hunk.getOldStartRow() || 1) + delta;
      let oldLineNumber = oldStartRow;
      const lines = [];
      let hunkContainsSelectedLines = false;
      for (const line of hunk.getLines()) {
        if (line.getStatus() === 'nonewline') {
          lines.push(line.copy({oldLineNumber: -1, newLineNumber: -1}));
        } else if (selectedLines.has(line)) {
          hunkContainsSelectedLines = true;
          if (line.getStatus() === 'added') {
            lines.push(line.copy());
          } else {
            lines.push(line.copy({oldLineNumber: oldLineNumber++}));
          }
        } else if (line.getStatus() === 'added') {
          lines.push(line.copy({oldLineNumber: oldLineNumber++, status: 'unchanged'}));
        } else if (line.getStatus() === 'unchanged') {
          lines.push(line.copy({oldLineNumber: oldLineNumber++}));
        }
      }
      const oldRowCount = oldLineNumber - oldStartRow;
      if (hunkContainsSelectedLines) {
        // eslint-disable-next-line max-len
        hunks.push(new Hunk(oldStartRow, hunk.getNewStartRow(), oldRowCount, hunk.getNewRowCount(), hunk.getSectionHeading(), lines));
      }
      delta += oldRowCount - hunk.getOldRowCount();
    }

    return this.clone({
      oldFile: this.getOldPath() ? this.getOldFile() : this.getNewFile(),
      patch: this.getPatch().clone({hunks}),
    }).getUnstagePatch();
  }

  toString() {
    return this.getHunks().map(h => h.toString()).join('');
  }

  getHeaderString() {
    let header = this.getOldPath() ? `--- a/${toGitPathSep(this.getOldPath())}` : '--- /dev/null';
    header += '\n';
    header += this.getNewPath() ? `+++ b/${toGitPathSep(this.getNewPath())}` : '+++ /dev/null';
    header += '\n';
    return header;
  }
}
<commit_msg>Handle file deletion/creation for typechanges when staging last line<commit_after>import Hunk from './hunk';
import {toGitPathSep} from '../helpers';

class File {
  constructor({path, mode, symlink}) {
    this.path = path;
    this.mode = mode;
    this.symlink = symlink;
  }

  getPath() {
    return this.path;
  }

  getMode() {
    return this.mode;
  }

  getSymlink() {
    return this.symlink;
  }

  clone(opts = {}) {
    return new File({
      path: opts.path !== undefined ? opts.path : this.path,
      mode: opts.mode !== undefined ? opts.mode : this.mode,
      symlink: opts.symlink !== undefined ? opts.symlink : this.symlink,
    });
  }
}

class Patch {
  constructor({status, hunks, typechange}) {
    this.status = status;
    this.hunks = hunks;
    this.typechange = !!typechange;
  }

  getStatus() {
    return this.status;
  }

  getHunks() {
    return this.hunks;
  }

  hasTypechange() {
    return this.typechange;
  }

  clone(opts = {}) {
    return new Patch({
      status: opts.status !== undefined ? opts.status : this.status,
      hunks: opts.hunks !== undefined ? opts.hunks : this.hunks,
    });
  }
}

export default class FilePatch {
  static File = File;
  static Patch = Patch;

  constructor(oldFile, newFile, patch) {
    this.oldFile = oldFile;
    this.newFile = newFile;
    this.patch = patch;

    this.changedLineCount = this.getHunks().reduce((acc, hunk) => {
      return acc + hunk.getLines().filter(line => line.isChanged()).length;
    }, 0);
  }

  clone(opts = {}) {
    const oldFile = opts.oldFile !== undefined ? opts.oldFile : this.getOldFile();
    const newFile = opts.newFile !== undefined ? opts.newFile : this.getNewFile();
    const patch = opts.patch !== undefined ? opts.patch : this.patch;
    return new FilePatch(oldFile, newFile, patch);
  }

  getOldFile() {
    return this.oldFile;
  }

  getNewFile() {
    return this.newFile;
  }

  getPatch() {
    return this.patch;
  }

  getOldPath() {
    return this.getOldFile().getPath();
  }

  getNewPath() {
    return this.getNewFile().getPath();
  }

  getOldMode() {
    return this.getOldFile().getMode();
  }

  getNewMode() {
    return this.getNewFile().getMode();
  }

  didChangeExecutableMode() {
    const oldMode = this.getOldMode();
    const newMode = this.getNewMode();
    return oldMode === '100755' && newMode !== '100755' ||
      oldMode !== '100755' && newMode === '100755';
  }

  didChangeSymlinkMode() {
    const oldMode = this.getOldMode();
    const newMode = this.getNewMode();
    return oldMode === '120000' && newMode !== '120000' ||
      oldMode !== '120000' && newMode === '120000';
  }

  hasSymlink() {
    return this.getOldFile().getSymlink() || this.getNewFile().getSymlink();
  }

  hasTypechange() {
    return this.getPatch().hasTypechange();
  }

  getPath() {
    return this.getOldPath() || this.getNewPath();
  }

  getStatus() {
    return this.getPatch().getStatus();
  }

  getHunks() {
    return this.getPatch().getHunks();
  }

  getStagePatchForHunk(selectedHunk) {
    return this.getStagePatchForLines(new Set(selectedHunk.getLines()));
  }

  getStagePatchForLines(selectedLines) {
    if (this.changedLineCount === [...selectedLines].filter(line => line.isChanged()).length) {
      if (this.hasTypechange() && this.getStatus() === 'deleted') {
        // handle special case when symlink is created where a file was deleted. In order to stage the file deletion,
        // we must ensure that the created file patch has no new file
        return this.clone({
          newFile: new File({path: null, mode: null, symlink: null}),
        });
      } else {
        return this;
      }
    }

    let delta = 0;
    const hunks = [];
    for (const hunk of this.getHunks()) {
      const newStartRow = (hunk.getNewStartRow() || 1) + delta;
      let newLineNumber = newStartRow;
      const lines = [];
      let hunkContainsSelectedLines = false;
      for (const line of hunk.getLines()) {
        if (line.getStatus() === 'nonewline') {
          lines.push(line.copy({oldLineNumber: -1, newLineNumber: -1}));
        } else if (selectedLines.has(line)) {
          hunkContainsSelectedLines = true;
          if (line.getStatus() === 'deleted') {
            lines.push(line.copy());
          } else {
            lines.push(line.copy({newLineNumber: newLineNumber++}));
          }
        } else if (line.getStatus() === 'deleted') {
          lines.push(line.copy({newLineNumber: newLineNumber++, status: 'unchanged'}));
        } else if (line.getStatus() === 'unchanged') {
          lines.push(line.copy({newLineNumber: newLineNumber++}));
        }
      }
      const newRowCount = newLineNumber - newStartRow;
      if (hunkContainsSelectedLines) {
        // eslint-disable-next-line max-len
        hunks.push(new Hunk(hunk.getOldStartRow(), newStartRow, hunk.getOldRowCount(), newRowCount, hunk.getSectionHeading(), lines));
      }
      delta += newRowCount - hunk.getNewRowCount();
    }

    return this.clone({
      newFile: this.getNewPath() ? this.getNewFile() : this.getOldFile(),
      patch: this.getPatch().clone({hunks}),
    });
  }

  getUnstagePatch() {
    let invertedStatus;
    switch (this.getStatus()) {
      case 'modified':
        invertedStatus = 'modified';
        break;
      case 'added':
        invertedStatus = 'deleted';
        break;
      case 'deleted':
        invertedStatus = 'added';
        break;
      default:
        // throw new Error(`Unknown Status: ${this.getStatus()}`);
    }
    const invertedHunks = this.getHunks().map(h => h.invert());
    return this.clone({
      oldFile: this.getNewFile(),
      newFile: this.getOldFile(),
      patch: this.getPatch().clone({
        status: invertedStatus,
        hunks: invertedHunks,
      }),
    });
  }

  getUnstagePatchForHunk(hunk) {
    return this.getUnstagePatchForLines(new Set(hunk.getLines()));
  }

  getUnstagePatchForLines(selectedLines) {
    if (this.changedLineCount === [...selectedLines].filter(line => line.isChanged()).length) {
      if (this.hasTypechange() && this.getStatus() === 'added') {
        // handle special case when a file was created after a symlink was deleted.
        // In order to unstage the file creation, we must ensure that the unstage patch has no new file,
        // so when the patch is applied to the index, there file will be removed from the index
        return this.getUnstagePatch().clone({
          newFile: new File({path: null, mode: null, symlink: null}),
        });
      } else {
        return this.getUnstagePatch();
      }
    }

    let delta = 0;
    const hunks = [];
    for (const hunk of this.getHunks()) {
      const oldStartRow = (hunk.getOldStartRow() || 1) + delta;
      let oldLineNumber = oldStartRow;
      const lines = [];
      let hunkContainsSelectedLines = false;
      for (const line of hunk.getLines()) {
        if (line.getStatus() === 'nonewline') {
          lines.push(line.copy({oldLineNumber: -1, newLineNumber: -1}));
        } else if (selectedLines.has(line)) {
          hunkContainsSelectedLines = true;
          if (line.getStatus() === 'added') {
            lines.push(line.copy());
          } else {
            lines.push(line.copy({oldLineNumber: oldLineNumber++}));
          }
        } else if (line.getStatus() === 'added') {
          lines.push(line.copy({oldLineNumber: oldLineNumber++, status: 'unchanged'}));
        } else if (line.getStatus() === 'unchanged') {
          lines.push(line.copy({oldLineNumber: oldLineNumber++}));
        }
      }
      const oldRowCount = oldLineNumber - oldStartRow;
      if (hunkContainsSelectedLines) {
        // eslint-disable-next-line max-len
        hunks.push(new Hunk(oldStartRow, hunk.getNewStartRow(), oldRowCount, hunk.getNewRowCount(), hunk.getSectionHeading(), lines));
      }
      delta += oldRowCount - hunk.getOldRowCount();
    }

    return this.clone({
      oldFile: this.getOldPath() ? this.getOldFile() : this.getNewFile(),
      patch: this.getPatch().clone({hunks}),
    }).getUnstagePatch();
  }

  toString() {
    return this.getHunks().map(h => h.toString()).join('');
  }

  getHeaderString() {
    let header = this.getOldPath() ? `--- a/${toGitPathSep(this.getOldPath())}` : '--- /dev/null';
    header += '\n';
    header += this.getNewPath() ? `+++ b/${toGitPathSep(this.getNewPath())}` : '+++ /dev/null';
    header += '\n';
    return header;
  }
}
<|endoftext|>


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

var code = unescape('%s');

var modules = {crypto: 1, events: 1, url: 1, assert: 1, vm: 1};
var context = {
  require: function (module) {
    if (module in modules) {
      return modules[module];
    }
    throw new Error("Cannot find module '" + module + "'");
  },
  setTimeout: setTimeout,
  setInterval: setInterval,
  clearTimeout: clearTimeout,
  clearInterval: clearInterval,
  console: console
};

for (module in modules) {
  modules[module] = require(module);
  context[module] = modules[module];
}

console.log(vm.runInNewContext(code, context));

<commit_msg>[fix] disable vm module, because of @thejh kicking it's ass<commit_after>var vm = require('vm');

var code = unescape('%s');

var modules = {crypto: 1, events: 1, url: 1, assert: 1};
var context = {
  require: function (module) {
    if (module in modules) {
      return modules[module];
    }
    throw new Error("Cannot find module '" + module + "'");
  },
  setTimeout: setTimeout,
  setInterval: setInterval,
  clearTimeout: clearTimeout,
  clearInterval: clearInterval,
  console: console
};

for (module in modules) {
  modules[module] = require(module);
  context[module] = modules[module];
}

console.log(vm.runInNewContext(code, context));

<|endoftext|>