<commit_before>import _ from 'lodash/fp'
import { dotJoinWith, zipObjectDeepWith } from './array'
import { overNone } from './logic'
import { isNotNil, isBlank } from './lang'
import {
  reduceIndexed,
  pickIn,
  getIn,
  hasIn,
  mapIndexed,
  mapValuesIndexed,
} from './conversion'
import { findApply } from './collection'
import { aspects } from './aspect'
const noCap = _.convert({ cap: false })

// (k, v) -> {k: v}
export const singleObject = _.curry((key, value) => ({ [key]: value }))
export const singleObjectR = _.flip(singleObject)

// Formerly objToObjArr
// ({a, b}) -> [{a}, {b}]
export const chunkObject = value =>
  _.isArray(value) ? value : _.map(_.spread(singleObject), _.toPairs(value))

// Remove properties with falsey values: ({ a: 1, b: null, c: false}) -> {a:1}
export const compactObject = _.pickBy(_.identity)

export const isEmptyObject = _.isEqual({})

export const isNotEmptyObject = _.negate(isEmptyObject)

// { a:1, b:{}, c:2 } -> { a:1, c:2 }
export const stripEmptyObjects = _.pickBy(isNotEmptyObject)

// const crazyBS = (f, g) => (a, b) => f(a)(g(b))

// { a: { b: 1, c: 2 } }, [ 'b' ] -> { a: { b: 1 } }
export const pickInto = (map, source) => _.mapValues(pickIn(source), map)

export const renameProperty = _.curry((from, to, target) =>
  _.has(from, target)
    ? _.flow(
        x => _.set(to, _.get(from, x), x),
        _.unset(from)
      )(target)
    : target
)

// { x:['a','b'], y:1 } -> [{ x:'a', y:1 }, { x:'b', y:1 }] just like mongo's `$unwind`
export const unwind = _.curry((prop, x) =>
  _.map(y => _.set(prop, y, x), _.get(prop, x))
)

export const isFlatObject = overNone([_.isPlainObject, _.isArray])

// { a: { b: { c: 1 } } } => { 'a.b.c' : 1 }
export const flattenObject = (input, paths) =>
  reduceIndexed(
    (output, value, key) =>
      _.merge(
        output,
        (isFlatObject(value) ? singleObjectR : flattenObject)(
          value,
          dotJoinWith(isNotNil)([paths, key])
        )
      ),
    {},
    input
  )

// { 'a.b.c' : 1 } => { a: { b: { c: 1 } } }
export const unflattenObject = x => _.zipObjectDeep(_.keys(x), _.values(x))

// Returns true if object keys are only elements from signature list (but does not require all signature keys to be present)
export const matchesSignature = _.curry(
  (signature, value) =>
    _.isObject(value) && !_.difference(_.keys(value), signature).length
)

// `_.matches` that returns true if one or more of the conditions match instead of all
export const matchesSome = _.flow(
  chunkObject,
  _.map(_.matches),
  _.overSome
)

// Checks if a property deep in a given item equals to a given value
export const compareDeep = _.curry(
  (path, item, value) => _.get(path, item) === value
)

//Depreacted in favor of _.update version from lodash
export const mapProp = aspects.deprecate('mapProp', '1.46.0', '_.update')(
  noCap.update
)

// `_.get` that returns the target object if lookup fails
export let getOrReturn = _.curry((prop, x) => _.getOr(x, prop, x))
// `_.get` that returns the prop if lookup fails
export let alias = _.curry((prop, x) => _.getOr(prop, prop, x))
// flipped alias
export let aliasIn = _.curry((x, prop) => _.getOr(prop, prop, x))

// A `_.get` that takes an array of paths and returns the value at the first path that matches
export let cascade = _.curryN(2, (paths, obj, defaultValue) =>
  _.flow(
    findApply(x => x && _.iteratee(x)(obj)),
    _.defaultTo(defaultValue)
  )(paths)
)

// Flipped cascade
export let cascadeIn = _.curryN(2, (obj, paths, defaultValue) =>
  cascade(paths, obj, defaultValue)
)
// A `_.get` that takes an array of paths and returns the first path that matched
export let cascadeKey = _.curry((paths, obj) => _.find(getIn(obj), paths))
// A `_.get` that takes an array of paths and returns the first path that exists
export let cascadePropKey = _.curry((paths, obj) => _.find(hasIn(obj), paths))
// A `_.get` that takes an array of paths and returns the first value that has an existing path
export let cascadeProp = _.curry((paths, obj) =>
  _.get(cascadePropKey(paths, obj), obj)
)

export let unkeyBy = _.curry((keyName, obj) =>
  mapIndexed((val, key) => _.extend(val, { [keyName || key]: key }))(obj)
)

export let simpleDiff = (original, deltas) => {
  let o = flattenObject(original)
  return _.flow(
    flattenObject,
    mapValuesIndexed((to, field) => ({ from: o[field], to })),
    _.omitBy(x => x.from === x.to)
  )(deltas)
}
export let simpleDiffArray = _.flow(
  simpleDiff,
  unkeyBy('field')
)

export let diff = (original, deltas) => {
  let o = flattenObject(original)
  let d = flattenObject(deltas)
  return _.flow(
    mapValuesIndexed((_, field) => ({ from: o[field], to: d[field] })),
    _.omitBy(x => x.from === x.to)
  )(_.merge(o, d))
}
export let diffArray = _.flow(
  diff,
  unkeyBy('field')
)

// A `_.pick` that mutates the object
export let pickOn = (paths = [], obj = {}) =>
  _.flow(
    _.keys,
    _.map(key => {
      if (!_.includes(key, paths)) {
        delete obj[key]
      }
    })
  )(obj)

// Straight from the lodash docs
export let mergeAllArrays = _.mergeAllWith((objValue, srcValue) => {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue)
  }
})
// { a: [x, y, z], b: [x] } -> { x: [a, b], y: [a], z: [a] }
export let invertByArray = _.flow(
  mapIndexed((arr, key) => zipObjectDeepWith(arr, () => [key])),
  mergeAllArrays
)

// key -> { a: { x: 1 }, b: { y: 2 } } -> { a: { x: 1, key: 'a' }, b: { y: 2, key: 'b' } }
export const stampKey = _.curry((key, x) =>
  mapValuesIndexed((val, k) => ({ ...val, [key]: k }), x)
)

export let omitNil = x => _.omitBy(_.isNil, x)
export let omitNull = x => _.omitBy(_.isNull, x)
export let omitBlank = x => _.omitBy(isBlank, x)
export let omitEmpty = x => _.omitBy(_.isEmpty, x)

// (f, g) -> (x, y) -> {...f(x, y), ...g(x, y)}
export let mergeOverAll = fns =>
  _.flow(
    _.over(fns),
    _.mergeAll
  )
<commit_msg>add getWith, expandObject, expandObjectBy<commit_after>import _ from 'lodash/fp'
import { dotJoinWith, zipObjectDeepWith } from './array'
import { overNone } from './logic'
import { isNotNil, isBlank } from './lang'
import {
  reduceIndexed,
  pickIn,
  getIn,
  hasIn,
  mapIndexed,
  mapValuesIndexed,
} from './conversion'
import { findApply } from './collection'
import { aspects } from './aspect'
const noCap = _.convert({ cap: false })

// (k, v) -> {k: v}
export const singleObject = _.curry((key, value) => ({ [key]: value }))
export const singleObjectR = _.flip(singleObject)

// Formerly objToObjArr
// ({a, b}) -> [{a}, {b}]
export const chunkObject = value =>
  _.isArray(value) ? value : _.map(_.spread(singleObject), _.toPairs(value))

// Remove properties with falsey values: ({ a: 1, b: null, c: false}) -> {a:1}
export const compactObject = _.pickBy(_.identity)

export const isEmptyObject = _.isEqual({})

export const isNotEmptyObject = _.negate(isEmptyObject)

// { a:1, b:{}, c:2 } -> { a:1, c:2 }
export const stripEmptyObjects = _.pickBy(isNotEmptyObject)

// const crazyBS = (f, g) => (a, b) => f(a)(g(b))

// { a: { b: 1, c: 2 } }, [ 'b' ] -> { a: { b: 1 } }
export const pickInto = (map, source) => _.mapValues(pickIn(source), map)

export const renameProperty = _.curry((from, to, target) =>
  _.has(from, target)
    ? _.flow(
        x => _.set(to, _.get(from, x), x),
        _.unset(from)
      )(target)
    : target
)

// { x:['a','b'], y:1 } -> [{ x:'a', y:1 }, { x:'b', y:1 }] just like mongo's `$unwind`
export const unwind = _.curry((prop, x) =>
  _.map(y => _.set(prop, y, x), _.get(prop, x))
)

export const isFlatObject = overNone([_.isPlainObject, _.isArray])

// { a: { b: { c: 1 } } } => { 'a.b.c' : 1 }
export const flattenObject = (input, paths) =>
  reduceIndexed(
    (output, value, key) =>
      _.merge(
        output,
        (isFlatObject(value) ? singleObjectR : flattenObject)(
          value,
          dotJoinWith(isNotNil)([paths, key])
        )
      ),
    {},
    input
  )

// { 'a.b.c' : 1 } => { a: { b: { c: 1 } } }
export const unflattenObject = x => _.zipObjectDeep(_.keys(x), _.values(x))

// Returns true if object keys are only elements from signature list (but does not require all signature keys to be present)
export const matchesSignature = _.curry(
  (signature, value) =>
    _.isObject(value) && !_.difference(_.keys(value), signature).length
)

// `_.matches` that returns true if one or more of the conditions match instead of all
export const matchesSome = _.flow(
  chunkObject,
  _.map(_.matches),
  _.overSome
)

// Checks if a property deep in a given item equals to a given value
export const compareDeep = _.curry(
  (path, item, value) => _.get(path, item) === value
)

//Depreacted in favor of _.update version from lodash
export const mapProp = aspects.deprecate('mapProp', '1.46.0', '_.update')(
  noCap.update
)

// `_.get` that returns the target object if lookup fails
export let getOrReturn = _.curry((prop, x) => _.getOr(x, prop, x))
// `_.get` that returns the prop if lookup fails
export let alias = _.curry((prop, x) => _.getOr(prop, prop, x))
// flipped alias
export let aliasIn = _.curry((x, prop) => _.getOr(prop, prop, x))

// A `_.get` that takes an array of paths and returns the value at the first path that matches
export let cascade = _.curryN(2, (paths, obj, defaultValue) =>
  _.flow(
    findApply(x => x && _.iteratee(x)(obj)),
    _.defaultTo(defaultValue)
  )(paths)
)

// Flipped cascade
export let cascadeIn = _.curryN(2, (obj, paths, defaultValue) =>
  cascade(paths, obj, defaultValue)
)
// A `_.get` that takes an array of paths and returns the first path that matched
export let cascadeKey = _.curry((paths, obj) => _.find(getIn(obj), paths))
// A `_.get` that takes an array of paths and returns the first path that exists
export let cascadePropKey = _.curry((paths, obj) => _.find(hasIn(obj), paths))
// A `_.get` that takes an array of paths and returns the first value that has an existing path
export let cascadeProp = _.curry((paths, obj) =>
  _.get(cascadePropKey(paths, obj), obj)
)

export let unkeyBy = _.curry((keyName, obj) =>
  mapIndexed((val, key) => _.extend(val, { [keyName || key]: key }))(obj)
)

export let simpleDiff = (original, deltas) => {
  let o = flattenObject(original)
  return _.flow(
    flattenObject,
    mapValuesIndexed((to, field) => ({ from: o[field], to })),
    _.omitBy(x => x.from === x.to)
  )(deltas)
}
export let simpleDiffArray = _.flow(
  simpleDiff,
  unkeyBy('field')
)

export let diff = (original, deltas) => {
  let o = flattenObject(original)
  let d = flattenObject(deltas)
  return _.flow(
    mapValuesIndexed((_, field) => ({ from: o[field], to: d[field] })),
    _.omitBy(x => x.from === x.to)
  )(_.merge(o, d))
}
export let diffArray = _.flow(
  diff,
  unkeyBy('field')
)

// A `_.pick` that mutates the object
export let pickOn = (paths = [], obj = {}) =>
  _.flow(
    _.keys,
    _.map(key => {
      if (!_.includes(key, paths)) {
        delete obj[key]
      }
    })
  )(obj)

// Straight from the lodash docs
export let mergeAllArrays = _.mergeAllWith((objValue, srcValue) => {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue)
  }
})
// { a: [x, y, z], b: [x] } -> { x: [a, b], y: [a], z: [a] }
export let invertByArray = _.flow(
  mapIndexed((arr, key) => zipObjectDeepWith(arr, () => [key])),
  mergeAllArrays
)

// key -> { a: { x: 1 }, b: { y: 2 } } -> { a: { x: 1, key: 'a' }, b: { y: 2, key: 'b' } }
export const stampKey = _.curry((key, x) =>
  mapValuesIndexed((val, k) => ({ ...val, [key]: k }), x)
)

export let omitNil = x => _.omitBy(_.isNil, x)
export let omitNull = x => _.omitBy(_.isNull, x)
export let omitBlank = x => _.omitBy(isBlank, x)
export let omitEmpty = x => _.omitBy(_.isEmpty, x)

// (f, g) -> (x, y) -> {...f(x, y), ...g(x, y)}
export let mergeOverAll = fns =>
  _.flow(
    _.over(fns),
    _.mergeAll
  )

// (x -> y) -> k -> {k: x} -> y
export let getWith = _.curry((customizer, path, object) =>
  customizer(_.get(path, object))
)

// ({a} -> {b}) -> {a} -> {a, b}
export let expandObject = _.curry((transform, obj) => ({
  ...obj,
  ...transform(obj),
}))

// k -> (a -> {b}) -> {k: a} -> {a, b}
export let expandObjectBy = _.curry((key, fn, obj) =>
  expandObject(getWith(fn, key))(obj)
)
<|endoftext|>


<commit_before>'use strict';

const Stats = require('fast-stats').Stats,
  get = require('lodash.get'),
  set = require('lodash.set');

function percentileName(percentile) {
  if (percentile === 0) {
    return 'min';
  } else if (percentile === 100) {
    return 'max';
  } else {
    return 'p' + String(percentile).replace('.', '_');
  }
}

module.exports = {

  /**
   * Create or update a fast-stats#Stats object in target at path.
   */
  pushStats(target, path, data) {
    if (typeof data !== 'number')
      throw new Error('Tried to add ' + data + ' to stats');

    const stats = get(target, path, new Stats());
    stats.push(data);
    set(target, path, stats);
  },

  pushGroupStats(target, domainTarget, path, data) {
    this.pushStats(target, path, data);
    this.pushStats(domainTarget, path, data);
  },

  /**
   * Summarize stats and put result in target at path
   */
  setStatsSummary(target, path, stats) {
    set(target, path, this.summarizeStats(stats));
  },

  summarizeStats(stats, options) {
    if (stats.length === 0) {
      return undefined;
    }

    options = options || {};
    let percentiles = options.percentiles || [0, 90, 100];
    let decimals = options.decimals || 0;
    let data = {
      median: stats.median().toFixed(decimals),
      mean: stats.amean().toFixed(decimals)
    };
    percentiles.forEach((p) => {
      let name = percentileName(p);
      const percentile = stats.percentile(p);
      if (Number.isFinite(percentile)) {
        data[name] = percentile.toFixed(decimals);
      } else {
        throw new Error('Failed to calculate ' + name + ' for stats: ' + JSON.stringify(stats, null, 2));
      }
    });
    if (options.includeSum) {
      data.sum = stats.Σ().toFixed(decimals);
    }

    return data;
  }
};
<commit_msg>Better logging when adding undefined value to stat<commit_after>'use strict';

const Stats = require('fast-stats').Stats,
  get = require('lodash.get'),
  set = require('lodash.set');

function percentileName(percentile) {
  if (percentile === 0) {
    return 'min';
  } else if (percentile === 100) {
    return 'max';
  } else {
    return 'p' + String(percentile).replace('.', '_');
  }
}

module.exports = {

  /**
   * Create or update a fast-stats#Stats object in target at path.
   */
  pushStats(target, path, data) {
    if (typeof data !== 'number')
      throw new Error(`Tried to add ${data} to stats for path ${path}`);

    const stats = get(target, path, new Stats());
    stats.push(data);
    set(target, path, stats);
  },

  pushGroupStats(target, domainTarget, path, data) {
    this.pushStats(target, path, data);
    this.pushStats(domainTarget, path, data);
  },

  /**
   * Summarize stats and put result in target at path
   */
  setStatsSummary(target, path, stats) {
    set(target, path, this.summarizeStats(stats));
  },

  summarizeStats(stats, options) {
    if (stats.length === 0) {
      return undefined;
    }

    options = options || {};
    let percentiles = options.percentiles || [0, 90, 100];
    let decimals = options.decimals || 0;
    let data = {
      median: stats.median().toFixed(decimals),
      mean: stats.amean().toFixed(decimals)
    };
    percentiles.forEach((p) => {
      let name = percentileName(p);
      const percentile = stats.percentile(p);
      if (Number.isFinite(percentile)) {
        data[name] = percentile.toFixed(decimals);
      } else {
        throw new Error('Failed to calculate ' + name + ' for stats: ' + JSON.stringify(stats, null, 2));
      }
    });
    if (options.includeSum) {
      data.sum = stats.Σ().toFixed(decimals);
    }

    return data;
  }
};
<|endoftext|>


<commit_before>const fs = require('fs');

var redTransform = function() {
  fs.readFile('../test/palette-bitmap.bmp', function(err, data) {
    if (err) console.log(err);
    var averageColor = 0;
    for (var i = 54; i < 1078; i++) {
      if(i % 4 !== 0) {
        averageColor += data[i];
      } else {
        for (var j = 3; j > 0; j--) {
          data[i - j] = averageColor / 256;
          averageColor = 0;
        }
      }
    }
    fs.writeFile('../test/red-palette-bitmap.bmp', data);
  });
};

redTransform();
<commit_msg>removed transform-red-bitmap.js file<commit_after><|endoftext|>


<commit_before>// Dependencies
var findRoot = require('find-root')
var minimatch = require('minimatch')
var pkgConfig = require('pkg-config')
var binPath = require('./bin-path')

module.exports = function checkStyleSettings (linterName, filePath) {
  // Default value
  var styleSettings = false

  // Try to get the project's absolute path
  // NOTE: the project's path returned will be
  // from the nearest package.json (direction upward)
  try {
    var projectPath = findRoot(filePath)
  } catch (e) {
    return
  }

  // Get relative path of the filePath
  var relativeFilePath = filePath.replace(projectPath, '').substring(1)

  var options = { cwd: filePath, root: 'standard', cache: false }

  switch (linterName) {
    case 'standard':
      styleSettings = pkgConfig(null, options)
      break

    case 'semistandard':
      options.root = 'semistandard'
      styleSettings = pkgConfig(null, options)
      break

    case 'happiness':
      options.root = 'happiness'
      styleSettings = pkgConfig(null, options)
      break

    default:
      throw new Error('Something went wrong. Unknown linter "' + linterName + '"')
  }

  if (styleSettings) {
    // Check parser
    if (styleSettings.parser) {
      this.args.push('--parser', styleSettings.parser)
    }

    // If ignore glob patterns are present
    if (styleSettings.ignore) {
      var ignoreGlobPatterns = []
      ignoreGlobPatterns = ignoreGlobPatterns.concat(styleSettings.ignore)

      ignoreGlobPatterns = ignoreGlobPatterns.some(function (pattern) {
        return minimatch(relativeFilePath, pattern)
      })

      // If found something return false
      // telling linter-js-standard that this
      // file should be ignored because
      // the glob pattern was matched
      if (ignoreGlobPatterns) {
        this.styleObj = {
          name: 'no-style',
          execPath: binPath.noStyle
        }
      }
    }
  }

  // fallback
  return
}
<commit_msg>fix style settings<commit_after>// Dependencies
var findRoot = require('find-root')
var minimatch = require('minimatch')
var pkgConfig = require('pkg-config')
var binPath = require('./bin-path')

module.exports = function checkStyleSettings (filePath) {
  // Default value
  var styleSettings = false

  // Try to get the project's absolute path
  // NOTE: the project's path returned will be
  // from the nearest package.json (direction upward)
  try {
    var projectPath = findRoot(filePath)
  } catch (e) {
    return
  }

  // Get relative path of the filePath
  var relativeFilePath = filePath.replace(projectPath, '').substring(1)

  var options = { cwd: filePath, root: 'standard', cache: false }

  switch (this.styleObj.name) {
    case 'standard':
      styleSettings = pkgConfig(null, options)
      break

    case 'semistandard':
      options.root = 'semistandard'
      styleSettings = pkgConfig(null, options)
      break

    case 'happiness':
      options.root = 'happiness'
      styleSettings = pkgConfig(null, options)
      break

    default:
      throw new Error('Something went wrong. Unknown linter "' + this.styleObj.name + '"')
  }

  if (styleSettings) {
    // Check parser
    if (styleSettings.parser) {
      this.args.push('--parser', styleSettings.parser)
    }

    // If ignore glob patterns are present
    if (styleSettings.ignore) {
      var ignoreGlobPatterns = []
      ignoreGlobPatterns = ignoreGlobPatterns.concat(styleSettings.ignore)

      ignoreGlobPatterns = ignoreGlobPatterns.some(function (pattern) {
        return minimatch(relativeFilePath, pattern)
      })

      // If found something return false
      // telling linter-js-standard that this
      // file should be ignored because
      // the glob pattern was matched
      if (ignoreGlobPatterns) {
        this.styleObj = {
          name: 'no-style',
          execPath: binPath.noStyle
        }
      }
    }
  }

  // fallback
  return
}
<|endoftext|>


<commit_before>import Transport from "./transport.js"

const INITIAL_PING_TIMEOUT   =  2000;
const KEEPALIVE_PING_TIMEOUT = 20000;

const sendPing = (socket) => {
  socket.send(JSON.stringify({ping: 'PING'}))
}

const getWebSocket = () => {
  return (typeof window !== 'undefined' && window !== null ? window.WebSocket : undefined) || (typeof global !== 'undefined' && global !== null ? global.WebSocket : undefined)
}

export default class WebSocketTransport extends Transport {
  name() { return 'WebSocket'; }

  static ieSupported() { return (document.documentMode || 10) > 9; }
  static supported() { return !!getWebSocket(); } // Check if WebSocket is an object in the window.

  constructor(args) {
    super(args);
    this._sendMessage = this._sendMessage.bind(this);
    this._request = this._request.bind(this);
    this._protocol = this._protocol.bind(this);
    this._requestParams = this._requestParams.bind(this);
    this._open = this._open.bind(this);
    this._lookForInitialPong = this._lookForInitialPong.bind(this);
    this.sendStartingMessageSequence = this.sendStartingMessageSequence.bind(this);
    this.stop = this.stop.bind(this);
    this._message = this._message.bind(this);
    this._close = this._close.bind(this);
    this._error = this._error.bind(this);
    this._cleanUp = this._cleanUp.bind(this);
    this._restartKeepAlive = this._restartKeepAlive.bind(this);
    this._clearKeepalive = this._clearKeepalive.bind(this);
    // Configrations specifically for web sockets
    if (!this.config.webSocket) { this.config.webSocket = {}; }
    this.config.webSocket.connectionVerified = this.config.connectionVerified;
  }

  _sendMessage(message) {
    return (this.socket != null ? this.socket.send(JSON.stringify(message)) : undefined);
  }

  _request() {
    // Run this in a try/catch block because IE10 inside of a .NET control
    // complains about security zones.
    try {
      const ws = getWebSocket();
      this.socket = new ws(`${this._protocol()}:${this.config.uri}?${$.param(this._requestParams())}`);
      this.socket.onopen    = this._open;
      this.socket.onclose   = this._close;
      this.socket.onerror   = this._error;
      return this.socket.onmessage = this._lookForInitialPong;
    } catch (err) {
      if (this.config.failed) {
        return this.config.failed(err);
      } else {
        return (typeof console !== 'undefined' && console !== null ? console.log(err) : undefined);
      }
    }
  }

  // Protocol schema we should use for talking to firehose server.
  _protocol() {
    if (this.config.ssl) { return "wss"; } else { return "ws"; }
  }

  _requestParams() {
    if (typeof this.config.params === "function") {
      return this.config.params();
    } else {
      return this.config.params;
    }
  }

  _open() {
    return sendPing(this.socket);
  }

  _lookForInitialPong(event) {
    this._restartKeepAlive();
    if (this._isPong((() => { try { return JSON.parse(event.data); } catch (e) { return {}; } })())) {
      if (this._lastMessageSequence != null) {
        // don't callback to connectionVerified on subsequent reconnects
        return this.sendStartingMessageSequence(this._lastMessageSequence);
      } else { return this.config.webSocket.connectionVerified(this); }
    }
  }

  sendStartingMessageSequence(message_sequence) {
    this._lastMessageSequence = message_sequence;
    this.socket.onmessage     = this._message;
    this._sendMessage({message_sequence});
    this._needToNotifyOfDisconnect = true;
    return Transport.prototype._open.call(this);
  }

  stop() {
    return this._cleanUp();
  }

  _message(event) {
    const frame = this.config.parse(event.data);
    this._restartKeepAlive();

    if (this._isSubscriptionFailed(frame)) {
      return this.config.subscriptionFailed(frame);
    }

    if (!this._isPong(frame)) {
      this._lastMessageSequence = frame.last_sequence;
      return this.config.message(this.config.parse(frame.message));
    }
  }

  _close(event) {
    if ((event != null ? event.wasClean : undefined)) { return this._cleanUp();
    } else { return this._error(event); }
  }

  _error(event) {
    this._cleanUp();
    if (this._needToNotifyOfDisconnect) {
      this._needToNotifyOfDisconnect = false;
      this.config.disconnected();
    }
    if (this._succeeded) {
      return this.connect(this._retryDelay);
    } else if (this.config.failed) {
      return this.config.failed(event);
    }
  }

  _cleanUp() {
    this._clearKeepalive();
    if (this.socket != null) {
      this.socket.onopen    = null;
      this.socket.onclose   = null;
      this.socket.onerror   = null;
      this.socket.onmessage = null;
      return this.socket.close();
    }
  }
      // delete @socket

  _restartKeepAlive() {
    const doPing = () => {
      sendPing(this.socket);
      return setNextKeepAlive();
    };
    var setNextKeepAlive = () => {
      return this.keepaliveTimeout = setTimeout(doPing, KEEPALIVE_PING_TIMEOUT);
    };
    this._clearKeepalive();
    return setNextKeepAlive();
  }

  _clearKeepalive() {
    if (this.keepaliveTimeout != null) {
      clearTimeout(this.keepaliveTimeout);
      return this.keepaliveTimeout = null;
    }
  }

  _isPong(o) {
    return o.pong === 'PONG';
  }

  _isSubscriptionFailed(o) {
    return o.error === 'Subscription Failed';
  }
}
<commit_msg>Call this.config.error as the last resort when there's a WS error<commit_after>import Transport from "./transport.js"

const INITIAL_PING_TIMEOUT   =  2000;
const KEEPALIVE_PING_TIMEOUT = 20000;

const sendPing = (socket) => {
  socket.send(JSON.stringify({ping: 'PING'}))
}

const getWebSocket = () => {
  return (typeof window !== 'undefined' && window !== null ? window.WebSocket : undefined) || (typeof global !== 'undefined' && global !== null ? global.WebSocket : undefined)
}

export default class WebSocketTransport extends Transport {
  name() { return 'WebSocket'; }

  static ieSupported() { return (document.documentMode || 10) > 9; }
  static supported() { return !!getWebSocket(); } // Check if WebSocket is an object in the window.

  constructor(args) {
    super(args);
    this._sendMessage = this._sendMessage.bind(this);
    this._request = this._request.bind(this);
    this._protocol = this._protocol.bind(this);
    this._requestParams = this._requestParams.bind(this);
    this._open = this._open.bind(this);
    this._lookForInitialPong = this._lookForInitialPong.bind(this);
    this.sendStartingMessageSequence = this.sendStartingMessageSequence.bind(this);
    this.stop = this.stop.bind(this);
    this._message = this._message.bind(this);
    this._close = this._close.bind(this);
    this._error = this._error.bind(this);
    this._cleanUp = this._cleanUp.bind(this);
    this._restartKeepAlive = this._restartKeepAlive.bind(this);
    this._clearKeepalive = this._clearKeepalive.bind(this);
    // Configrations specifically for web sockets
    if (!this.config.webSocket) { this.config.webSocket = {}; }
    this.config.webSocket.connectionVerified = this.config.connectionVerified;
  }

  _sendMessage(message) {
    return (this.socket != null ? this.socket.send(JSON.stringify(message)) : undefined);
  }

  _request() {
    // Run this in a try/catch block because IE10 inside of a .NET control
    // complains about security zones.
    try {
      const ws = getWebSocket();
      this.socket = new ws(`${this._protocol()}:${this.config.uri}?${$.param(this._requestParams())}`);
      this.socket.onopen    = this._open;
      this.socket.onclose   = this._close;
      this.socket.onerror   = this._error;
      return this.socket.onmessage = this._lookForInitialPong;
    } catch (err) {
      if (this.config.failed) {
        return this.config.failed(err);
      } else {
        return (typeof console !== 'undefined' && console !== null ? console.log(err) : undefined);
      }
    }
  }

  // Protocol schema we should use for talking to firehose server.
  _protocol() {
    if (this.config.ssl) { return "wss"; } else { return "ws"; }
  }

  _requestParams() {
    if (typeof this.config.params === "function") {
      return this.config.params();
    } else {
      return this.config.params;
    }
  }

  _open() {
    return sendPing(this.socket);
  }

  _lookForInitialPong(event) {
    this._restartKeepAlive();
    if (this._isPong((() => { try { return JSON.parse(event.data); } catch (e) { return {}; } })())) {
      if (this._lastMessageSequence != null) {
        // don't callback to connectionVerified on subsequent reconnects
        return this.sendStartingMessageSequence(this._lastMessageSequence);
      } else { return this.config.webSocket.connectionVerified(this); }
    }
  }

  sendStartingMessageSequence(message_sequence) {
    this._lastMessageSequence = message_sequence;
    this.socket.onmessage     = this._message;
    this._sendMessage({message_sequence});
    this._needToNotifyOfDisconnect = true;
    return Transport.prototype._open.call(this);
  }

  stop() {
    return this._cleanUp();
  }

  _message(event) {
    const frame = this.config.parse(event.data);
    this._restartKeepAlive();

    if (this._isSubscriptionFailed(frame)) {
      return this.config.subscriptionFailed(frame);
    }

    if (!this._isPong(frame)) {
      this._lastMessageSequence = frame.last_sequence;
      return this.config.message(this.config.parse(frame.message));
    }
  }

  _close(event) {
    if ((event != null ? event.wasClean : undefined)) { return this._cleanUp();
    } else { return this._error(event); }
  }

  _error(event) {
    this._cleanUp();
    if (this._needToNotifyOfDisconnect) {
      this._needToNotifyOfDisconnect = false;
      this.config.disconnected();
    }
    if (this._succeeded) {
      return this.connect(this._retryDelay);
    } else if (this.config.failed) {
      return this.config.failed(event);
    } else {
      return this.config.error(event)
    }
  }

  _cleanUp() {
    this._clearKeepalive();
    if (this.socket != null) {
      this.socket.onopen    = null;
      this.socket.onclose   = null;
      this.socket.onerror   = null;
      this.socket.onmessage = null;
      return this.socket.close();
    }
  }
      // delete @socket

  _restartKeepAlive() {
    const doPing = () => {
      sendPing(this.socket);
      return setNextKeepAlive();
    };
    var setNextKeepAlive = () => {
      return this.keepaliveTimeout = setTimeout(doPing, KEEPALIVE_PING_TIMEOUT);
    };
    this._clearKeepalive();
    return setNextKeepAlive();
  }

  _clearKeepalive() {
    if (this.keepaliveTimeout != null) {
      clearTimeout(this.keepaliveTimeout);
      return this.keepaliveTimeout = null;
    }
  }

  _isPong(o) {
    return o.pong === 'PONG';
  }

  _isSubscriptionFailed(o) {
    return o.error === 'Subscription Failed';
  }
}
<|endoftext|>


<commit_before>const { DateTime } = require('luxon');

const schedule = require('./schedule');
const { getUpdatedPackageFiles } = require('./get-updated');
const { getAdditionalFiles } = require('../../manager/npm/post-update');
const { commitFilesToBranch } = require('./commit');
const { getParentBranch } = require('./parent');
const { tryBranchAutomerge } = require('./automerge');
const { setUnpublishable } = require('./status-checks');
const { prAlreadyExisted } = require('./check-existing');
const prWorker = require('../pr');
const { appName, appSlug } = require('../../config/app-strings');

const { isScheduledNow } = schedule;

module.exports = {
  processBranch,
};

async function processBranch(branchConfig, prHourlyLimitReached, packageFiles) {
  const config = { ...branchConfig };
  const dependencies = config.upgrades
    .map(upgrade => upgrade.depName)
    .filter(v => v) // remove nulls (happens for lock file maintenance)
    .filter((value, i, list) => list.indexOf(value) === i); // remove duplicates
  logger.setMeta({
    repository: config.repository,
    branch: config.branchName,
    dependencies,
  });
  logger.debug(`processBranch with ${branchConfig.upgrades.length} upgrades`);
  logger.trace({ config });
  await platform.setBaseBranch(config.baseBranch);
  const branchExists = await platform.branchExists(config.branchName);
  const branchPr = await platform.getBranchPr(config.branchName);
  logger.debug(`branchExists=${branchExists}`);
  const masterIssueCheck = (config.masterIssueChecks || {})[config.branchName];
  // istanbul ignore if
  if (masterIssueCheck) {
    logger.info('Branch has been checked in master issue: ' + masterIssueCheck);
  }
  try {
    logger.debug(
      `Branch has ${dependencies ? dependencies.length : 0} upgrade(s)`
    );

    // Check if branch already existed
    const existingPr = branchPr ? undefined : await prAlreadyExisted(config);
    if (existingPr && !masterIssueCheck) {
      logger.debug(
        { prTitle: config.prTitle },
        'Closed PR already exists. Skipping branch.'
      );
      if (existingPr.state === 'closed') {
        const subject = `${appName} Ignore Notification`;
        let content;
        if (config.updateType === 'major') {
          content = `As this PR has been closed unmerged, ${appName} will ignore this upgrade and you will not receive PRs for *any* future ${
            config.newMajor
          }.x releases. However, if you upgrade to ${
            config.newMajor
          }.x manually then ${appName} will then reenable updates for minor and patch updates automatically.`;
        } else if (config.updateType === 'digest') {
          content = `As this PR has been closed unmerged, ${appName} will ignore this upgrade updateType and you will not receive PRs for *any* future ${
            config.depName
          }:${
            config.currentValue
          } digest updates. Digest updates will resume if you update the specified tag at any time.`;
        } else {
          content = `As this PR has been closed unmerged, ${appName} will now ignore this update (${
            config.newValue
          }). You will still receive a PR once a newer version is released, so if you wish to permanently ignore this dependency, please add it to the \`ignoreDeps\` array of your renovate config.`;
        }
        content +=
          '\n\nIf this PR was closed by mistake or you changed your mind, you can simply rename this PR and you will soon get a fresh replacement PR opened.';
        if (!config.suppressNotifications.includes('prIgnoreNotification')) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would ensure closed PR comment in PR #' +
                existingPr.number
            );
          } else {
            await platform.ensureComment(existingPr.number, subject, content);
          }
        }
        if (branchExists) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info('DRY-RUN: Would delete branch ' + config.branchName);
          } else {
            await platform.deleteBranch(config.branchName);
          }
        }
      } else if (existingPr.state === 'merged') {
        logger.info(
          { pr: existingPr.number },
          'Merged PR is blocking this branch'
        );
      }
      return 'already-existed';
    }
    // istanbul ignore if
    if (!branchExists && config.masterIssueApproval) {
      if (masterIssueCheck) {
        logger.info(`Branch ${config.branchName} is approved for creation`);
      } else {
        logger.info(`Branch ${config.branchName} needs approval`);
        return 'needs-approval';
      }
    }
    if (!branchExists && prHourlyLimitReached && !masterIssueCheck) {
      logger.info('Reached PR creation limit - skipping branch creation');
      return 'pr-hourly-limit-reached';
    }
    if (branchExists) {
      logger.debug('Checking if PR has been edited');
      if (branchPr) {
        logger.debug('Found existing branch PR');
        if (branchPr.state !== 'open') {
          logger.info(
            'PR has been closed or merged since this run started - aborting'
          );
          throw new Error('repository-changed');
        }
        if (!branchPr.canRebase) {
          const subject = 'PR has been edited';
          const titleRebase =
            branchPr.title && branchPr.title.startsWith('rebase!');
          const labelRebase =
            branchPr.labels && branchPr.labels.includes(config.rebaseLabel);
          if (titleRebase || labelRebase) {
            // istanbul ignore if
            if (config.dryRun) {
              logger.info(
                'DRY-RUN: Would ensure PR edited comment removal in PR #' +
                  branchPr.number
              );
            } else {
              await platform.ensureCommentRemoval(branchPr.number, subject);
            }
          } else {
            let content = `:construction_worker: This PR has received other commits, so ${appName} will stop updating it to avoid conflicts or other problems.`;
            content += ` If you wish to abandon your changes and have ${appName} start over then you can add the label \`${
              config.rebaseLabel
            }\` to this PR and ${appName} will reset/recreate it.`;
            if (!config.suppressNotifications.includes('prEditNotification')) {
              // istanbul ignore if
              if (config.dryRun) {
                logger.info(
                  'DRY-RUN: ensure comment in PR #' + branchPr.number
                );
              } else {
                await platform.ensureComment(branchPr.number, subject, content);
              }
            }
            return 'pr-edited';
          }
        }
      }
    }

    // Check schedule
    config.isScheduledNow = isScheduledNow(config);
    if (!config.isScheduledNow && !masterIssueCheck) {
      if (!branchExists) {
        logger.info('Skipping branch creation as not within schedule');
        return 'not-scheduled';
      }
      if (config.updateNotScheduled === false) {
        logger.debug('Skipping branch update as not within schedule');
        return 'not-scheduled';
      }
      // istanbul ignore if
      if (!branchPr) {
        logger.debug('Skipping PR creation out of schedule');
        return 'not-scheduled';
      }
      logger.debug(
        'Branch + PR exists but is not scheduled -- will update if necessary'
      );
    }

    if (
      config.updateType !== 'lockFileMaintenance' &&
      config.unpublishSafe &&
      config.canBeUnpublished &&
      (config.prCreation === 'not-pending' ||
        config.prCreation === 'status-success')
    ) {
      logger.info(
        'Skipping branch creation due to unpublishSafe + status checks'
      );
      return 'pending';
    }
    // istanbul ignore if
    if (masterIssueCheck === 'rebase') {
      logger.info('Manual rebase requested via master issue');
      delete config.parentBranch;
    } else {
      Object.assign(config, await getParentBranch(config));
    }
    logger.debug(`Using parentBranch: ${config.parentBranch}`);
    const res = await getUpdatedPackageFiles(config);
    // istanbul ignore if
    if (res.artifactErrors && config.artifactErrors) {
      res.artifactErrors = config.artifactErrors.concat(res.artifactErrors);
    }
    Object.assign(config, res);
    if (config.updatedPackageFiles && config.updatedPackageFiles.length) {
      logger.debug(
        `Updated ${config.updatedPackageFiles.length} package files`
      );
    } else {
      logger.debug('No package files need updating');
    }
    const additionalFiles = await getAdditionalFiles(config, packageFiles);
    config.artifactErrors = (config.artifactErrors || []).concat(
      additionalFiles.artifactErrors
    );
    config.updatedArtifacts = (config.updatedArtifacts || []).concat(
      additionalFiles.updatedArtifacts
    );
    if (config.updatedArtifacts && config.updatedArtifacts.length) {
      logger.debug(
        { updatedArtifacts: config.updatedArtifacts.map(f => f.name) },
        `Updated ${config.updatedArtifacts.length} lock files`
      );
    } else {
      logger.debug('No updated lock files in branch');
    }
    if (config.artifactErrors && config.artifactErrors.length) {
      if (config.releaseTimestamp) {
        logger.debug(`Branch timestamp: ` + config.releaseTimestamp);
        const releaseTimestamp = DateTime.fromISO(config.releaseTimestamp);
        if (releaseTimestamp.plus({ days: 1 }) < DateTime.local()) {
          logger.info('PR is older than a day, raise PR with lock file errors');
        } else if (branchExists) {
          logger.info(
            'PR is less than a day old but branchExists so updating anyway'
          );
        } else {
          logger.info('PR is less than a day old - raise error instead of PR');
          throw new Error('lockfile-error');
        }
      } else {
        logger.debug('PR has no releaseTimestamp');
      }
    }

    config.committedFiles = await commitFilesToBranch(config);
    // istanbul ignore if
    if (
      config.updateType === 'lockFileMaintenance' &&
      !config.committedFiles &&
      !config.parentBranch &&
      branchExists
    ) {
      logger.info(
        'Deleting lock file maintenance branch as master lock file no longer needs updating'
      );
      // istanbul ignore if
      if (config.dryRun) {
        logger.info('DRY-RUN: Would delete lock file maintenance branch');
      } else {
        await platform.deleteBranch(config.branchName);
      }
      return 'done';
    }
    if (!(config.committedFiles || branchExists)) {
      return 'no-work';
    }

    // Set branch statuses
    await setUnpublishable(config);

    // Try to automerge branch and finish if successful, but only if branch already existed before this run
    if (branchExists || !config.requiresStatusChecks) {
      const mergeStatus = await tryBranchAutomerge(config);
      logger.debug(`mergeStatus=${mergeStatus}`);
      if (mergeStatus === 'automerged') {
        logger.debug('Branch is automerged - returning');
        return 'automerged';
      }
      if (
        mergeStatus === 'automerge aborted - PR exists' ||
        mergeStatus === 'branch status error' ||
        mergeStatus === 'failed'
      ) {
        logger.info({ mergeStatus }, 'Branch automerge not possible');
        config.forcePr = true;
        config.branchAutomergeFailureMessage = mergeStatus;
      }
    }
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'rate-limit-exceeded') {
      logger.debug('Passing rate-limit-exceeded error up');
      throw err;
    }
    if (err.message === 'repository-changed') {
      logger.debug('Passing repository-changed error up');
      throw err;
    }
    if (err.message === 'bad-credentials') {
      logger.debug('Passing bad-credentials error up');
      throw err;
    }
    if (err.message === 'integration-unauthorized') {
      logger.debug('Passing integration-unauthorized error up');
      throw err;
    }
    if (err.message === 'lockfile-error') {
      logger.debug('Passing lockfile-error up');
      throw err;
    }
    if (err.message.startsWith('disk-space')) {
      logger.debug('Passing disk-space error up');
      throw err;
    }
    if (err.message.startsWith('Resource not accessible by integration')) {
      logger.debug('Passing 403 error up');
      throw err;
    }
    if (err.message === 'update-failure') {
      logger.warn('Error updating branch: update failure');
    } else if (
      err.message === 'bundler-fs' ||
      err.message === 'bundler-credentials'
    ) {
      // we have already warned, so just return
      return 'error';
    } else if (err.message === 'bundler-unknown') {
      logger.warn('Unknown bundler error');
    } else if (
      err.messagee &&
      err.message.includes('fatal: Authentication failed')
    ) {
      throw new Error('authentication-failure');
    } else if (
      err.message !== 'registry-failure' &&
      err.message !== 'platform-failure'
    ) {
      logger.error({ err }, `Error updating branch: ${err.message}`);
    }
    // Don't throw here - we don't want to stop the other renovations
    return 'error';
  }
  try {
    logger.debug('Ensuring PR');
    logger.debug(
      `There are ${config.errors.length} errors and ${
        config.warnings.length
      } warnings`
    );
    const pr = await prWorker.ensurePr(config);
    // TODO: ensurePr should check for automerge itself
    if (pr) {
      const topic = ':warning: Artifact update problem';
      if (config.artifactErrors && config.artifactErrors.length) {
        logger.warn(
          { artifactErrors: config.artifactErrors },
          'artifactErrors'
        );
        let content = `${appName} failed to update `;
        content +=
          config.artifactErrors.length > 1 ? 'artifacts' : 'an artifact';
        content +=
          ' related to this branch. You probably do not want to merge this PR as-is.';
        content += `\n\n:recycle: ${appName} will retry this branch, including artifacts, only when one of the following happens:\n\n`;
        content +=
          ' - any of the package files in this branch needs updating, or \n';
        content += ' - the branch becomes conflicted, or\n';
        content +=
          ' - you check the rebase/retry checkbox if found above, or\n';
        content +=
          ' - you rename this PR\'s title to start with "rebase!" to trigger it manually';
        content += '\n\nThe artifact failure details are included below:\n\n';
        config.artifactErrors.forEach(error => {
          content += `##### File name: ${error.lockFile}\n\n`;
          content += `\`\`\`\n${error.stderr}\n\`\`\`\n\n`;
        });
        if (
          !(
            config.suppressNotifications.includes('artifactErrors') ||
            config.suppressNotifications.includes('lockFileErrors')
          )
        ) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would ensure lock file error comment in PR #' +
                pr.number
            );
          } else {
            await platform.ensureComment(pr.number, topic, content);
            // TODO: remoe this soon once they're all cleared out
            await platform.ensureCommentRemoval(
              pr.number,
              ':warning: Lock file problem'
            );
          }
        }
        const context = `${appSlug}/artifacts`;
        const description = 'Artifact file update failure';
        const state = 'failure';
        const existingState = await platform.getBranchStatusCheck(
          config.branchName,
          context
        );
        // Check if state needs setting
        if (existingState !== state) {
          logger.debug(`Updating status check state to failed`);
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would set branch status in ' + config.branchName
            );
          } else {
            await platform.setBranchStatus(
              config.branchName,
              context,
              description,
              state
            );
          }
        }
      } else {
        if (config.updatedArtifacts && config.updatedArtifacts.length) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would ensure comment removal in PR #' + pr.number
            );
          } else {
            await platform.ensureCommentRemoval(pr.number, topic);
          }
        }
        const prAutomerged = await prWorker.checkAutoMerge(pr, config);
        if (prAutomerged) {
          return 'automerged';
        }
      }
    }
  } catch (err) /* istanbul ignore next */ {
    if (
      [
        'rate-limit-exceeded',
        'platform-failure',
        'repository-changed',
      ].includes(err.message)
    ) {
      logger.debug('Passing PR error up');
      throw err;
    }
    // Otherwise don't throw here - we don't want to stop the other renovations
    logger.error({ err }, `Error ensuring PR: ${err.message}`);
  }
  if (!branchExists) {
    return 'pr-created';
  }
  return 'done';
}
<commit_msg>fix: correct phrasing for rebase notification (#3196)<commit_after>const { DateTime } = require('luxon');

const schedule = require('./schedule');
const { getUpdatedPackageFiles } = require('./get-updated');
const { getAdditionalFiles } = require('../../manager/npm/post-update');
const { commitFilesToBranch } = require('./commit');
const { getParentBranch } = require('./parent');
const { tryBranchAutomerge } = require('./automerge');
const { setUnpublishable } = require('./status-checks');
const { prAlreadyExisted } = require('./check-existing');
const prWorker = require('../pr');
const { appName, appSlug } = require('../../config/app-strings');

const { isScheduledNow } = schedule;

module.exports = {
  processBranch,
};

async function processBranch(branchConfig, prHourlyLimitReached, packageFiles) {
  const config = { ...branchConfig };
  const dependencies = config.upgrades
    .map(upgrade => upgrade.depName)
    .filter(v => v) // remove nulls (happens for lock file maintenance)
    .filter((value, i, list) => list.indexOf(value) === i); // remove duplicates
  logger.setMeta({
    repository: config.repository,
    branch: config.branchName,
    dependencies,
  });
  logger.debug(`processBranch with ${branchConfig.upgrades.length} upgrades`);
  logger.trace({ config });
  await platform.setBaseBranch(config.baseBranch);
  const branchExists = await platform.branchExists(config.branchName);
  const branchPr = await platform.getBranchPr(config.branchName);
  logger.debug(`branchExists=${branchExists}`);
  const masterIssueCheck = (config.masterIssueChecks || {})[config.branchName];
  // istanbul ignore if
  if (masterIssueCheck) {
    logger.info('Branch has been checked in master issue: ' + masterIssueCheck);
  }
  try {
    logger.debug(
      `Branch has ${dependencies ? dependencies.length : 0} upgrade(s)`
    );

    // Check if branch already existed
    const existingPr = branchPr ? undefined : await prAlreadyExisted(config);
    if (existingPr && !masterIssueCheck) {
      logger.debug(
        { prTitle: config.prTitle },
        'Closed PR already exists. Skipping branch.'
      );
      if (existingPr.state === 'closed') {
        const subject = `${appName} Ignore Notification`;
        let content;
        if (config.updateType === 'major') {
          content = `As this PR has been closed unmerged, ${appName} will ignore this upgrade and you will not receive PRs for *any* future ${
            config.newMajor
          }.x releases. However, if you upgrade to ${
            config.newMajor
          }.x manually then ${appName} will then reenable updates for minor and patch updates automatically.`;
        } else if (config.updateType === 'digest') {
          content = `As this PR has been closed unmerged, ${appName} will ignore this upgrade updateType and you will not receive PRs for *any* future ${
            config.depName
          }:${
            config.currentValue
          } digest updates. Digest updates will resume if you update the specified tag at any time.`;
        } else {
          content = `As this PR has been closed unmerged, ${appName} will now ignore this update (${
            config.newValue
          }). You will still receive a PR once a newer version is released, so if you wish to permanently ignore this dependency, please add it to the \`ignoreDeps\` array of your renovate config.`;
        }
        content +=
          '\n\nIf this PR was closed by mistake or you changed your mind, you can simply rename this PR and you will soon get a fresh replacement PR opened.';
        if (!config.suppressNotifications.includes('prIgnoreNotification')) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would ensure closed PR comment in PR #' +
                existingPr.number
            );
          } else {
            await platform.ensureComment(existingPr.number, subject, content);
          }
        }
        if (branchExists) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info('DRY-RUN: Would delete branch ' + config.branchName);
          } else {
            await platform.deleteBranch(config.branchName);
          }
        }
      } else if (existingPr.state === 'merged') {
        logger.info(
          { pr: existingPr.number },
          'Merged PR is blocking this branch'
        );
      }
      return 'already-existed';
    }
    // istanbul ignore if
    if (!branchExists && config.masterIssueApproval) {
      if (masterIssueCheck) {
        logger.info(`Branch ${config.branchName} is approved for creation`);
      } else {
        logger.info(`Branch ${config.branchName} needs approval`);
        return 'needs-approval';
      }
    }
    if (!branchExists && prHourlyLimitReached && !masterIssueCheck) {
      logger.info('Reached PR creation limit - skipping branch creation');
      return 'pr-hourly-limit-reached';
    }
    if (branchExists) {
      logger.debug('Checking if PR has been edited');
      if (branchPr) {
        logger.debug('Found existing branch PR');
        if (branchPr.state !== 'open') {
          logger.info(
            'PR has been closed or merged since this run started - aborting'
          );
          throw new Error('repository-changed');
        }
        if (!branchPr.canRebase) {
          const subject = 'PR has been edited';
          const titleRebase =
            branchPr.title && branchPr.title.startsWith('rebase!');
          const labelRebase =
            branchPr.labels && branchPr.labels.includes(config.rebaseLabel);
          if (titleRebase || labelRebase) {
            // istanbul ignore if
            if (config.dryRun) {
              logger.info(
                'DRY-RUN: Would ensure PR edited comment removal in PR #' +
                  branchPr.number
              );
            } else {
              await platform.ensureCommentRemoval(branchPr.number, subject);
            }
          } else {
            let content = `:construction_worker: This PR has received other commits, so ${appName} will stop updating it to avoid conflicts or other problems.`;
            content += ` If you wish to abandon your changes and have ${appName} start over you may click the "rebase" checkbox in the PR body/description.`;
            if (!config.suppressNotifications.includes('prEditNotification')) {
              // istanbul ignore if
              if (config.dryRun) {
                logger.info(
                  'DRY-RUN: ensure comment in PR #' + branchPr.number
                );
              } else {
                await platform.ensureComment(branchPr.number, subject, content);
              }
            }
            return 'pr-edited';
          }
        }
      }
    }

    // Check schedule
    config.isScheduledNow = isScheduledNow(config);
    if (!config.isScheduledNow && !masterIssueCheck) {
      if (!branchExists) {
        logger.info('Skipping branch creation as not within schedule');
        return 'not-scheduled';
      }
      if (config.updateNotScheduled === false) {
        logger.debug('Skipping branch update as not within schedule');
        return 'not-scheduled';
      }
      // istanbul ignore if
      if (!branchPr) {
        logger.debug('Skipping PR creation out of schedule');
        return 'not-scheduled';
      }
      logger.debug(
        'Branch + PR exists but is not scheduled -- will update if necessary'
      );
    }

    if (
      config.updateType !== 'lockFileMaintenance' &&
      config.unpublishSafe &&
      config.canBeUnpublished &&
      (config.prCreation === 'not-pending' ||
        config.prCreation === 'status-success')
    ) {
      logger.info(
        'Skipping branch creation due to unpublishSafe + status checks'
      );
      return 'pending';
    }
    // istanbul ignore if
    if (masterIssueCheck === 'rebase') {
      logger.info('Manual rebase requested via master issue');
      delete config.parentBranch;
    } else {
      Object.assign(config, await getParentBranch(config));
    }
    logger.debug(`Using parentBranch: ${config.parentBranch}`);
    const res = await getUpdatedPackageFiles(config);
    // istanbul ignore if
    if (res.artifactErrors && config.artifactErrors) {
      res.artifactErrors = config.artifactErrors.concat(res.artifactErrors);
    }
    Object.assign(config, res);
    if (config.updatedPackageFiles && config.updatedPackageFiles.length) {
      logger.debug(
        `Updated ${config.updatedPackageFiles.length} package files`
      );
    } else {
      logger.debug('No package files need updating');
    }
    const additionalFiles = await getAdditionalFiles(config, packageFiles);
    config.artifactErrors = (config.artifactErrors || []).concat(
      additionalFiles.artifactErrors
    );
    config.updatedArtifacts = (config.updatedArtifacts || []).concat(
      additionalFiles.updatedArtifacts
    );
    if (config.updatedArtifacts && config.updatedArtifacts.length) {
      logger.debug(
        { updatedArtifacts: config.updatedArtifacts.map(f => f.name) },
        `Updated ${config.updatedArtifacts.length} lock files`
      );
    } else {
      logger.debug('No updated lock files in branch');
    }
    if (config.artifactErrors && config.artifactErrors.length) {
      if (config.releaseTimestamp) {
        logger.debug(`Branch timestamp: ` + config.releaseTimestamp);
        const releaseTimestamp = DateTime.fromISO(config.releaseTimestamp);
        if (releaseTimestamp.plus({ days: 1 }) < DateTime.local()) {
          logger.info('PR is older than a day, raise PR with lock file errors');
        } else if (branchExists) {
          logger.info(
            'PR is less than a day old but branchExists so updating anyway'
          );
        } else {
          logger.info('PR is less than a day old - raise error instead of PR');
          throw new Error('lockfile-error');
        }
      } else {
        logger.debug('PR has no releaseTimestamp');
      }
    }

    config.committedFiles = await commitFilesToBranch(config);
    // istanbul ignore if
    if (
      config.updateType === 'lockFileMaintenance' &&
      !config.committedFiles &&
      !config.parentBranch &&
      branchExists
    ) {
      logger.info(
        'Deleting lock file maintenance branch as master lock file no longer needs updating'
      );
      // istanbul ignore if
      if (config.dryRun) {
        logger.info('DRY-RUN: Would delete lock file maintenance branch');
      } else {
        await platform.deleteBranch(config.branchName);
      }
      return 'done';
    }
    if (!(config.committedFiles || branchExists)) {
      return 'no-work';
    }

    // Set branch statuses
    await setUnpublishable(config);

    // Try to automerge branch and finish if successful, but only if branch already existed before this run
    if (branchExists || !config.requiresStatusChecks) {
      const mergeStatus = await tryBranchAutomerge(config);
      logger.debug(`mergeStatus=${mergeStatus}`);
      if (mergeStatus === 'automerged') {
        logger.debug('Branch is automerged - returning');
        return 'automerged';
      }
      if (
        mergeStatus === 'automerge aborted - PR exists' ||
        mergeStatus === 'branch status error' ||
        mergeStatus === 'failed'
      ) {
        logger.info({ mergeStatus }, 'Branch automerge not possible');
        config.forcePr = true;
        config.branchAutomergeFailureMessage = mergeStatus;
      }
    }
  } catch (err) /* istanbul ignore next */ {
    if (err.message === 'rate-limit-exceeded') {
      logger.debug('Passing rate-limit-exceeded error up');
      throw err;
    }
    if (err.message === 'repository-changed') {
      logger.debug('Passing repository-changed error up');
      throw err;
    }
    if (err.message === 'bad-credentials') {
      logger.debug('Passing bad-credentials error up');
      throw err;
    }
    if (err.message === 'integration-unauthorized') {
      logger.debug('Passing integration-unauthorized error up');
      throw err;
    }
    if (err.message === 'lockfile-error') {
      logger.debug('Passing lockfile-error up');
      throw err;
    }
    if (err.message.startsWith('disk-space')) {
      logger.debug('Passing disk-space error up');
      throw err;
    }
    if (err.message.startsWith('Resource not accessible by integration')) {
      logger.debug('Passing 403 error up');
      throw err;
    }
    if (err.message === 'update-failure') {
      logger.warn('Error updating branch: update failure');
    } else if (
      err.message === 'bundler-fs' ||
      err.message === 'bundler-credentials'
    ) {
      // we have already warned, so just return
      return 'error';
    } else if (err.message === 'bundler-unknown') {
      logger.warn('Unknown bundler error');
    } else if (
      err.messagee &&
      err.message.includes('fatal: Authentication failed')
    ) {
      throw new Error('authentication-failure');
    } else if (
      err.message !== 'registry-failure' &&
      err.message !== 'platform-failure'
    ) {
      logger.error({ err }, `Error updating branch: ${err.message}`);
    }
    // Don't throw here - we don't want to stop the other renovations
    return 'error';
  }
  try {
    logger.debug('Ensuring PR');
    logger.debug(
      `There are ${config.errors.length} errors and ${
        config.warnings.length
      } warnings`
    );
    const pr = await prWorker.ensurePr(config);
    // TODO: ensurePr should check for automerge itself
    if (pr) {
      const topic = ':warning: Artifact update problem';
      if (config.artifactErrors && config.artifactErrors.length) {
        logger.warn(
          { artifactErrors: config.artifactErrors },
          'artifactErrors'
        );
        let content = `${appName} failed to update `;
        content +=
          config.artifactErrors.length > 1 ? 'artifacts' : 'an artifact';
        content +=
          ' related to this branch. You probably do not want to merge this PR as-is.';
        content += `\n\n:recycle: ${appName} will retry this branch, including artifacts, only when one of the following happens:\n\n`;
        content +=
          ' - any of the package files in this branch needs updating, or \n';
        content += ' - the branch becomes conflicted, or\n';
        content +=
          ' - you check the rebase/retry checkbox if found above, or\n';
        content +=
          ' - you rename this PR\'s title to start with "rebase!" to trigger it manually';
        content += '\n\nThe artifact failure details are included below:\n\n';
        config.artifactErrors.forEach(error => {
          content += `##### File name: ${error.lockFile}\n\n`;
          content += `\`\`\`\n${error.stderr}\n\`\`\`\n\n`;
        });
        if (
          !(
            config.suppressNotifications.includes('artifactErrors') ||
            config.suppressNotifications.includes('lockFileErrors')
          )
        ) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would ensure lock file error comment in PR #' +
                pr.number
            );
          } else {
            await platform.ensureComment(pr.number, topic, content);
            // TODO: remoe this soon once they're all cleared out
            await platform.ensureCommentRemoval(
              pr.number,
              ':warning: Lock file problem'
            );
          }
        }
        const context = `${appSlug}/artifacts`;
        const description = 'Artifact file update failure';
        const state = 'failure';
        const existingState = await platform.getBranchStatusCheck(
          config.branchName,
          context
        );
        // Check if state needs setting
        if (existingState !== state) {
          logger.debug(`Updating status check state to failed`);
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would set branch status in ' + config.branchName
            );
          } else {
            await platform.setBranchStatus(
              config.branchName,
              context,
              description,
              state
            );
          }
        }
      } else {
        if (config.updatedArtifacts && config.updatedArtifacts.length) {
          // istanbul ignore if
          if (config.dryRun) {
            logger.info(
              'DRY-RUN: Would ensure comment removal in PR #' + pr.number
            );
          } else {
            await platform.ensureCommentRemoval(pr.number, topic);
          }
        }
        const prAutomerged = await prWorker.checkAutoMerge(pr, config);
        if (prAutomerged) {
          return 'automerged';
        }
      }
    }
  } catch (err) /* istanbul ignore next */ {
    if (
      [
        'rate-limit-exceeded',
        'platform-failure',
        'repository-changed',
      ].includes(err.message)
    ) {
      logger.debug('Passing PR error up');
      throw err;
    }
    // Otherwise don't throw here - we don't want to stop the other renovations
    logger.error({ err }, `Error ensuring PR: ${err.message}`);
  }
  if (!branchExists) {
    return 'pr-created';
  }
  return 'done';
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
 *
 * A brief overview of this source file: what is its purpose.
 */

// This is not really needed, but javascriptlint will complain otherwise:
var sdcClients = require('sdc-clients');
var restify = require('restify');

function validateForZoneAction(job, cb) {
    if (!cnapiUrl)
        return cb('No CNAPI URL provided');

    if (!job.params['vm_uuid'])
        return cb('VM UUID is required');

    return cb(null, 'All parameters OK!');
}

function zoneAction(job, cb) {
    if (!job.endpoint)
        return cb('No CNAPI endpoint provided');

    if (!job.requestMethod)
        return cb('No HTTP request method provided');

    var cnapi = restify.createJsonClient({ url: cnapiUrl, log: job.log });

    function callback(err, req, res, task) {
        if (err) {
            return cb(err);
        } else {
            job.taskId = task.id;
            return cb(null, 'Task queued to CNAPI!');
        }
    }

    if (job.requestMethod == 'post')
        return cnapi.post(job.endpoint, job.params, callback);
    else if (job.requestMethod == 'del')
        return cnapi.del(job.endpoint, callback);
    else
        return cb('Unsupported requestMethod: "' + job.requestMethod + '"');
}

function pollTask(job, cb) {
    if (!job.taskId)
        return cb('No taskId provided');

    if (!cnapiUrl)
        return cb('No CNAPI URL provided');

    var cnapi = restify.createJsonClient({ url: cnapiUrl, log: job.log });

    // We have to poll the task until it completes. Ensure the timeout is
    // big enough so tasks end on time
    var intervalId = setInterval(function () {
        cnapi.get('/tasks/' + job.taskId, function (err, req, res, task) {
            if (err) {
                return cb(err);
            } else {
                if (task.status == 'failure') {
                    clearInterval(intervalId);
                    cb('Job failed');
                    return;

                } else if (task.status == 'complete') {
                    clearInterval(intervalId);
                    cb(null, 'Job succeeded!');
                    return;
                }
            }
        });
    }, 1000);
}

function checkState(job, cb) {
    // For now don't fail the job if this parameter is not present
    if (!job.expects)
        return cb(null, 'No \'expects\' state parameter provided');

    if (!job.params['vm_uuid'])
        return cb('No VM UUID provided');

    if (!vmapiUrl)
        return cb('No VMAPI URL provided');

    var vmapi = restify.createJsonClient({ url: vmapiUrl, log: job.log });

    // Poll the VM until we reach to the desired state, otherwise the task
    // timeout will fail the job, which is what we want
    var path = '/vms/' + job.params['vm_uuid'];
    var intervalId = setInterval(function () {
        vmapi.get(path, function (err, req, res, vm) {
            // Provision tasks can return 404 when machine has not showed up
            if (res && res.statusCode == 404 && job.params.task == 'provision') {
                return;
            } else if (err) {
                return cb(err);
            } else {
                if (vm.state == job.expects) {
                    clearInterval(intervalId);
                    cb(null, 'VM is now ' + job.expects);
                    return;
                }
            }
        });
    }, 1000);
}

module.exports = {
    validateForZoneAction: validateForZoneAction,
    zoneAction: zoneAction,
    pollTask: pollTask,
    checkState: checkState
};
<commit_msg>ZAPI-142: Clear interval when there is an error polling vmapi<commit_after>/*
 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
 *
 * A brief overview of this source file: what is its purpose.
 */

// This is not really needed, but javascriptlint will complain otherwise:
var sdcClients = require('sdc-clients');
var restify = require('restify');

function validateForZoneAction(job, cb) {
    if (!cnapiUrl)
        return cb('No CNAPI URL provided');

    if (!job.params['vm_uuid'])
        return cb('VM UUID is required');

    return cb(null, 'All parameters OK!');
}

function zoneAction(job, cb) {
    if (!job.endpoint)
        return cb('No CNAPI endpoint provided');

    if (!job.requestMethod)
        return cb('No HTTP request method provided');

    var cnapi = restify.createJsonClient({ url: cnapiUrl, log: job.log });

    function callback(err, req, res, task) {
        if (err) {
            return cb(err);
        } else {
            job.taskId = task.id;
            return cb(null, 'Task queued to CNAPI!');
        }
    }

    if (job.requestMethod == 'post')
        return cnapi.post(job.endpoint, job.params, callback);
    else if (job.requestMethod == 'del')
        return cnapi.del(job.endpoint, callback);
    else
        return cb('Unsupported requestMethod: "' + job.requestMethod + '"');
}

function pollTask(job, cb) {
    if (!job.taskId)
        return cb('No taskId provided');

    if (!cnapiUrl)
        return cb('No CNAPI URL provided');

    var cnapi = restify.createJsonClient({ url: cnapiUrl, log: job.log });

    // We have to poll the task until it completes. Ensure the timeout is
    // big enough so tasks end on time
    var intervalId = setInterval(function () {
        cnapi.get('/tasks/' + job.taskId, function (err, req, res, task) {
            if (err) {
                return cb(err);
            } else {
                if (task.status == 'failure') {
                    clearInterval(intervalId);
                    return cb('Job failed');

                } else if (task.status == 'complete') {
                    clearInterval(intervalId);
                    return cb(null, 'Job succeeded!');
                }
            }
        });
    }, 1000);
}

function checkState(job, cb) {
    // For now don't fail the job if this parameter is not present
    if (!job.expects)
        return cb(null, 'No \'expects\' state parameter provided');

    if (!job.params['vm_uuid'])
        return cb('No VM UUID provided');

    if (!vmapiUrl)
        return cb('No VMAPI URL provided');

    var vmapi = restify.createJsonClient({ url: vmapiUrl, log: job.log });

    // Poll the VM until we reach to the desired state, otherwise the task
    // timeout will fail the job, which is what we want
    var path = '/vms/' + job.params['vm_uuid'];
    var intervalId = setInterval(function () {
        vmapi.get(path, function (err, req, res, vm) {
            // Provision tasks can return 404 when machine has not showed up
            if (res && res.statusCode == 404 && job.params.task == 'provision') {
                return;
            } else if (err) {
                clearInterval(intervalId);
                return cb(err);
            } else {
                if (vm.state == job.expects) {
                    clearInterval(intervalId);
                    return cb(null, 'VM is now ' + job.expects);
                }
            }
        });
    }, 1000);
}

module.exports = {
    validateForZoneAction: validateForZoneAction,
    zoneAction: zoneAction,
    pollTask: pollTask,
    checkState: checkState
};
<|endoftext|>


<commit_before>define([
	"./core",
	"./var/strundefined",
	"./core/access",
	"./css/var/rnumnonpx",
	"./css/curCSS",
	"./css/addGetHookIf",
	"./css/support",

	"./core/init",
	"./css",
	"./selector" // contains
], function( jQuery, strundefined, access, rnumnonpx, curCSS, addGetHookIf, support ) {

// BuildExclude
curCSS = curCSS.curCSS;

var docElem = window.document.documentElement;

/**
 * Gets a window from an element
 */
function getWindow( elem ) {
	return jQuery.isWindow( elem ) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}

jQuery.offset = {
	setOffset: function( elem, options, i ) {
		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
			position = jQuery.css( elem, "position" ),
			curElem = jQuery( elem ),
			props = {};

		// set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		curOffset = curElem.offset();
		curCSSTop = jQuery.css( elem, "top" );
		curCSSLeft = jQuery.css( elem, "left" );
		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
			jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;

		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;
		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );
		} else {
			curElem.css( props );
		}
	}
};

jQuery.fn.extend({
	offset: function( options ) {
		if ( arguments.length ) {
			return options === undefined ?
				this :
				this.each(function( i ) {
					jQuery.offset.setOffset( this, options, i );
				});
		}

		var docElem, win,
			box = { top: 0, left: 0 },
			elem = this[ 0 ],
			doc = elem && elem.ownerDocument;

		if ( !doc ) {
			return;
		}

		docElem = doc.documentElement;

		// Make sure it's not a disconnected DOM node
		if ( !jQuery.contains( docElem, elem ) ) {
			return box;
		}

		// If we don't have gBCR, just use 0,0 rather than error
		// BlackBerry 5, iOS 3 (original iPhone)
		if ( typeof elem.getBoundingClientRect !== strundefined ) {
			box = elem.getBoundingClientRect();
		}
		win = getWindow( doc );
		return {
			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
		};
	},

	position: function() {
		if ( !this[ 0 ] ) {
			return;
		}

		var offsetParent, offset,
			parentOffset = { top: 0, left: 0 },
			elem = this[ 0 ];

		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
		if ( jQuery.css( elem, "position" ) === "fixed" ) {
			// we assume that getBoundingClientRect is available when computed position is fixed
			offset = elem.getBoundingClientRect();
		} else {
			// Get *real* offsetParent
			offsetParent = this.offsetParent();

			// Get correct offsets
			offset = this.offset();
			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
				parentOffset = offsetParent.offset();
			}

			// Add offsetParent borders
			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
		}

		// Subtract parent offsets and element margins
		// note: when an element has margin: auto the offsetLeft and marginLeft
		// are the same in Safari causing offset.left to incorrectly be 0
		return {
			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
		};
	},

	offsetParent: function() {
		return this.map(function() {
			var offsetParent = this.offsetParent || docElem;

			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
				offsetParent = offsetParent.offsetParent;
			}
			return offsetParent || docElem;
		});
	}
});

// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
	var top = /Y/.test( prop );

	jQuery.fn[ method ] = function( val ) {
		return access( this, function( elem, method, val ) {
			var win = getWindow( elem );

			if ( val === undefined ) {
				return win ? (prop in win) ? win[ prop ] :
					win.document.documentElement[ method ] :
					elem[ method ];
			}

			if ( win ) {
				win.scrollTo(
					!top ? val : jQuery( win ).scrollLeft(),
					top ? val : jQuery( win ).scrollTop()
				);

			} else {
				elem[ method ] = val;
			}
		}, method, val, arguments.length, null );
	};
});

// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// getComputedStyle returns percent when specified for top/left/bottom/right
// rather than make the css module depend on the offset module, we just check for it here
jQuery.each( [ "top", "left" ], function( i, prop ) {
	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
		function( elem, computed ) {
			if ( computed ) {
				computed = curCSS( elem, prop );
				// if curCSS returns percentage, fallback to offset
				return rnumnonpx.test( computed ) ?
					jQuery( elem ).position()[ prop ] + "px" :
					computed;
			}
		}
	);
});

return jQuery;
});
<commit_msg>Offset: Fix comment typo, thanks @AurelioDeRosa<commit_after>define([
	"./core",
	"./var/strundefined",
	"./core/access",
	"./css/var/rnumnonpx",
	"./css/curCSS",
	"./css/addGetHookIf",
	"./css/support",

	"./core/init",
	"./css",
	"./selector" // contains
], function( jQuery, strundefined, access, rnumnonpx, curCSS, addGetHookIf, support ) {

// BuildExclude
curCSS = curCSS.curCSS;

var docElem = window.document.documentElement;

/**
 * Gets a window from an element
 */
function getWindow( elem ) {
	return jQuery.isWindow( elem ) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}

jQuery.offset = {
	setOffset: function( elem, options, i ) {
		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
			position = jQuery.css( elem, "position" ),
			curElem = jQuery( elem ),
			props = {};

		// set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		curOffset = curElem.offset();
		curCSSTop = jQuery.css( elem, "top" );
		curCSSLeft = jQuery.css( elem, "left" );
		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
			jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;

		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;
		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );
		} else {
			curElem.css( props );
		}
	}
};

jQuery.fn.extend({
	offset: function( options ) {
		if ( arguments.length ) {
			return options === undefined ?
				this :
				this.each(function( i ) {
					jQuery.offset.setOffset( this, options, i );
				});
		}

		var docElem, win,
			box = { top: 0, left: 0 },
			elem = this[ 0 ],
			doc = elem && elem.ownerDocument;

		if ( !doc ) {
			return;
		}

		docElem = doc.documentElement;

		// Make sure it's not a disconnected DOM node
		if ( !jQuery.contains( docElem, elem ) ) {
			return box;
		}

		// If we don't have gBCR, just use 0,0 rather than error
		// BlackBerry 5, iOS 3 (original iPhone)
		if ( typeof elem.getBoundingClientRect !== strundefined ) {
			box = elem.getBoundingClientRect();
		}
		win = getWindow( doc );
		return {
			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
		};
	},

	position: function() {
		if ( !this[ 0 ] ) {
			return;
		}

		var offsetParent, offset,
			parentOffset = { top: 0, left: 0 },
			elem = this[ 0 ];

		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
		if ( jQuery.css( elem, "position" ) === "fixed" ) {
			// we assume that getBoundingClientRect is available when computed position is fixed
			offset = elem.getBoundingClientRect();
		} else {
			// Get *real* offsetParent
			offsetParent = this.offsetParent();

			// Get correct offsets
			offset = this.offset();
			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
				parentOffset = offsetParent.offset();
			}

			// Add offsetParent borders
			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
		}

		// Subtract parent offsets and element margins
		// note: when an element has margin: auto the offsetLeft and marginLeft
		// are the same in Safari causing offset.left to incorrectly be 0
		return {
			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
		};
	},

	offsetParent: function() {
		return this.map(function() {
			var offsetParent = this.offsetParent || docElem;

			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
				offsetParent = offsetParent.offsetParent;
			}
			return offsetParent || docElem;
		});
	}
});

// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
	var top = /Y/.test( prop );

	jQuery.fn[ method ] = function( val ) {
		return access( this, function( elem, method, val ) {
			var win = getWindow( elem );

			if ( val === undefined ) {
				return win ? (prop in win) ? win[ prop ] :
					win.document.documentElement[ method ] :
					elem[ method ];
			}

			if ( win ) {
				win.scrollTo(
					!top ? val : jQuery( win ).scrollLeft(),
					top ? val : jQuery( win ).scrollTop()
				);

			} else {
				elem[ method ] = val;
			}
		}, method, val, arguments.length, null );
	};
});

// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// getComputedStyle returns percent when specified for top/left/bottom/right
// rather than make the css module depend on the offset module, we just check for it here
jQuery.each( [ "top", "left" ], function( i, prop ) {
	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
		function( elem, computed ) {
			if ( computed ) {
				computed = curCSS( elem, prop );
				// if curCSS returns percentage, fallback to offset
				return rnumnonpx.test( computed ) ?
					jQuery( elem ).position()[ prop ] + "px" :
					computed;
			}
		}
	);
});

return jQuery;
});
<|endoftext|>


<commit_before>'use strict'

const Path = require('path')

const JiraClient = require('../common/jiraClient')
const FileStore = require('../common/fileStore')

function mapIssue (issue) {
  return {
    key: issue.key,
    summary: issue.fields.summary,
    issueType: issue.fields.issuetype.name,
    project: issue.fields.project.name,
    projectKey: issue.fields.project.key,
    priority: issue.fields.priority.name,
    labels: issue.fields.labels,
    status: issue.fields.status.name,
    statusCategory: issue.fields.status.statusCategory.name,
    issueLinks: issue.fields.issuelinks.map(mapIssueLink),
    updated: issue.fields.updated
  }
}

function mapIssueLink (link) {
  let ret = {}
  if (link.inwardIssue) {
    ret.direction = 'inward'
    ret.type = link.type.inward
    ret.key = link.inwardIssue.key
  }
  if (link.outwardIssue) {
    ret.direction = 'outward'
    ret.type = link.type.outward
    ret.key = link.outwardIssue.key
  }
  return ret
}

async function fetchIssues (jiraClient, jql) {
  const list = await jiraClient.search(jql)
  let issues = list.issues.reduce((acc, cur) => {
    acc[cur.key] = mapIssue(cur)
    return acc
  }, {})
  return issues
}

class Repository {
  constructor (config) {
    this.config = config
    this.jiraClient = new JiraClient(config.server, config.username, config.password)
    if (this.config.path) {
      this.dataStore = new FileStore(Path.join(Path.dirname(this.config.config), this.config.path))
    }
    this.issues = {}
  }

  async populate () {
    let issues
    if (this.dataStore) {
      issues = await this.dataStore.readData('issues')
    }
    if (!issues) {
      issues = await fetchIssues(this.jiraClient, this.config.query)
    }
    this.issues = issues
  }

  async store () {
    if (this.dataStore) {
      await this.dataStore.writeData('issues', this.issues)
    }
  }

  async cleanup () {
    this.issues = {}
    if (this.dataStore) {
      await this.dataStore.deleteData('issues')
    }
  }
}

exports = module.exports = Repository
<commit_msg>separate out a fetch function from populate<commit_after>'use strict'

const Path = require('path')

const JiraClient = require('../common/jiraClient')
const FileStore = require('../common/fileStore')

function mapIssue (issue) {
  return {
    key: issue.key,
    summary: issue.fields.summary,
    issueType: issue.fields.issuetype.name,
    project: issue.fields.project.name,
    projectKey: issue.fields.project.key,
    priority: issue.fields.priority.name,
    labels: issue.fields.labels,
    status: issue.fields.status.name,
    statusCategory: issue.fields.status.statusCategory.name,
    issueLinks: issue.fields.issuelinks.map(mapIssueLink),
    updated: issue.fields.updated
  }
}

function mapIssueLink (link) {
  let ret = {}
  if (link.inwardIssue) {
    ret.direction = 'inward'
    ret.type = link.type.inward
    ret.key = link.inwardIssue.key
  }
  if (link.outwardIssue) {
    ret.direction = 'outward'
    ret.type = link.type.outward
    ret.key = link.outwardIssue.key
  }
  return ret
}

async function fetchIssues (jiraClient, jql) {
  const list = await jiraClient.search(jql)
  let issues = list.issues.reduce((acc, cur) => {
    acc[cur.key] = mapIssue(cur)
    return acc
  }, {})
  return issues
}

class Repository {
  constructor (config) {
    this.config = config
    this.jiraClient = new JiraClient(config.server, config.username, config.password)
    if (this.config.path) {
      this.dataStore = new FileStore(Path.join(Path.dirname(this.config.config), this.config.path))
    }
    this.issues = {}
  }

  async populate () {
    if (this.dataStore) {
      this.issues = await this.dataStore.readData('issues')
    }
    if (!this.issues) {
      await this.fetch()
    }
  }

  async fetch () {
    this.issues = await fetchIssues(this.jiraClient, this.config.query)
  }

  async store () {
    if (this.dataStore) {
      await this.dataStore.writeData('issues', this.issues)
    }
  }

  async cleanup () {
    this.issues = {}
    if (this.dataStore) {
      await this.dataStore.deleteData('issues')
    }
  }
}

exports = module.exports = Repository
<|endoftext|>


<commit_before>var Promise = require('bluebird');

module.exports = {

  changedCommunities: function(startTime, endTime) {

    return Promise.join(
      // new members
      User.createdInTimeRange(startTime, endTime).fetchAll({withRelated: ['memberships']}),

      // new posts
      Post.createdInTimeRange(startTime, endTime)
      .query(qb => qb.where('post.type', '!=', 'welcome'))
      .fetchAll({withRelated: [
        {communities: qb => qb.column('community_id')}
      ]}),

      // new comments
      Comment.createdInTimeRange(startTime, endTime)
      .query(qb => {
        qb.join('post', () => this.on('post.id', 'comment.post_id'));
        qb.where('post.type', '!=', 'welcome');
      })
      .fetchAll({withRelated: [
        {post: qb => qb.column('id')},
        {'post.communities': qb => qb.column('community_id')}
      ]})
    ).spread(function(users, posts, comments) {

      var communityIds = [];

      users.each(function(u) {
        var ids = u.relations.memberships.map(m => m.get('community_id'));
        communityIds.push(ids);
      });

      posts.each(function(s) {
        var ids = s.relations.communities.map('id');
        communityIds.push(ids);
      });

      comments.each(function(c) {
        var ids = c.relations.post.relations.communities.map('community_id');
        communityIds.push(ids);
      });

      return _.union.apply(_, communityIds).sort((a, b) => a > b);
    });

  }

};
<commit_msg>fix the use of community id in changes.js<commit_after>var Promise = require('bluebird');

module.exports = {

  changedCommunities: function(startTime, endTime) {

    return Promise.join(
      // new members
      User.createdInTimeRange(startTime, endTime).fetchAll({withRelated: ['memberships']}),

      // new posts
      Post.createdInTimeRange(startTime, endTime)
      .query(qb => qb.where('post.type', '!=', 'welcome'))
      .fetchAll({withRelated: [
        {communities: qb => qb.column('community.id')}
      ]}),

      // new comments
      Comment.createdInTimeRange(startTime, endTime)
      .query(qb => {
        qb.join('post', () => this.on('post.id', 'comment.post_id'));
        qb.where('post.type', '!=', 'welcome');
      })
      .fetchAll({withRelated: [
        {post: qb => qb.column('id')},
        {'post.communities': qb => qb.column('community.id')}
      ]})
    ).spread(function(users, posts, comments) {

      var communityIds = [];

      users.each(function(u) {
        var ids = u.relations.memberships.map(m => m.get('community_id'));
        communityIds.push(ids);
      });

      posts.each(function(s) {
        var ids = s.relations.communities.map('id');
        communityIds.push(ids);
      });

      comments.each(function(c) {
        var ids = c.relations.post.relations.communities.map('id');
        communityIds.push(ids);
      });

      return _.union.apply(_, communityIds).sort((a, b) => a > b);
    });

  }

};
<|endoftext|>