<commit_before>'use strict';

var _ = require('lodash');
var moment = require('moment');
var levels = require('../levels');
var times = require('../times');

var ALL_STATUS_FIELDS = ['reservoir', 'battery', 'clock', 'status', 'device'];

function init (ctx) {
  var translate = ctx.language.translate;
  var timeago = require('./timeago')(ctx);
  var openaps = require('./openaps')(ctx);

  var pump = {
    name: 'pump'
    , label: 'Pump'
    , pluginType: 'pill-status'
  };

  pump.getPrefs = function getPrefs (sbx) {

    function cleanList (value) {
      return decodeURIComponent(value || '').toLowerCase().split(' ');
    }

    function isEmpty (list) {
      return _.isEmpty(list) || _.isEmpty(list[0]);
    }

    var fields = cleanList(sbx.extendedSettings.fields);
    fields = isEmpty(fields) ? ['reservoir'] : fields;

    var retroFields = cleanList(sbx.extendedSettings.retroFields);
    retroFields = isEmpty(retroFields) ? ['reservoir', 'battery'] : retroFields;

    return {
      fields: fields
      , retroFields: retroFields
      , warnClock: sbx.extendedSettings.warnClock || 30
      , urgentClock: sbx.extendedSettings.urgentClock || 60
      , warnRes: sbx.extendedSettings.warnRes || 10
      , urgentRes: sbx.extendedSettings.urgentRes || 5
      , warnBattV: sbx.extendedSettings.warnBattV || 1.35
      , urgentBattV: sbx.extendedSettings.urgentBattV || 1.3
      , warnBattP: sbx.extendedSettings.warnBattP || 30
      , urgentBattP: sbx.extendedSettings.urgentBattP || 20
      , warnOnSuspend: sbx.extendedSettings.warnOnSuspend || false
      , enableAlerts: sbx.extendedSettings.enableAlerts || false
    };
  };

  pump.setProperties = function setProperties (sbx) {
    sbx.offerProperty('pump', function setPump ( ) {

      var prefs = pump.getPrefs(sbx);
      var recentMills = sbx.time - times.mins(prefs.urgentClock * 2).msecs;

      var filtered = _.filter(sbx.data.devicestatus, function (status) {
        return ('pump' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills;
      });

      var pumpStatus = null;

      _.forEach(filtered, function each (status) {
        status.clockMills = status.pump && status.pump.clock ? moment(status.pump.clock).valueOf() : status.mills;
        if (!pumpStatus || status.clockMills > pumpStatus.clockMills) {
          pumpStatus = status;
        }
      });

      pumpStatus = pumpStatus || { };
      pumpStatus.data = prepareData(pumpStatus, prefs, sbx);

      return pumpStatus;
    });
  };

  pump.checkNotifications = function checkNotifications (sbx) {
    var prefs = pump.getPrefs(sbx);

    if (!prefs.enableAlerts) { return; }

    pump.warnOnSuspend = prefs.warnOnSuspend;

    var data = prepareData(sbx.properties.pump, prefs, sbx);

    if (data.level >= levels.WARN) {
      sbx.notifications.requestNotify({
        level: data.level
        , title: data.title
        , message: data.message
        , pushoverSound: 'echo'
        , group: 'Pump'
        , plugin: pump
      });
    }
  };

  pump.updateVisualisation = function updateVisualisation (sbx) {
    var prop = sbx.properties.pump;

    var prefs = pump.getPrefs(sbx);
    var result = prepareData(prop, prefs, sbx);

    var values = [ ];
    var info = [ ];

    var selectedFields = sbx.data.inRetroMode ? prefs.retroFields : prefs.fields;

    _.forEach(ALL_STATUS_FIELDS, function eachField (fieldName) {
      var field = result[fieldName];
      if (field) {
        var selected = _.indexOf(selectedFields, fieldName) > -1;
        if (selected) {
          values.push(field.display);
        } else {
          info.push({label: field.label, value: field.display});
        }
      }
    });

    if (result.extended) {
      info.push({label: '------------', value: ''});
      _.forOwn(result.extended, function(value, key) {
         info.push({ label: key, value: value });
      });
    }

    sbx.pluginBase.updatePillText(pump, {
      value: values.join(' ')
      , info: info
      , label: translate('Pump')
      , pillClass: statusClass(result.level)
    });
  };

  function virtAsstReservoirHandler (next, slots, sbx) {
    var reservoir = sbx.properties.pump.pump.reservoir;
    if (reservoir) {
      var response = translate('virtAsstReservoir', {
        params: [
            reservoir
        ]
      });
      next(translate('virtAsstTitlePumpReservoir'), response);
    } else {
      next(translate('virtAsstTitlePumpReservoir'), translate('virtAsstUnknown'));
    }
  }

  function virtAsstBatteryHandler (next, slots, sbx) {
    var battery = _.get(sbx, 'properties.pump.data.battery');
    if (battery) {
      var response = translate('virtAsstPumpBattery', {
              params: [
                  battery.value,
                  battery.unit
              ]
          });
      next(translate('virtAsstTitlePumpBattery'), response);
    } else {
      next(translate('virtAsstTitlePumpBattery'), translate('virtAsstUnknown'));
    }
  }

  pump.virtAsst = {
    intentHandlers:[
      {
        // backwards compatibility
        intent: 'InsulinRemaining',
        intentHandler: virtAsstReservoirHandler
      }
      , {
        // backwards compatibility
        intent: 'PumpBattery',
        intentHandler: virtAsstBatteryHandler
      }
      , {
        intent: 'MetricNow'
        , metrics: ['pump reservoir']
        , intentHandler: virtAsstReservoirHandler
      }
      , {
        intent: 'MetricNow'
        , metrics: ['pump battery']
        , intentHandler: virtAsstBatteryHandler
      }
    ]
  };

  function statusClass (level) {
    var cls = 'current';

    if (level === levels.WARN) {
      cls = 'warn';
    } else if (level === levels.URGENT) {
      cls = 'urgent';
    }

    return cls;
  }

  function updateClock (prefs, result, sbx) {
    if (result.clock) {
      result.clock.label = 'Last Clock';
      result.clock.display = timeFormat(result.clock.value, sbx);

      var urgent = moment(sbx.time).subtract(prefs.urgentClock, 'minutes');
      var warn = moment(sbx.time).subtract(prefs.warnClock, 'minutes');

      if (urgent.isAfter(result.clock.value)) {
        result.clock.level = levels.URGENT;
        result.clock.message = 'URGENT: Pump data stale';
      } else if (warn.isAfter(result.clock.value)) {
        result.clock.level = levels.WARN;
        result.clock.message = 'Warning, Pump data stale';
      } else {
        result.clock.level = levels.NONE;
      }
    }
  }

  function updateReservoir (prefs, result) {
    if (result.reservoir) {
      result.reservoir.label = 'Reservoir';
      result.reservoir.display = result.reservoir.value.toPrecision(3) + 'U';
      if (result.reservoir.value < prefs.urgentRes) {
        result.reservoir.level = levels.URGENT;
        result.reservoir.message = 'URGENT: Pump Reservoir Low';
      } else if (result.reservoir.value < prefs.warnRes) {
        result.reservoir.level = levels.WARN;
        result.reservoir.message = 'Warning, Pump Reservoir Low';
      } else {
        result.reservoir.level = levels.NONE;
      }
    } else if (result.manufacturer === 'Insulet' &&  result.model === 'Eros') {
      result.reservoir = {
        label: 'Reservoir', display: '50+ U'
      }
    }
  }

  function updateBattery (type, prefs, result) {
    if (result.battery) {
      result.battery.label = 'Battery';
      result.battery.display = result.battery.value + type;
      var urgent = type === 'v' ? prefs.urgentBattV : prefs.urgentBattP;
      var warn = type === 'v' ? prefs.warnBattV : prefs.warnBattP;

      if (result.battery.value < urgent) {
        result.battery.level = levels.URGENT;
        result.battery.message = 'URGENT: Pump Battery Low';
      } else if (result.battery.value < warn) {
        result.battery.level = levels.WARN;
        result.battery.message = 'Warning, Pump Battery Low';
      } else {
        result.battery.level = levels.NONE;
      }
    }
  }

  function buildMessage (result) {
    if (result.level > levels.NONE) {
      var message = [];

      if (result.battery) {
        message.push('Pump Battery: ' + result.battery.display);
      }

      if (result.reservoir) {
        message.push('Pump Reservoir: ' + result.reservoir.display);
      }

      result.message = message.join('\n');
    }
  }

  function updateStatus(pump, result) {
    if (pump.status) {
      var status = pump.status.status || 'normal';
      if (pump.status.bolusing) {
        status = 'bolusing';
      } else if (pump.status.suspended) {
        status = 'suspended';
        if (pump.warnOnSuspend && pump.status.suspended) {
          result.status.level = levels.WARN;
          result.status.message = 'Pump Suspended';
        }
      }
      result.status = { value: status, display: status, label: translate('Status') };
    }
  }

  function prepareData (prop, prefs, sbx) {
    var pump = (prop && prop.pump) || { };

    var result = {
      level: levels.NONE
      , clock: pump.clock ? { value: moment(pump.clock) } : null
      , reservoir: pump.reservoir || pump.reservoir === 0 ? { value: pump.reservoir } : null
      , manufacturer: pump.manufacturer
      , model: pump.model
      , extended: pump.extended || null
    };

    updateClock(prefs, result, sbx);
    updateReservoir(prefs, result);
    updateStatus(pump, result);

    if (pump.battery && pump.battery.percent) {
      result.battery = { value: pump.battery.percent, unit: 'percent' };
      updateBattery('%', prefs, result);
    } else if (pump.battery && pump.battery.voltage) {
      result.battery = { value: pump.battery.voltage, unit: 'volts'};
      updateBattery('v', prefs, result);
    }

    result.device = { label: translate('Device'), display: prop.device };

    result.title = 'Pump Status';
    result.level = levels.NONE;

    //TODO: A new Pump Offline marker?  Something generic?  Use something new instead of a treatment?
    if (openaps.findOfflineMarker(sbx)) {
      console.info('OpenAPS known offline, not checking for alerts');
    } else {
      _.forEach(ALL_STATUS_FIELDS, function eachField(fieldName) {
        var field = result[fieldName];
        if (field && field.level > result.level) {
          result.level = field.level;
          result.title = field.message;
        }
      });
    }

    buildMessage(result);

    return result;
  }

  function timeFormat (m, sbx) {

    var when;
    if (m && sbx.data.inRetroMode) {
      when = m.format('LT');
    } else if (m) {
      when = formatAgo(m, sbx.time);
    } else {
      when = 'unknown';
    }

    return when;
  }

  function formatAgo (m, nowMills) {
    var ago = timeago.calcDisplay({mills: m.valueOf()}, nowMills);
    return translate('%1' + ago.shortLabel + (ago.shortLabel.length === 1 ? ' ago' : ''), { params: [(ago.value ? ago.value : '')]});
  }

  return pump;
}

module.exports = init;
<commit_msg>Handled 0 for pump reservoir<commit_after>'use strict';

var _ = require('lodash');
var moment = require('moment');
var levels = require('../levels');
var times = require('../times');

var ALL_STATUS_FIELDS = ['reservoir', 'battery', 'clock', 'status', 'device'];

function init (ctx) {
  var translate = ctx.language.translate;
  var timeago = require('./timeago')(ctx);
  var openaps = require('./openaps')(ctx);

  var pump = {
    name: 'pump'
    , label: 'Pump'
    , pluginType: 'pill-status'
  };

  pump.getPrefs = function getPrefs (sbx) {

    function cleanList (value) {
      return decodeURIComponent(value || '').toLowerCase().split(' ');
    }

    function isEmpty (list) {
      return _.isEmpty(list) || _.isEmpty(list[0]);
    }

    var fields = cleanList(sbx.extendedSettings.fields);
    fields = isEmpty(fields) ? ['reservoir'] : fields;

    var retroFields = cleanList(sbx.extendedSettings.retroFields);
    retroFields = isEmpty(retroFields) ? ['reservoir', 'battery'] : retroFields;

    return {
      fields: fields
      , retroFields: retroFields
      , warnClock: sbx.extendedSettings.warnClock || 30
      , urgentClock: sbx.extendedSettings.urgentClock || 60
      , warnRes: sbx.extendedSettings.warnRes || 10
      , urgentRes: sbx.extendedSettings.urgentRes || 5
      , warnBattV: sbx.extendedSettings.warnBattV || 1.35
      , urgentBattV: sbx.extendedSettings.urgentBattV || 1.3
      , warnBattP: sbx.extendedSettings.warnBattP || 30
      , urgentBattP: sbx.extendedSettings.urgentBattP || 20
      , warnOnSuspend: sbx.extendedSettings.warnOnSuspend || false
      , enableAlerts: sbx.extendedSettings.enableAlerts || false
    };
  };

  pump.setProperties = function setProperties (sbx) {
    sbx.offerProperty('pump', function setPump ( ) {

      var prefs = pump.getPrefs(sbx);
      var recentMills = sbx.time - times.mins(prefs.urgentClock * 2).msecs;

      var filtered = _.filter(sbx.data.devicestatus, function (status) {
        return ('pump' in status) && sbx.entryMills(status) <= sbx.time && sbx.entryMills(status) >= recentMills;
      });

      var pumpStatus = null;

      _.forEach(filtered, function each (status) {
        status.clockMills = status.pump && status.pump.clock ? moment(status.pump.clock).valueOf() : status.mills;
        if (!pumpStatus || status.clockMills > pumpStatus.clockMills) {
          pumpStatus = status;
        }
      });

      pumpStatus = pumpStatus || { };
      pumpStatus.data = prepareData(pumpStatus, prefs, sbx);

      return pumpStatus;
    });
  };

  pump.checkNotifications = function checkNotifications (sbx) {
    var prefs = pump.getPrefs(sbx);

    if (!prefs.enableAlerts) { return; }

    pump.warnOnSuspend = prefs.warnOnSuspend;

    var data = prepareData(sbx.properties.pump, prefs, sbx);

    if (data.level >= levels.WARN) {
      sbx.notifications.requestNotify({
        level: data.level
        , title: data.title
        , message: data.message
        , pushoverSound: 'echo'
        , group: 'Pump'
        , plugin: pump
      });
    }
  };

  pump.updateVisualisation = function updateVisualisation (sbx) {
    var prop = sbx.properties.pump;

    var prefs = pump.getPrefs(sbx);
    var result = prepareData(prop, prefs, sbx);

    var values = [ ];
    var info = [ ];

    var selectedFields = sbx.data.inRetroMode ? prefs.retroFields : prefs.fields;

    _.forEach(ALL_STATUS_FIELDS, function eachField (fieldName) {
      var field = result[fieldName];
      if (field) {
        var selected = _.indexOf(selectedFields, fieldName) > -1;
        if (selected) {
          values.push(field.display);
        } else {
          info.push({label: field.label, value: field.display});
        }
      }
    });

    if (result.extended) {
      info.push({label: '------------', value: ''});
      _.forOwn(result.extended, function(value, key) {
         info.push({ label: key, value: value });
      });
    }

    sbx.pluginBase.updatePillText(pump, {
      value: values.join(' ')
      , info: info
      , label: translate('Pump')
      , pillClass: statusClass(result.level)
    });
  };

  function virtAsstReservoirHandler (next, slots, sbx) {
    var reservoir = sbx.properties.pump.pump.reservoir;
    if (reservoir || reservoir === 0) {
      var response = translate('virtAsstReservoir', {
        params: [
            reservoir
        ]
      });
      next(translate('virtAsstTitlePumpReservoir'), response);
    } else {
      next(translate('virtAsstTitlePumpReservoir'), translate('virtAsstUnknown'));
    }
  }

  function virtAsstBatteryHandler (next, slots, sbx) {
    var battery = _.get(sbx, 'properties.pump.data.battery');
    if (battery) {
      var response = translate('virtAsstPumpBattery', {
              params: [
                  battery.value,
                  battery.unit
              ]
          });
      next(translate('virtAsstTitlePumpBattery'), response);
    } else {
      next(translate('virtAsstTitlePumpBattery'), translate('virtAsstUnknown'));
    }
  }

  pump.virtAsst = {
    intentHandlers:[
      {
        // backwards compatibility
        intent: 'InsulinRemaining',
        intentHandler: virtAsstReservoirHandler
      }
      , {
        // backwards compatibility
        intent: 'PumpBattery',
        intentHandler: virtAsstBatteryHandler
      }
      , {
        intent: 'MetricNow'
        , metrics: ['pump reservoir']
        , intentHandler: virtAsstReservoirHandler
      }
      , {
        intent: 'MetricNow'
        , metrics: ['pump battery']
        , intentHandler: virtAsstBatteryHandler
      }
    ]
  };

  function statusClass (level) {
    var cls = 'current';

    if (level === levels.WARN) {
      cls = 'warn';
    } else if (level === levels.URGENT) {
      cls = 'urgent';
    }

    return cls;
  }

  function updateClock (prefs, result, sbx) {
    if (result.clock) {
      result.clock.label = 'Last Clock';
      result.clock.display = timeFormat(result.clock.value, sbx);

      var urgent = moment(sbx.time).subtract(prefs.urgentClock, 'minutes');
      var warn = moment(sbx.time).subtract(prefs.warnClock, 'minutes');

      if (urgent.isAfter(result.clock.value)) {
        result.clock.level = levels.URGENT;
        result.clock.message = 'URGENT: Pump data stale';
      } else if (warn.isAfter(result.clock.value)) {
        result.clock.level = levels.WARN;
        result.clock.message = 'Warning, Pump data stale';
      } else {
        result.clock.level = levels.NONE;
      }
    }
  }

  function updateReservoir (prefs, result) {
    if (result.reservoir) {
      result.reservoir.label = 'Reservoir';
      result.reservoir.display = result.reservoir.value.toPrecision(3) + 'U';
      if (result.reservoir.value < prefs.urgentRes) {
        result.reservoir.level = levels.URGENT;
        result.reservoir.message = 'URGENT: Pump Reservoir Low';
      } else if (result.reservoir.value < prefs.warnRes) {
        result.reservoir.level = levels.WARN;
        result.reservoir.message = 'Warning, Pump Reservoir Low';
      } else {
        result.reservoir.level = levels.NONE;
      }
    } else if (result.manufacturer === 'Insulet' &&  result.model === 'Eros') {
      result.reservoir = {
        label: 'Reservoir', display: '50+ U'
      }
    }
  }

  function updateBattery (type, prefs, result) {
    if (result.battery) {
      result.battery.label = 'Battery';
      result.battery.display = result.battery.value + type;
      var urgent = type === 'v' ? prefs.urgentBattV : prefs.urgentBattP;
      var warn = type === 'v' ? prefs.warnBattV : prefs.warnBattP;

      if (result.battery.value < urgent) {
        result.battery.level = levels.URGENT;
        result.battery.message = 'URGENT: Pump Battery Low';
      } else if (result.battery.value < warn) {
        result.battery.level = levels.WARN;
        result.battery.message = 'Warning, Pump Battery Low';
      } else {
        result.battery.level = levels.NONE;
      }
    }
  }

  function buildMessage (result) {
    if (result.level > levels.NONE) {
      var message = [];

      if (result.battery) {
        message.push('Pump Battery: ' + result.battery.display);
      }

      if (result.reservoir) {
        message.push('Pump Reservoir: ' + result.reservoir.display);
      }

      result.message = message.join('\n');
    }
  }

  function updateStatus(pump, result) {
    if (pump.status) {
      var status = pump.status.status || 'normal';
      if (pump.status.bolusing) {
        status = 'bolusing';
      } else if (pump.status.suspended) {
        status = 'suspended';
        if (pump.warnOnSuspend && pump.status.suspended) {
          result.status.level = levels.WARN;
          result.status.message = 'Pump Suspended';
        }
      }
      result.status = { value: status, display: status, label: translate('Status') };
    }
  }

  function prepareData (prop, prefs, sbx) {
    var pump = (prop && prop.pump) || { };

    var result = {
      level: levels.NONE
      , clock: pump.clock ? { value: moment(pump.clock) } : null
      , reservoir: pump.reservoir || pump.reservoir === 0 ? { value: pump.reservoir } : null
      , manufacturer: pump.manufacturer
      , model: pump.model
      , extended: pump.extended || null
    };

    updateClock(prefs, result, sbx);
    updateReservoir(prefs, result);
    updateStatus(pump, result);

    if (pump.battery && pump.battery.percent) {
      result.battery = { value: pump.battery.percent, unit: 'percent' };
      updateBattery('%', prefs, result);
    } else if (pump.battery && pump.battery.voltage) {
      result.battery = { value: pump.battery.voltage, unit: 'volts'};
      updateBattery('v', prefs, result);
    }

    result.device = { label: translate('Device'), display: prop.device };

    result.title = 'Pump Status';
    result.level = levels.NONE;

    //TODO: A new Pump Offline marker?  Something generic?  Use something new instead of a treatment?
    if (openaps.findOfflineMarker(sbx)) {
      console.info('OpenAPS known offline, not checking for alerts');
    } else {
      _.forEach(ALL_STATUS_FIELDS, function eachField(fieldName) {
        var field = result[fieldName];
        if (field && field.level > result.level) {
          result.level = field.level;
          result.title = field.message;
        }
      });
    }

    buildMessage(result);

    return result;
  }

  function timeFormat (m, sbx) {

    var when;
    if (m && sbx.data.inRetroMode) {
      when = m.format('LT');
    } else if (m) {
      when = formatAgo(m, sbx.time);
    } else {
      when = 'unknown';
    }

    return when;
  }

  function formatAgo (m, nowMills) {
    var ago = timeago.calcDisplay({mills: m.valueOf()}, nowMills);
    return translate('%1' + ago.shortLabel + (ago.shortLabel.length === 1 ? ' ago' : ''), { params: [(ago.value ? ago.value : '')]});
  }

  return pump;
}

module.exports = init;
<|endoftext|>


<commit_before>'use strict';

var Utils = require('../../utils')
  , AbstractQuery = require('../abstract/query')
  , _ = require('lodash')
  , autocommit = true;

var Query = function(connection, sequelize, options) {
  this.connection = connection;
  this.instance = options.instance;
  this.model = options.model;
  this.sequelize = sequelize;
  this.options = _.extend({
    logging: console.log,
    plain: false,
    raw: false
  }, options || {});

  this.checkLoggingOption();
};

Utils.inherit(Query, AbstractQuery);

Query.prototype.run = function(sql) {
  var self = this;
  this.sql = sql;

  this.sequelize.log('Executing (' + (this.connection.uuid || 'default') + '): ' + this.sql, this.options);

  var promise = new Utils.Promise(function(resolve, reject) {
    // TRANSACTION SUPPORT
    if (_.contains(self.sql, 'ROLLBACK;')) {
      console.log('should roll back');
      self.connection.rollback(function(err) {
        if (!!err) {
          reject(self);
        } else {
          resolve(self);
        }
      });
    } else if (_.contains(self.sql, 'COMMIT;')) {
      console.log('should send commit');
      self.connection.commit(function(err) {
        if (!!err) {
          reject(self);
        } else {
          resolve(self);
        }
      });
    } else if (_.contains(self.sql, 'SET AUTOCOMMIT ON')) {
      autocommit = true;
      console.log('auto commit is set on');
    } else if (_.contains(self.sql, 'SET AUTOCOMMIT OFF')) {
      autocommit = false;
      console.log('auto commit is set off');
    } else {
      // QUERY SUPPORT
      var variables = {};
      if (self.sql.match('RETURNING "(.*?)" INTO')) {
        variables[self.sql.match('RETURNING "(.*?)" INTO')[1]] = { type: self.connection.lib.NUMBER, dir: self.connection.lib.BIND_OUT };
      }
      self.connection.execute(self.sql, variables, {autoCommit: autocommit}, function(err, result) {
        if (err) {
          err.sql = sql;
          console.log('Auto commit:'+ autocommit + ' Exec: =====  ' + sql + '===== end of code');
          console.log('Got error: ' + err);
          reject(err);
        } else {
          // console.log('Auto commit:'+ autocommit + ' Exec: =====  ' + sql + '===== end of code');
          // console.log('Result rows:', result.rows);
          // console.log('Meta data:', result.metaData);
          // console.log('Out Binds:', result.outBinds);
          resolve(self.formatResults(result));
        }
      });
    }
  });

  return promise;
};

Query.prototype.getInsertIdField = function() {
  return 'id';
};

Query.prototype.formatResults = function(data) {
  var result = this.instance;
  if (this.isInsertQuery(data)) {
    this.handleInsertQuery(data);

    if (!this.instance) {
      if (this.options.plain) {
        var record = data[0];
        result = record[Object.keys(record)[0]];
      } else {
        result = data;
      }
    }

    if (data.outBinds) {
      for (var attrname in data.outBinds) { result.dataValues[attrname] = data.outBinds[attrname][0]; }
    }
  }

  if (this.isShowTablesQuery()) {
    result = this.handleShowTablesQuery(data.rows);
  } else if (this.isDescribeQuery()) {
    result = {};
    data.forEach(function(_result) {
      if (_result.Default) {
        _result.Default = _result.Default.replace("('",'').replace("')",'').replace(/'/g,''); /* jshint ignore: line */
      }

      result[_result.Name] = {
        type: _result.Type.toUpperCase(),
        allowNull: (_result.IsNull === 'YES' ? true : false),
        defaultValue: _result.Default,
        primaryKey: _result.Constraint === 'PRIMARY KEY'
      };
    });
  } else if (this.isShowIndexesQuery()) {
    result = data.rows;
  } else if (this.isSelectQuery()) {
    result = this.handleSelectQuery(data.rows);
  } else if (this.isCallQuery()) {
    result = data.rows[0];
  } else if (this.isBulkUpdateQuery()) {
    result = data.length;
  } else if (this.isBulkDeleteQuery()){
    result = data[0] && data[0].AFFECTEDROWS;
  } else if (this.isVersionQuery()) {
    result = data.version;
  } else if (this.isForeignKeysQuery()) {
    result = data.rows;
  } else if (this.isRawQuery()) {
    // MSSQL returns row data and metadata (affected rows etc) in a single object - let's standarize it, sorta
    result = [data.rows, data.metaData];
   }
  return result;
};

module.exports = Query;
<commit_msg>Oracle error handling with first exception.<commit_after>'use strict';

var Utils = require('../../utils')
  , AbstractQuery = require('../abstract/query')
  , _ = require('lodash')
  , autocommit = true
  , sequelizeErrors = require('../../errors.js');

var Query = function(connection, sequelize, options) {
  this.connection = connection;
  this.instance = options.instance;
  this.model = options.model;
  this.sequelize = sequelize;
  this.options = _.extend({
    logging: console.log,
    plain: false,
    raw: false
  }, options || {});

  this.checkLoggingOption();
};

Utils.inherit(Query, AbstractQuery);

Query.prototype.run = function(sql) {
  var self = this;
  this.sql = sql;

  this.sequelize.log('Executing (' + (this.connection.uuid || 'default') + '): ' + this.sql, this.options);

  var promise = new Utils.Promise(function(resolve, reject) {
    // TRANSACTION SUPPORT
    if (_.contains(self.sql, 'ROLLBACK;')) {
      console.log('should roll back');
      self.connection.rollback(function(err) {
        if (!!err) {
          reject(self.formatError(err, self.sql));
        } else {
          resolve(self);
        }
      });
    } else if (_.contains(self.sql, 'COMMIT;')) {
      console.log('should send commit');
      self.connection.commit(function(err) {
        if (!!err) {
          reject(self.formatError(err, self.sql));
        } else {
          resolve(self);
        }
      });
    } else if (_.contains(self.sql, 'SET AUTOCOMMIT ON')) {
      autocommit = true;
      console.log('auto commit is set on');
    } else if (_.contains(self.sql, 'SET AUTOCOMMIT OFF')) {
      autocommit = false;
      console.log('auto commit is set off');
    } else {
      // QUERY SUPPORT
      var variables = {};
      if (self.sql.match('RETURNING "(.*?)" INTO')) {
        variables[self.sql.match('RETURNING "(.*?)" INTO')[1]] = { type: self.connection.lib.NUMBER, dir: self.connection.lib.BIND_OUT };
      }
      self.connection.execute(self.sql, variables, {autoCommit: autocommit}, function(err, result) {
        if (err) {
          console.log('Auto commit:'+ autocommit + ' Exec: =====  ' + sql + '===== end of code');
          console.log('Got error: ' + err);
          reject(self.formatError(err, sql));
        } else {
          // console.log('Auto commit:'+ autocommit + ' Exec: =====  ' + sql + '===== end of code');
          // console.log('Result rows:', result.rows);
          // console.log('Meta data:', result.metaData);
          // console.log('Out Binds:', result.outBinds);
          resolve(self.formatResults(result));
        }
      });
    }
  });

  return promise;
};

Query.prototype.getInsertIdField = function() {
  return 'id';
};

Query.prototype.formatError = function (err) {
  var match;
  console.log(err);
  match = err.toString().match('ORA-02291');
  if (match !== null) {
    return new sequelizeErrors.ForeignKeyConstraintError({
      parent :err
    });
  }
  return err;
};

Query.prototype.formatResults = function(data) {
  var result = this.instance;
  if (this.isInsertQuery(data)) {
    this.handleInsertQuery(data);

    if (!this.instance) {
      if (this.options.plain) {
        var record = data[0];
        result = record[Object.keys(record)[0]];
      } else {
        result = data;
      }
    }

    if (data.outBinds) {
      for (var attrname in data.outBinds) { result.dataValues[attrname] = data.outBinds[attrname][0]; }
    }
  }

  if (this.isShowTablesQuery()) {
    result = this.handleShowTablesQuery(data.rows);
  } else if (this.isDescribeQuery()) {
    result = {};
    data.forEach(function(_result) {
      if (_result.Default) {
        _result.Default = _result.Default.replace("('",'').replace("')",'').replace(/'/g,''); /* jshint ignore: line */
      }

      result[_result.Name] = {
        type: _result.Type.toUpperCase(),
        allowNull: (_result.IsNull === 'YES' ? true : false),
        defaultValue: _result.Default,
        primaryKey: _result.Constraint === 'PRIMARY KEY'
      };
    });
  } else if (this.isShowIndexesQuery()) {
    result = data.rows;
  } else if (this.isSelectQuery()) {
    result = this.handleSelectQuery(data.rows);
  } else if (this.isCallQuery()) {
    result = data.rows[0];
  } else if (this.isBulkUpdateQuery()) {
    result = data.length;
  } else if (this.isBulkDeleteQuery()){
    result = data[0] && data[0].AFFECTEDROWS;
  } else if (this.isVersionQuery()) {
    result = data.version;
  } else if (this.isForeignKeysQuery()) {
    result = data.rows;
  } else if (this.isRawQuery()) {
    // MSSQL returns row data and metadata (affected rows etc) in a single object - let's standarize it, sorta
    result = [data.rows, data.metaData];
   }
  return result;
};

module.exports = Query;
<|endoftext|>


<commit_before>
// Express - Cache - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)

/**
 * Module dependencies.
 */

var Request = require('express/request').Request

// --- Cache

var Cache = new Class({

  /**
   * Initialize cache with _key_ and _val_.
   */

  constructor: function(key, val) {
    this.key = key
    this.val = val
    this.created = Date.now()
  }
})

// --- Store

exports.Store = new Class({

  /**
   * Ensure that the given _key_ is a string.
   * Override in subclass to provide data-store specific functionality.
   *
   * @param  {string} key
   * @param  {string} val
   * @param  {function} callback
   * @api public
   */

  set: function(key, val, callback) {
    if (typeof key !== 'string')
      throw new Error(this.name + ' store #set() key must be a string')
  },

  /**
   * Ensure that the given _key_ is a string.
   * Override in subclass to provide data-store specific functionality.
   *
   * @param  {string} key
   * @param  {function} callback
   * @api public
   */

  get: function(key, callback) {
    if (typeof key !== 'string')
      throw new Error(this.name + 'store #get() key must be a string')
  },

  /**
   * Convert to '[NAME Store]'.
   *
   * @return {string}
   * @api public
   */

  toString: function() {
    return '[' + this.name + ' Store]'
  }
})

// --- Store.Memory

exports.Store.Memory = exports.Store.extend({

  /**
   * Datastore name.
   */

  name: 'Memory',

  /**
   * Initialize data.
   */

  constructor: function() {
    this.data = {}
  },

  /**
   * Set the given _key_ to _val_.
   *
   * @param  {string} key
   * @param  {string} val
   * @param  {function} callback
   * @return {string}
   * @api public
   */

  set: function(key, val, callback) {
    exports.Store.prototype.set.apply(this, arguments)
    this.data[key] = new Cache(key, val)
    if (callback) callback(val)
  },

  /**
   * Get data found matching the given _key_.
   *
   * Examples:
   *
   *   cache.get('page:front', function(val){})
   *   // => '...'
   *
   *   cache.get('page:*', function(vals){})
   *   // => { 'page:front': '...',
   *           'page:users': '...',
   *            ... }
   *
   * @param  {string} key
   * @param  {function} callback
   * @return {mixed}
   * @api public
   */

  get: function(key, callback) {
    exports.Store.prototype.get.apply(this, arguments)
    if (key.indexOf('*') === -1)
      return callback(this.data[key] instanceof Cache
        ? this.data[key].val
        : null)
    var regexp = this.normalize(key)
    callback(this.data.reduce(function(vals, cache){
      if (regexp.test(cache.key))
        vals[cache.key] = cache.val
      return vals
    }, {}))
  },

  /**
   * Clear data matching the given _key_.
   *
   * Examples:
   *
   *   cache.clear('page:front', function(){})
   *   cache.clear('page:*', function(){})
   *
   * @param  {string} key
   * @param  {function} callback
   * @api public
   */

  clear: function(key, callback) {
    if (key.indexOf('*') === -1)
      delete this.data[key]
    else {
      var regexp = this.normalize(key)
      for (var key in this.data)
        if (this.data.hasOwnProperty(key))
          if (regexp.test(key))
            delete this.data[key]
    }
    callback()
  },

  /**
   * Reap caches older than _ms_.
   *
   * @param  {int} ms
   * @api private
   */

  reap: function(ms, callback) {
    var self = this,
        threshold = +new Date(Date.now() - ms)
    this.data.each(function(cache){
      if (cache.created < threshold)
        self.clear(cache.key, function(){})
    })
    if (callback) callback()
  },

  /**
   * Convert the given key matching _pattern_
   * into a RegExp.
   *
   *  - *  is converted to (.*?)
   *
   * @param  {string} pattern
   * @return {regexp}
   * @api private
   */

  normalize: function(pattern) {
    return new RegExp('^' + pattern.replace(/[*]/g, '(.*?)') + '$')
  }
})

// --- Cache

exports.Cache = Plugin.extend({
  extend: {

    /**
     * Initialize memory store and start reaper.
     *
     * Options:
     *
     *  - dataStore                constructor name of cache data store, defaults to Store.Memory
     *  - lifetime                 lifetime of cache in milliseconds, defaults to one day
     *  - reapInterval, reapEvery  interval in milliseconds in which to reap old caches, defaults to one hour
     *
     * @param  {hash} options
     * @api private
     */

    init: function(options) {
      this.merge(options || {})
      this.store = new (this.dataStore || exports.Store.Memory)(options)
      Request.include({ cache: this.store })
      this.startReaper()
    },

    /**
     * Start reaper.
     *
     * @param  {function} callback
     * @api private
     */

    startReaper: function(callbac) {
      setInterval(function(self){
        self.store.reap(self.lifetime || (1).day)
      }, this.reapInterval || this.reapEvery || (1).hour, this)
    }
  }
})<commit_msg>Removed unused param in Cache.startReaper()<commit_after>
// Express - Cache - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)

/**
 * Module dependencies.
 */

var Request = require('express/request').Request

// --- Cache

var Cache = new Class({

  /**
   * Initialize cache with _key_ and _val_.
   */

  constructor: function(key, val) {
    this.key = key
    this.val = val
    this.created = Date.now()
  }
})

// --- Store

exports.Store = new Class({

  /**
   * Ensure that the given _key_ is a string.
   * Override in subclass to provide data-store specific functionality.
   *
   * @param  {string} key
   * @param  {string} val
   * @param  {function} callback
   * @api public
   */

  set: function(key, val, callback) {
    if (typeof key !== 'string')
      throw new Error(this.name + ' store #set() key must be a string')
  },

  /**
   * Ensure that the given _key_ is a string.
   * Override in subclass to provide data-store specific functionality.
   *
   * @param  {string} key
   * @param  {function} callback
   * @api public
   */

  get: function(key, callback) {
    if (typeof key !== 'string')
      throw new Error(this.name + 'store #get() key must be a string')
  },

  /**
   * Convert to '[NAME Store]'.
   *
   * @return {string}
   * @api public
   */

  toString: function() {
    return '[' + this.name + ' Store]'
  }
})

// --- Store.Memory

exports.Store.Memory = exports.Store.extend({

  /**
   * Datastore name.
   */

  name: 'Memory',

  /**
   * Initialize data.
   */

  constructor: function() {
    this.data = {}
  },

  /**
   * Set the given _key_ to _val_.
   *
   * @param  {string} key
   * @param  {string} val
   * @param  {function} callback
   * @return {string}
   * @api public
   */

  set: function(key, val, callback) {
    exports.Store.prototype.set.apply(this, arguments)
    this.data[key] = new Cache(key, val)
    if (callback) callback(val)
  },

  /**
   * Get data found matching the given _key_.
   *
   * Examples:
   *
   *   cache.get('page:front', function(val){})
   *   // => '...'
   *
   *   cache.get('page:*', function(vals){})
   *   // => { 'page:front': '...',
   *           'page:users': '...',
   *            ... }
   *
   * @param  {string} key
   * @param  {function} callback
   * @return {mixed}
   * @api public
   */

  get: function(key, callback) {
    exports.Store.prototype.get.apply(this, arguments)
    if (key.indexOf('*') === -1)
      return callback(this.data[key] instanceof Cache
        ? this.data[key].val
        : null)
    var regexp = this.normalize(key)
    callback(this.data.reduce(function(vals, cache){
      if (regexp.test(cache.key))
        vals[cache.key] = cache.val
      return vals
    }, {}))
  },

  /**
   * Clear data matching the given _key_.
   *
   * Examples:
   *
   *   cache.clear('page:front', function(){})
   *   cache.clear('page:*', function(){})
   *
   * @param  {string} key
   * @param  {function} callback
   * @api public
   */

  clear: function(key, callback) {
    if (key.indexOf('*') === -1)
      delete this.data[key]
    else {
      var regexp = this.normalize(key)
      for (var key in this.data)
        if (this.data.hasOwnProperty(key))
          if (regexp.test(key))
            delete this.data[key]
    }
    callback()
  },

  /**
   * Reap caches older than _ms_.
   *
   * @param  {int} ms
   * @api private
   */

  reap: function(ms, callback) {
    var self = this,
        threshold = +new Date(Date.now() - ms)
    this.data.each(function(cache){
      if (cache.created < threshold)
        self.clear(cache.key, function(){})
    })
    if (callback) callback()
  },

  /**
   * Convert the given key matching _pattern_
   * into a RegExp.
   *
   *  - *  is converted to (.*?)
   *
   * @param  {string} pattern
   * @return {regexp}
   * @api private
   */

  normalize: function(pattern) {
    return new RegExp('^' + pattern.replace(/[*]/g, '(.*?)') + '$')
  }
})

// --- Cache

exports.Cache = Plugin.extend({
  extend: {

    /**
     * Initialize memory store and start reaper.
     *
     * Options:
     *
     *  - dataStore                constructor name of cache data store, defaults to Store.Memory
     *  - lifetime                 lifetime of cache in milliseconds, defaults to one day
     *  - reapInterval, reapEvery  interval in milliseconds in which to reap old caches, defaults to one hour
     *
     * @param  {hash} options
     * @api private
     */

    init: function(options) {
      this.merge(options || {})
      this.store = new (this.dataStore || exports.Store.Memory)(options)
      Request.include({ cache: this.store })
      this.startReaper()
    },

    /**
     * Start reaper.
     *
     * @api private
     */

    startReaper: function() {
      setInterval(function(self){
        self.store.reap(self.lifetime || (1).day)
      }, this.reapInterval || this.reapEvery || (1).hour, this)
    }
  }
})<|endoftext|>


<commit_before>import { join } from 'node:path';
import get from 'lodash.get';
import intel from 'intel';
import {
  android_sampling_interval,
  desktop_sampling_interval
} from './settings/geckoProfilerDefaults.js';
import { isAndroidConfigured, Android } from '../android/index.js';
import pathToFolder from '../support/pathToFolder.js';
import { BrowserError } from '../support/errors.js';
const delay = ms => new Promise(res => setTimeout(res, ms));
const log = intel.getLogger('browsertime.firefox');

/**
 * Timeout a promise after ms. Use promise.race to compete
 * about the timeout and the promise.
 * @param {promise} promise - The promise to wait for
 * @param {int} ms - how long in ms to wait for the promise to fininsh
 * @param {string} errorMessage - the error message in the Error if we timeouts
 */
async function timeout(promise, ms, errorMessage) {
  let timer;

  return Promise.race([
    new Promise((resolve, reject) => {
      timer = setTimeout(reject, ms, new BrowserError(errorMessage));
      return timer;
    }),
    promise.then(value => {
      clearTimeout(timer);
      return value;
    })
  ]);
}
class GeckoProfiler {
  constructor(runner, storageManager, firefoxConfig, options) {
    this.runner = runner;
    this.storageManager = storageManager;
    this.firefoxConfig = firefoxConfig;
    this.options = options;
  }

  async start() {
    const runner = this.runner;
    const firefoxConfig = this.firefoxConfig;
    const options = this.options;
    const chosenFeatures =
      firefoxConfig.geckoProfilerParams.features.split(',');
    const featureString = '["' + chosenFeatures.join('","') + '"]';

    const chosenThreads = firefoxConfig.geckoProfilerParams.threads.split(',');
    const threadString = '["' + chosenThreads.join('","') + '"]';

    let interval = firefoxConfig.geckoProfilerParams.interval;

    // Set platform specific sampling intervals if not explicitly specified.
    if (
      firefoxConfig.geckoProfiler &&
      !firefoxConfig.geckoProfilerParams.interval
    ) {
      interval = isAndroidConfigured(options)
        ? android_sampling_interval
        : desktop_sampling_interval;
    }

    const bufferSize = firefoxConfig.geckoProfilerParams.bufferSize;

    // Firefox 69 and above has a slightly different API for StartProfiler
    // See nsIProfiler::StartProfiler in tools/profiler/gecko/nsIProfiler.idl
    const parameterLength = await runner.runPrivilegedScript(
      'return Services.profiler.StartProfiler.length;',
      'Get StartProfiler.length'
    );

    let script;
    if (parameterLength === 7) {
      script = `Services.profiler.StartProfiler(${bufferSize},${interval},${featureString},
        ${chosenFeatures.length},${threadString},${chosenThreads.length});`;
    } else if (parameterLength === 5 || parameterLength === 6) {
      script = `Services.profiler.StartProfiler(${bufferSize},${interval},${featureString},${threadString});`;
    } else {
      log.error('Unknown Gecko Profiler API');
      throw new Error('Unknown Gecko Profiler API');
    }

    log.info(
      'Start GeckoProfiler with features: %s and threads: %s',
      featureString,
      threadString
    );

    await runner.runPrivilegedScript(script, 'Start GeckoProfiler');
    return delay(firefoxConfig.geckoProfilerSettleTime || 3000);
  }

  async stop(index, url) {
    const runner = this.runner;
    const storageManager = this.storageManager;
    const options = this.options;
    let profileDir = await storageManager.createSubDataDir(
      join(pathToFolder(url, options))
    );
    let destinationFilename = join(profileDir, `geckoProfile-${index}.json`);

    let deviceProfileFilename = destinationFilename;
    if (isAndroidConfigured(options)) {
      deviceProfileFilename = `/sdcard/Android/data/${get(
        this.firefoxConfig,
        'android.package',
        'org.mozilla.firefox'
      )}/files/geckoProfile-${index}.json`;
    }

    // Must use String.raw or else the backslashes on Windows will be escapes.
    log.info(
      `Collecting Gecko profile from ${deviceProfileFilename} to ${destinationFilename}`
    );
    // Pause profiler before we collect the profile, so that we don't capture
    // more samples while the parent process waits for subprocess profiles.
    await runner.runPrivilegedScript(
      'Services.profiler.Pause();',
      'Pause GeckoProfiler.'
    );
    const script = `
      var callback = arguments[arguments.length - 1];
       Services.profiler.dumpProfileToFileAsync(String.raw\`${deviceProfileFilename}\`)
        .then(callback)
        .catch((e) => callback({'error' : e}));
       `;
    try {
      await timeout(
        runner.runPrivilegedAsyncScript(script, 'Collect GeckoProfiler'),
        1_200_000,
        'Could not get the Geckoprofiler log'
      );
      log.info('Stop GeckoProfiler.');
      await runner.runPrivilegedScript(
        'Services.profiler.StopProfiler();',
        'Stop GeckoProfiler'
      );

      if (isAndroidConfigured(options)) {
        const android = new Android(options);
        await android._downloadFile(deviceProfileFilename, destinationFilename);
      }

      // GZIP the profile and remove the old file
      return storageManager.gzip(
        destinationFilename,
        join(profileDir, `geckoProfile-${index}.json.gz`),
        true
      );
    } catch (error) {
      log.error(error.message);
    }
  }

  addMetaData() {}
}

export default GeckoProfiler;
<commit_msg>Provide active tab id to gecko profiler StartProfiler API (#1874)<commit_after>import { join } from 'node:path';
import get from 'lodash.get';
import intel from 'intel';
import {
  android_sampling_interval,
  desktop_sampling_interval
} from './settings/geckoProfilerDefaults.js';
import { isAndroidConfigured, Android } from '../android/index.js';
import pathToFolder from '../support/pathToFolder.js';
import { BrowserError } from '../support/errors.js';
const delay = ms => new Promise(res => setTimeout(res, ms));
const log = intel.getLogger('browsertime.firefox');

/**
 * Timeout a promise after ms. Use promise.race to compete
 * about the timeout and the promise.
 * @param {promise} promise - The promise to wait for
 * @param {int} ms - how long in ms to wait for the promise to fininsh
 * @param {string} errorMessage - the error message in the Error if we timeouts
 */
async function timeout(promise, ms, errorMessage) {
  let timer;

  return Promise.race([
    new Promise((resolve, reject) => {
      timer = setTimeout(reject, ms, new BrowserError(errorMessage));
      return timer;
    }),
    promise.then(value => {
      clearTimeout(timer);
      return value;
    })
  ]);
}
class GeckoProfiler {
  constructor(runner, storageManager, firefoxConfig, options) {
    this.runner = runner;
    this.storageManager = storageManager;
    this.firefoxConfig = firefoxConfig;
    this.options = options;
  }

  async start() {
    const runner = this.runner;
    const firefoxConfig = this.firefoxConfig;
    const options = this.options;
    const chosenFeatures =
      firefoxConfig.geckoProfilerParams.features.split(',');
    const featureString = '["' + chosenFeatures.join('","') + '"]';

    const chosenThreads = firefoxConfig.geckoProfilerParams.threads.split(',');
    const threadString = '["' + chosenThreads.join('","') + '"]';

    let interval = firefoxConfig.geckoProfilerParams.interval;

    // Set platform specific sampling intervals if not explicitly specified.
    if (
      firefoxConfig.geckoProfiler &&
      !firefoxConfig.geckoProfilerParams.interval
    ) {
      interval = isAndroidConfigured(options)
        ? android_sampling_interval
        : desktop_sampling_interval;
    }

    const bufferSize = firefoxConfig.geckoProfilerParams.bufferSize;

    // Firefox 69 and above has a slightly different API for StartProfiler
    // See nsIProfiler::StartProfiler in tools/profiler/gecko/nsIProfiler.idl
    const parameterLength = await runner.runPrivilegedScript(
      'return Services.profiler.StartProfiler.length;',
      'Get StartProfiler.length'
    );

    let script;
    switch (parameterLength) {
      case 7: {
        // Oldest profiler API. It was deprecated in Firefox 69.
        script = `Services.profiler.StartProfiler(${bufferSize},${interval},${featureString},
          ${chosenFeatures.length},${threadString},${chosenThreads.length});`;
        break;
      }
      case 6: {
        // Newest profiler API. It's being used since Firefox 72.
        // `activeBrowserId` is useful for distinguishing browser tabs in the profiler UI.
        const activeBrowserIdScript = `
          const win = Services.wm.getMostRecentWindow("navigator:browser");
          return win?.gBrowser?.selectedBrowser?.browsingContext?.browserId ?? 0;
      `;
        const activeBrowserId = await runner.runPrivilegedScript(
          activeBrowserIdScript,
          'Get activeBrowserId'
        );
        script = `Services.profiler.StartProfiler(${bufferSize},${interval},${featureString},
          ${threadString},${activeBrowserId});`;
        break;
      }
      case 5: {
        // The profiler API that was used between Firefox 69 and 72.
        script = `Services.profiler.StartProfiler(${bufferSize},${interval},${featureString},
          ${threadString});`;
        break;
      }
      default: {
        log.error('Unknown Gecko Profiler API');
        throw new Error('Unknown Gecko Profiler API');
      }
    }

    log.info(
      'Start GeckoProfiler with features: %s and threads: %s',
      featureString,
      threadString
    );

    await runner.runPrivilegedScript(script, 'Start GeckoProfiler');
    return delay(firefoxConfig.geckoProfilerSettleTime || 3000);
  }

  async stop(index, url) {
    const runner = this.runner;
    const storageManager = this.storageManager;
    const options = this.options;
    let profileDir = await storageManager.createSubDataDir(
      join(pathToFolder(url, options))
    );
    let destinationFilename = join(profileDir, `geckoProfile-${index}.json`);

    let deviceProfileFilename = destinationFilename;
    if (isAndroidConfigured(options)) {
      deviceProfileFilename = `/sdcard/Android/data/${get(
        this.firefoxConfig,
        'android.package',
        'org.mozilla.firefox'
      )}/files/geckoProfile-${index}.json`;
    }

    // Must use String.raw or else the backslashes on Windows will be escapes.
    log.info(
      `Collecting Gecko profile from ${deviceProfileFilename} to ${destinationFilename}`
    );
    // Pause profiler before we collect the profile, so that we don't capture
    // more samples while the parent process waits for subprocess profiles.
    await runner.runPrivilegedScript(
      'Services.profiler.Pause();',
      'Pause GeckoProfiler.'
    );
    const script = `
      var callback = arguments[arguments.length - 1];
       Services.profiler.dumpProfileToFileAsync(String.raw\`${deviceProfileFilename}\`)
        .then(callback)
        .catch((e) => callback({'error' : e}));
       `;
    try {
      await timeout(
        runner.runPrivilegedAsyncScript(script, 'Collect GeckoProfiler'),
        1_200_000,
        'Could not get the Geckoprofiler log'
      );
      log.info('Stop GeckoProfiler.');
      await runner.runPrivilegedScript(
        'Services.profiler.StopProfiler();',
        'Stop GeckoProfiler'
      );

      if (isAndroidConfigured(options)) {
        const android = new Android(options);
        await android._downloadFile(deviceProfileFilename, destinationFilename);
      }

      // GZIP the profile and remove the old file
      return storageManager.gzip(
        destinationFilename,
        join(profileDir, `geckoProfile-${index}.json.gz`),
        true
      );
    } catch (error) {
      log.error(error.message);
    }
  }

  addMetaData() {}
}

export default GeckoProfiler;
<|endoftext|>


<commit_before>// Read all filenames from directory and it's subdirectories

'use strict';

var call       = Function.prototype.call
  , keys       = Object.keys
  , trim       = call.bind(String.prototype.trim)
  , fs         = require('fs')
  , normalize  = require('../path/normalize')
  , compact    = require('es5-ext/lib/Array/prototype/compact')
  , contains   = require('es5-ext/lib/Array/prototype/contains')
  , copy       = require('es5-ext/lib/Array/prototype/copy')
  , group      = require('es5-ext/lib/Array/prototype/group')
  , memoize    = require('es5-ext/lib/Function/memoize')
  , isCallable = require('es5-ext/lib/Object/is-callable')
  , minimatch  = require('minimatch')

  , readdir = fs.readdir, lstat = fs.lstat, readFile = fs.readFile
  , read, read2, match, match2, prepIgnore;

read = function (path, options, ignore, files, cb) {
	if (!files.length) {
		cb(null, []);
		return;
	}
	if (options.ignorefile && contains.call(files, options.ignorefile)) {
		readFile(path + '/' + options.ignorefile, 'utf-8', function (err, result) {
			var nignore;
			if (err) {
				cb(err);
				return;
			}
			if (!ignore['/']) {
				ignore['/'] = [];
			}
			nignore = ignore['/'];
			compact.call(result.split('\n').map(trim)).forEach(function (key) {
				nignore.push(key);
			});
			read2(path, options, ignore, files, cb);
		});
	} else {
		read2(path, options, ignore, files, cb);
	}
};

prepIgnore = memoize(function (ignore) {
	var res = group.call(ignore, function (item) {
		return (item[0] === '!') ? 'exclude' : 'include';
	});
	!res.exclude && (res.exclude = []);
	!res.include && (res.include = []);
	return res;
});

match = function (ignore, file) {
	if (!ignore.length) {
		return false;
	}
	ignore = prepIgnore(ignore);
	return ignore.include.some(function (pattern) {
		return minimatch(file, pattern, { matchBase: true });
	}) && ignore.exclude.every(function (pattern) {
		return minimatch(file, pattern, { matchBase: true });
	});
};

match2 = function (ignore, file) {
	return keys(ignore).some(function (key) {
		return match(ignore[key], key + file);
	});
};

read2 = function (path, options, ignore, files, cb) {
	var waiting = files.length, result = [], nignore;
	files.forEach(function (file) {
		if (match2(ignore, file)) {
			if (!--waiting) {
				cb(null, result);
			}
			return;
		}
		lstat(path + '/' + file, function (err, stat) {
			if (err) {
				if (!--waiting) {
					cb(null, result);
				}
			} else if (stat.isFile()) {
				if (!options.pattern || options.pattern.test(file)) {
					result.push(file);
				}
				if (!--waiting) {
					cb(null, result);
				}
			} else if (stat.isDirectory()) {
				readdir(path + '/' + file, function (err, files) {
					if (err) {
						if (!--waiting) {
							cb(null, result);
						}
					} else {
						nignore = {};
						keys(ignore).forEach(function (key) {
							nignore[key + file + '/'] = ignore[key];
						});
						read(path + '/' + file, options, nignore, files, function (err, res) {
							if (err) {
								cb(err);
								waiting = -1;
								return;
							}
							result = result.concat(res.map(function (name) {
								return normalize(file + '/' + name);
							}));
							if (!--waiting) {
								cb(null, result);
							}
						});
					}
				});
			} else if (!--waiting) {
				cb(null, result);
			}
		});
	});
};

module.exports = function self (path, options, cb) {
	var ignore;
	if (isCallable(options)) {
		cb = options;
		options = {};
	}
	ignore = options.ignore ? copy.call(options.ignore) : [];
	if (options.ignorefile) {
		if (!contains.call(ignore, options.ignorefile)) {
			ignore.push(options.ignorefile);
		}
		if ((options.ignorefile === '.gitignore') &&
			(!contains.call(ignore, '.git'))) {
			ignore.push('.git');
		}
	}
	ignore = { "/": ignore };
	readdir(path = normalize(path), function (err, files) {
		if (err) {
			cb(err);
			return;
		}
		read(path, options, ignore, files, cb);
	});
};
<commit_msg>readdirFilesDeep now returns sorted result<commit_after>// Read all filenames from directory and it's subdirectories

'use strict';

var call       = Function.prototype.call
  , keys       = Object.keys
  , trim       = call.bind(String.prototype.trim)
  , fs         = require('fs')
  , normalize  = require('../path/normalize')
  , compact    = require('es5-ext/lib/Array/prototype/compact')
  , contains   = require('es5-ext/lib/Array/prototype/contains')
  , copy       = require('es5-ext/lib/Array/prototype/copy')
  , group      = require('es5-ext/lib/Array/prototype/group')
  , memoize    = require('es5-ext/lib/Function/memoize')
  , isCallable = require('es5-ext/lib/Object/is-callable')
  , minimatch  = require('minimatch')

  , readdir = fs.readdir, lstat = fs.lstat, readFile = fs.readFile
  , read, read2, match, match2, prepIgnore;

read = function (path, options, ignore, files, cb) {
	if (!files.length) {
		cb(null, []);
		return;
	}
	if (options.ignorefile && contains.call(files, options.ignorefile)) {
		readFile(path + '/' + options.ignorefile, 'utf-8', function (err, result) {
			var nignore;
			if (err) {
				cb(err);
				return;
			}
			if (!ignore['/']) {
				ignore['/'] = [];
			}
			nignore = ignore['/'];
			compact.call(result.split('\n').map(trim)).forEach(function (key) {
				nignore.push(key);
			});
			read2(path, options, ignore, files, cb);
		});
	} else {
		read2(path, options, ignore, files, cb);
	}
};

prepIgnore = memoize(function (ignore) {
	var res = group.call(ignore, function (item) {
		return (item[0] === '!') ? 'exclude' : 'include';
	});
	!res.exclude && (res.exclude = []);
	!res.include && (res.include = []);
	return res;
});

match = function (ignore, file) {
	if (!ignore.length) {
		return false;
	}
	ignore = prepIgnore(ignore);
	return ignore.include.some(function (pattern) {
		return minimatch(file, pattern, { matchBase: true });
	}) && ignore.exclude.every(function (pattern) {
		return minimatch(file, pattern, { matchBase: true });
	});
};

match2 = function (ignore, file) {
	return keys(ignore).some(function (key) {
		return match(ignore[key], key + file);
	});
};

read2 = function (path, options, ignore, files, cb) {
	var waiting = files.length, result = [], nignore;
	files.forEach(function (file) {
		if (match2(ignore, file)) {
			if (!--waiting) {
				cb(null, result);
			}
			return;
		}
		lstat(path + '/' + file, function (err, stat) {
			if (err) {
				if (!--waiting) {
					cb(null, result);
				}
			} else if (stat.isFile()) {
				if (!options.pattern || options.pattern.test(file)) {
					result.push(file);
				}
				if (!--waiting) {
					cb(null, result);
				}
			} else if (stat.isDirectory()) {
				readdir(path + '/' + file, function (err, files) {
					if (err) {
						if (!--waiting) {
							cb(null, result);
						}
					} else {
						nignore = {};
						keys(ignore).forEach(function (key) {
							nignore[key + file + '/'] = ignore[key];
						});
						read(path + '/' + file, options, nignore, files, function (err, res) {
							if (err) {
								cb(err);
								waiting = -1;
								return;
							}
							result = result.concat(res.map(function (name) {
								return normalize(file + '/' + name);
							}));
							if (!--waiting) {
								cb(null, result);
							}
						});
					}
				});
			} else if (!--waiting) {
				cb(null, result);
			}
		});
	});
};

module.exports = function self (path, options, cb) {
	var ignore;
	if (isCallable(options)) {
		cb = options;
		options = {};
	}
	ignore = options.ignore ? copy.call(options.ignore) : [];
	if (options.ignorefile) {
		if (!contains.call(ignore, options.ignorefile)) {
			ignore.push(options.ignorefile);
		}
		if ((options.ignorefile === '.gitignore') &&
			(!contains.call(ignore, '.git'))) {
			ignore.push('.git');
		}
	}
	ignore = { "/": ignore };
	readdir(path = normalize(path), function (err, files) {
		if (err) {
			cb(err);
			return;
		}
		read(path, options, ignore, files, function (err, result) {
			if (err) {
				cb(err);
				return;
			}
			cb(null, result.sort());
		});
	});
};
<|endoftext|>


<commit_before>'use strict';

var redis = require('redis');
var async = require('async');
var natural = require('natural');
var metaphone = natural.Metaphone.process;
var stem = natural.PorterStemmer.stem;
var stopwords = natural.stopwords;
var redisClient;

function noop() {}

var commands = {
  and: 'zinterstore',
  or: 'zunionstore'
};

exports.createSearch = function(namespace, client) {
  if (!namespace) {
    throw new Error('createSearch requires a namespace');
  }
  return new Search(namespace, client);
};

function Search(namespace, client) {
  this.namespace = namespace;
  redisClient = client || redis.createClient();
}

Search.prototype.index = function(data, id, callback) {
  callback = callback || noop;

  var namespace = this.namespace;
  if (!namespace) {
    return callback(new Error('index needs a namespace'));
  }

  indexData(namespace, data, id, callback);
};

Search.prototype.query = function(data, start, stop, callback) {
  if (typeof start === 'function') {
    callback = start;
    start = 0;
  }

  var namespace = this.namespace;
  start = start || 0;
  stop = stop || -1;

  var keyMap = getKeys(namespace, data);
  var cmds = [];
  var tmpKeys = [];

  for(var index in keyMap) {
    if (keyMap.hasOwnProperty(index)) {
      var keys = keyMap[index];
      if (keys.length === 1) {
        tmpKeys.push(keys[0]);
      } else if (keys.length > 1) {
        var tmpKeyName = namespace + ':' + index + ':temp';
        tmpKeys.push(tmpKeyName);
        var command = commands.and;
        if (index === 'content' && data.matchWords === 'any') {
          command = commands.or;
        }
        cmds.push([command, tmpKeyName, keys.length].concat(keys));
      }
    }
  }

  if (!tmpKeys.length) {
    return callback(null, []);
  }

  var finalKey = namespace + ':tempFinal';
  if (tmpKeys.length === 1) {
    finalKey = tmpKeys[0];
  } else {
    cmds.push([commands.and, finalKey, tmpKeys.length].concat(tmpKeys));
  }

  var resultIndex = cmds.length;
  cmds.push(['zrevrange', finalKey, start, stop]);

  tmpKeys = tmpKeys.concat([finalKey]);
  tmpKeys.forEach(function(tmpKey) {
    if (tmpKey.indexOf(':temp') !== -1) {
      cmds.push(['zremrangebyrank', tmpKey, start, stop]);
    }
  });

  redisClient.multi(cmds).exec(function(err, ids) {
    if (err) {
      return callback(err);
    }
    callback(null, ids[resultIndex]);
  });
};

function getKeys(namespace, data) {
  var keys = {};
  for (var index in data) {
    if (data.hasOwnProperty(index)) {
      keys[index] = indexToSets(namespace, index, data);
    }
  }
  return keys;
}

function indexToSets(namespace, index, data) {
  var sets = [];
  if (index === 'content') {
    if (!data.content) {
      return keys;
    }
    var words = toStem(stripStopWords(toWords(data.content)));
    var keys = metaphoneKeys(namespace, index, words);
    sets = sets.concat(keys);
  } else {
    if (Array.isArray(data[index])) {
      data[index].forEach(function(indexValue) {
        sets.push(namespace + ':' + index + ':' + indexValue + ':id');
      });
    } else {
      sets.push(namespace + ':' + index + ':' + data[index] + ':id');
    }
  }

  return sets;
}

Search.prototype.remove = function(id, callback) {
  callback = callback || noop;
  var namespace = this.namespace;

  async.waterfall([
    function(next) {
      getIndices(namespace, id, next);
    },
    function(indices, next) {
      async.each(indices, function(index, next) {
        removeIndex(namespace, id, index, next);
      }, next);
    }
  ], function(err) {
    if (err) {
      return callback(err);
    }
    redisClient.del(namespace + ':id:' + id + ':indices', callback);
  });

  return this;
};

function removeIndex(namespace, id, index, callback) {
  redisClient.smembers(namespace + ':id:' + id + ':' + index, function(err, indexValues) {
    if (err) {
      return callback(err);
    }

    var multi = redisClient.multi();
    multi.del(namespace + ':id:' + id + ':' + index);

    indexValues.forEach(function(indexValue) {
      multi.zrem(namespace + ':' + index + ':' + indexValue + ':id', id);
    });

    multi.exec(callback);
  });
}

function getIndices(namespace, id, callback) {
  redisClient.smembers(namespace + ':id:' + id + ':indices', callback);
}

function indexData(namespace, data, id, callback) {
  var cmds = [];
  for(var index in data) {
    if (data.hasOwnProperty(index)) {
      addIndexCommands(cmds, namespace, index, data[index], id);
    }
  }
  redisClient.multi(cmds).exec(callback);
}

function addIndexCommands(cmds, namespace, index, indexValue, id) {
  if (!indexValue || !index || !id) {
    return;
  }
  if (index === 'content') {
    var words = toStem(stripStopWords(toWords(indexValue)));
    var counts = countWords(words);
    var map = metaphoneMap(words);
    var keys = Object.keys(map);

    keys.forEach(function(word) {
      cmds.push(['zadd', namespace + ':' + index + ':' + map[word] + ':id', counts[word], id]);
      cmds.push(['sadd', namespace + ':id:' + id + ':' + index, map[word]]);
    });
  } else {
    cmds.push(['zadd', namespace + ':' + index + ':' + indexValue + ':id', indexValue, id]);
    cmds.push(['sadd', namespace + ':id:' + id + ':' + index, indexValue]);
  }
  cmds.push(['sadd', namespace + ':id:' + id + ':indices', index]);
}

function toWords(content) {
  return String(content).match(/\w+/g);
}

function metaphoneKeys(key, index, words) {
  return metaphoneArray(words).map(function(c) {
    return key + ':' + index + ':' + c + ':id';
  });
}

function metaphoneArray(words) {
  var arr = [];
  var constant;

  if (!words) {
    return arr;
  }

  for (var i = 0, len = words.length; i < len; ++i) {
    constant = metaphone(words[i]);
    if (!~arr.indexOf(constant)) {
      arr.push(constant);
    }
  }

  return arr;
}

function metaphoneMap(words) {
  var obj = {};
  if (!words) {
    return obj;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    obj[words[i]] = metaphone(words[i]);
  }
  return obj;
}

function toStem(words) {
  var ret = [];
  if (!words) {
    return ret;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    ret.push(stem(words[i]));
  }
  return ret;
}

function stripStopWords(words){
  var ret = [];
  if (!words) {
    return ret;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    if (stopwords.indexOf(words[i]) !== -1) {
      continue;
    }
    ret.push(words[i]);
  }
  return ret;
}

function countWords(words) {
  var obj = {};
  if (!words) {
    return obj;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    obj[words[i]] = (obj[words[i]] || 0) + 1;
  }
  return obj;
}

<commit_msg>use data.query<commit_after>'use strict';

var redis = require('redis');
var async = require('async');
var natural = require('natural');
var metaphone = natural.Metaphone.process;
var stem = natural.PorterStemmer.stem;
var stopwords = natural.stopwords;
var redisClient;

function noop() {}

var commands = {
  and: 'zinterstore',
  or: 'zunionstore'
};

exports.createSearch = function(namespace, client) {
  if (!namespace) {
    throw new Error('createSearch requires a namespace');
  }
  return new Search(namespace, client);
};

function Search(namespace, client) {
  this.namespace = namespace;
  redisClient = client || redis.createClient();
}

Search.prototype.index = function(data, id, callback) {
  callback = callback || noop;

  var namespace = this.namespace;
  if (!namespace) {
    return callback(new Error('index needs a namespace'));
  }

  indexData(namespace, data, id, callback);
};

Search.prototype.query = function(data, start, stop, callback) {
  if (typeof start === 'function') {
    callback = start;
    start = 0;
  }

  var namespace = this.namespace;
  start = start || 0;
  stop = stop || -1;

  var keyMap = getKeys(namespace, data.query);
  var cmds = [];
  var tmpKeys = [];

  for(var index in keyMap) {
    if (keyMap.hasOwnProperty(index)) {
      var keys = keyMap[index];
      if (keys.length === 1) {
        tmpKeys.push(keys[0]);
      } else if (keys.length > 1) {
        var tmpKeyName = namespace + ':' + index + ':temp';
        tmpKeys.push(tmpKeyName);
        var command = commands.and;
        if (index === 'content' && data.matchWords === 'any') {
          command = commands.or;
        }
        cmds.push([command, tmpKeyName, keys.length].concat(keys));
      }
    }
  }

  if (!tmpKeys.length) {
    return callback(null, []);
  }

  var finalKey = namespace + ':tempFinal';
  if (tmpKeys.length === 1) {
    finalKey = tmpKeys[0];
  } else {
    cmds.push([commands.and, finalKey, tmpKeys.length].concat(tmpKeys));
  }

  var resultIndex = cmds.length;
  cmds.push(['zrevrange', finalKey, start, stop]);

  tmpKeys = tmpKeys.concat([finalKey]);
  tmpKeys.forEach(function(tmpKey) {
    if (tmpKey.indexOf(':temp') !== -1) {
      cmds.push(['zremrangebyrank', tmpKey, start, stop]);
    }
  });

  redisClient.multi(cmds).exec(function(err, ids) {
    if (err) {
      return callback(err);
    }
    callback(null, ids[resultIndex]);
  });
};

function getKeys(namespace, data) {
  var keys = {};
  for (var index in data) {
    if (data.hasOwnProperty(index)) {
      keys[index] = indexToSets(namespace, index, data);
    }
  }
  return keys;
}

function indexToSets(namespace, index, data) {
  var sets = [];
  if (index === 'content') {
    if (!data.content) {
      return keys;
    }
    var words = toStem(stripStopWords(toWords(data.content)));
    var keys = metaphoneKeys(namespace, index, words);
    sets = sets.concat(keys);
  } else {
    if (Array.isArray(data[index])) {
      data[index].forEach(function(indexValue) {
        sets.push(namespace + ':' + index + ':' + indexValue + ':id');
      });
    } else {
      sets.push(namespace + ':' + index + ':' + data[index] + ':id');
    }
  }

  return sets;
}

Search.prototype.remove = function(id, callback) {
  callback = callback || noop;
  var namespace = this.namespace;

  async.waterfall([
    function(next) {
      getIndices(namespace, id, next);
    },
    function(indices, next) {
      async.each(indices, function(index, next) {
        removeIndex(namespace, id, index, next);
      }, next);
    }
  ], function(err) {
    if (err) {
      return callback(err);
    }
    redisClient.del(namespace + ':id:' + id + ':indices', callback);
  });

  return this;
};

function removeIndex(namespace, id, index, callback) {
  redisClient.smembers(namespace + ':id:' + id + ':' + index, function(err, indexValues) {
    if (err) {
      return callback(err);
    }

    var multi = redisClient.multi();
    multi.del(namespace + ':id:' + id + ':' + index);

    indexValues.forEach(function(indexValue) {
      multi.zrem(namespace + ':' + index + ':' + indexValue + ':id', id);
    });

    multi.exec(callback);
  });
}

function getIndices(namespace, id, callback) {
  redisClient.smembers(namespace + ':id:' + id + ':indices', callback);
}

function indexData(namespace, data, id, callback) {
  var cmds = [];
  for(var index in data) {
    if (data.hasOwnProperty(index)) {
      addIndexCommands(cmds, namespace, index, data[index], id);
    }
  }
  redisClient.multi(cmds).exec(callback);
}

function addIndexCommands(cmds, namespace, index, indexValue, id) {
  if (!indexValue || !index || !id) {
    return;
  }
  if (index === 'content') {
    var words = toStem(stripStopWords(toWords(indexValue)));
    var counts = countWords(words);
    var map = metaphoneMap(words);
    var keys = Object.keys(map);

    keys.forEach(function(word) {
      cmds.push(['zadd', namespace + ':' + index + ':' + map[word] + ':id', counts[word], id]);
      cmds.push(['sadd', namespace + ':id:' + id + ':' + index, map[word]]);
    });
  } else {
    cmds.push(['zadd', namespace + ':' + index + ':' + indexValue + ':id', indexValue, id]);
    cmds.push(['sadd', namespace + ':id:' + id + ':' + index, indexValue]);
  }
  cmds.push(['sadd', namespace + ':id:' + id + ':indices', index]);
}

function toWords(content) {
  return String(content).match(/\w+/g);
}

function metaphoneKeys(key, index, words) {
  return metaphoneArray(words).map(function(c) {
    return key + ':' + index + ':' + c + ':id';
  });
}

function metaphoneArray(words) {
  var arr = [];
  var constant;

  if (!words) {
    return arr;
  }

  for (var i = 0, len = words.length; i < len; ++i) {
    constant = metaphone(words[i]);
    if (!~arr.indexOf(constant)) {
      arr.push(constant);
    }
  }

  return arr;
}

function metaphoneMap(words) {
  var obj = {};
  if (!words) {
    return obj;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    obj[words[i]] = metaphone(words[i]);
  }
  return obj;
}

function toStem(words) {
  var ret = [];
  if (!words) {
    return ret;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    ret.push(stem(words[i]));
  }
  return ret;
}

function stripStopWords(words){
  var ret = [];
  if (!words) {
    return ret;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    if (stopwords.indexOf(words[i]) !== -1) {
      continue;
    }
    ret.push(words[i]);
  }
  return ret;
}

function countWords(words) {
  var obj = {};
  if (!words) {
    return obj;
  }
  for (var i = 0, len = words.length; i < len; ++i) {
    obj[words[i]] = (obj[words[i]] || 0) + 1;
  }
  return obj;
}

<|endoftext|>


<commit_before>'use strict';

var path = require('path')
  , DRIVE_REGEX = /^\w:\\/
  , resolvePath
  , isAbsolute
  ;

// resolvePath
// ===========
//
// resolvePath is a function that determines the absolute path to a file given a
// filepath. If the filepath begins with a `/`, then it is assumes that an
// absolute path was given. Otherwise, it assumes a relative path was given, and
// it will be based on `process.cwd()`.
//
// ### Parameters
//
// - `filepath` (String) - The path to the file. It can be absolute or relative
//
// ### Returns
//
// - `filepath` (String) - the filepath given, but in absolute form. If the
// given path was relative, then it will assume that it's relative based on
// `process.cwd()`.
resolvePath = function (filepath) {
  if (isAbsolute(filepath)) {
    return filepath;
  } else {
    return path.join(process.cwd(), filepath);
  }
};

isAbsolute = function (filepath) {
  var abs;
  // This is kind of a hacky way of doing things. This brings up the issue of
  // whether or not we should be using relative paths throughout or not.
  switch (process.platform) {
    case 'win32':
      abs = !!filepath.match(DRIVE_REGEX);
      break;
    default:
      abs = filepath.charAt(0) === path.sep;
  }
  return abs;
};

module.exports = resolvePath;
<commit_msg>ignoring windows specific test case<commit_after>'use strict';

var path = require('path')
  , DRIVE_REGEX = /^\w:\\/
  , resolvePath
  , isAbsolute
  ;

// resolvePath
// ===========
//
// resolvePath is a function that determines the absolute path to a file given a
// filepath. If the filepath begins with a `/`, then it is assumes that an
// absolute path was given. Otherwise, it assumes a relative path was given, and
// it will be based on `process.cwd()`.
//
// ### Parameters
//
// - `filepath` (String) - The path to the file. It can be absolute or relative
//
// ### Returns
//
// - `filepath` (String) - the filepath given, but in absolute form. If the
// given path was relative, then it will assume that it's relative based on
// `process.cwd()`.
resolvePath = function (filepath) {
  if (isAbsolute(filepath)) {
    return filepath;
  } else {
    return path.join(process.cwd(), filepath);
  }
};

isAbsolute = function (filepath) {
  var abs;
  // This is kind of a hacky way of doing things. This brings up the issue of
  // whether or not we should be using relative paths throughout or not.
  /* istanbul ignore next */
  switch (process.platform) {
    case 'win32':
      abs = !!filepath.match(DRIVE_REGEX);
      break;
    default:
      abs = filepath.charAt(0) === path.sep;
  }
  return abs;
};

module.exports = resolvePath;
<|endoftext|>


<commit_before>var URL = require('url');

module.exports = function(config) {

    function getRealUrlPrefixed(domain, path) {
        var port = '';
        var re_port = /\.port-([0-9]{1,5})-port\./i;
        if (re_port.test(domain)) {
            port = ':' + domain.match(re_port)[1];
            domain = domain.replace(re_port, '.');
        }
        if (domain.indexOf('h-t-t-p-s') === 0) {
            return 'https://' + domain.substring(10, domain.lastIndexOf(config.domain) - 1) + port + path;
        } else {
            return 'http://'  + domain.substring(8,  domain.lastIndexOf(config.domain) - 1) + port + path;
        }
    }

    return getRealUrlPrefixed;
};
<commit_msg>Handle missing h-t-t-p(-s)<commit_after>var URL = require('url');

module.exports = function(config) {

    function getRealUrlPrefixed(domain, path) {
        var port = '';
        var re_port = /\.port-([0-9]{1,5})-port\./i;
        if (re_port.test(domain)) {
            port = ':' + domain.match(re_port)[1];
            domain = domain.replace(re_port, '.');
        }
        if (domain.indexOf('h-t-t-p') === 0) {
            if (domain.indexOf('h-t-t-p-s') === 0) {
                return 'https://' + domain.substring(10, domain.lastIndexOf(config.domain) - 1) + port + path;
            } else {
                return 'http://'  + domain.substring(8,  domain.lastIndexOf(config.domain) - 1) + port + path;
            }
        } else {
            // Handle missing h-t-t-p(-s)
            return 'http://'  + domain.substring(0,  domain.lastIndexOf(config.domain) - 1) + port + path;
        }
    }

    return getRealUrlPrefixed;
};
<|endoftext|>


<commit_before>module.exports = makeRichMessage
module.exports.mergeMessages = mergeMessages

var emojiNamedCharacters = require('emoji-named-characters')
var ghlink = require('ghlink')
var htmlToVDom = require('html-to-vdom')
var MarkdownIt = require('markdown-it')
var VNode = require('virtual-dom/vnode/vnode')
var VText = require('virtual-dom/vnode/vtext')
var util = require('./util.js')

var EMOJI_REGEX = /(\s|>|^)?:([A-z0-9_+]+):(\s|<|$)/g

var md = new MarkdownIt({
  linkify: true
})
var convertHTML = htmlToVDom({
  VNode: VNode,
  VText: VText
})

function makeVDom (html) {
  return convertHTML('
' + html + '
')
}

function makeRichMessage (message) {
  message.anon = /Anonymous/i.test(message.username)
  message.avatar = message.anon
    ? 'static/cat.png'
    : 'https://github.com/' + message.username + '.png'
  message.timeago = util.timeago(message.timestamp)

  message.html = md.render(message.text)
  message.html = emojify(message.html)
  message.html = ghlink(message.html, { format: 'html' })
  message.html = message.html.replace(/(^| )(#[a-zA-Z0-9]+)( |$)$/g, '$1$2$3')
  message.vdom = makeVDom(message.html)

  return message
}

function emojify (str) {
  return str.replace(EMOJI_REGEX, function (full, $1, $2, $3) {
    return ($1 || '') + renderEmoji($2) + ($3 || '')
  })
}

function renderEmoji (emoji) {
  return emoji in emojiNamedCharacters ?
      ''
    : ':' + emoji + ':'
}

function mergeMessages (message1, message2) {
  message1.text += '\n' + message2.text
  message1.html += '

' + message2.html
  message1.vdom = makeVDom(message1.html)
  return message1
}
<commit_msg>highlight mentions on incoming messages<commit_after>module.exports = makeRichMessage
module.exports.mergeMessages = mergeMessages

var emojiNamedCharacters = require('emoji-named-characters')
var ghlink = require('ghlink')
var htmlToVDom = require('html-to-vdom')
var MarkdownIt = require('markdown-it')
var VNode = require('virtual-dom/vnode/vnode')
var VText = require('virtual-dom/vnode/vtext')
var util = require('./util.js')

var EMOJI_REGEX = /(\s|>|^)?:([A-z0-9_+]+):(\s|<|$)/g

var md = new MarkdownIt({
  linkify: true
})
var convertHTML = htmlToVDom({
  VNode: VNode,
  VText: VText
})

function makeVDom (html) {
  return convertHTML('
' + html + '
')
}

function makeRichMessage (message, username) {
  message.anon = /Anonymous/i.test(message.username)
  message.avatar = message.anon
    ? 'static/cat.png'
    : 'https://github.com/' + message.username + '.png'
  message.timeago = util.timeago(message.timestamp)

  message.html = md.render(message.text)
  message.html = emojify(message.html)
  message.html = ghlink(message.html, { format: 'html' })
  message.html = message.html.replace(/(^| )(#[a-zA-Z0-9]+)( |$)$/g, '$1$2$3')

  var highlight = (message.text.indexOf(username) !== -1)
  var classStr = highlight ? ' class="highlight"' : ''
  message.html = '
' + message.html + '
'

  message.vdom = makeVDom(message.html)

  return message
}

function emojify (str) {
  return str.replace(EMOJI_REGEX, function (full, $1, $2, $3) {
    return ($1 || '') + renderEmoji($2) + ($3 || '')
  })
}

function renderEmoji (emoji) {
  return emoji in emojiNamedCharacters ?
      ''
    : ':' + emoji + ':'
}

function mergeMessages (message1, message2) {
  message1.text += '\n' + message2.text
  message1.html += '

' + message2.html
  message1.vdom = makeVDom(message1.html)
  return message1
}
<|endoftext|>


<commit_before>
/*!
 * Express - Router
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Route = require('./route')
  , Collection = require('./collection')
  , utils = require('../utils')
  , parse = require('url').parse
  , toArray = utils.toArray;

/**
 * Expose `Router` constructor.
 */

exports = module.exports = Router;

/**
 * Expose HTTP methods.
 */

var methods = exports.methods = require('./methods');

/**
 * Initialize a new `Router` with the given `app`.
 *
 * @param {express.HTTPServer} app
 * @api private
 */

function Router(app) {
  var self = this;
  this.app = app;
  this.routes = {};
  this.params = {};
  this._params = [];

  this.middleware = function(req, res, next){
    self._dispatch(req, res, next);
  };
}

/**
 * Register a param callback `fn` for the given `name`.
 *
 * @param {String|Function} name
 * @param {Function} fn
 * @return {Router} for chaining
 * @api public
 */

Router.prototype.param = function(name, fn){
  // param logic
  if ('function' == typeof name) {
    this._params.push(name);
    return;
  }

  // apply param functions
  var params = this._params
    , len = params.length
    , ret;

  for (var i = 0; i < len; ++i) {
    if (ret = params[i](name, fn)) {
      fn = ret;
    }
  }

  // ensure we end up with a
  // middleware function
  if ('function' != typeof fn) {
    throw new Error('invalid param() call for ' + name + ', got ' + fn);
  }

  (this.params[name] = this.params[name] || []).push(fn);
  return this;
};

/**
 * Return a `Collection` of all routes defined.
 *
 * @return {Collection}
 * @api public
 */

Router.prototype.all = function(){
  return this.find(function(){
    return true;
  });
};

/**
 * Remove the given `route`, returns
 * a bool indicating if the route was present
 * or not.
 *
 * @param {Route} route
 * @return {Boolean}
 * @api public
 */

Router.prototype.remove = function(route){
  var routes = this.routes[route.method]
    , len = routes.length;

  for (var i = 0; i < len; ++i) {
    if (route == routes[i]) {
      routes.splice(i, 1);
      return true;
    }
  }
};

/**
 * Return routes with route paths matching `path`.
 *
 * @param {String} method
 * @param {String} path
 * @return {Collection}
 * @api public
 */

Router.prototype.lookup = function(method, path){
  return this.find(function(route){
    return path == route.path
      && (route.method == method
      || method == 'all');
  });
};

/**
 * Return routes with regexps that match the given `url`.
 *
 * @param {String} method
 * @param {String} url
 * @return {Collection}
 * @api public
 */

Router.prototype.match = function(method, url){
  return this.find(function(route){
    return route.match(url)
      && (route.method == method
      || method == 'all');
  });
};

/**
 * Find routes based on the return value of `fn`
 * which is invoked once per route.
 *
 * @param {Function} fn
 * @return {Collection}
 * @api public
 */

Router.prototype.find = function(fn){
  var len = methods.length
    , ret = new Collection(this)
    , method
    , routes
    , route;

  for (var i = 0; i < len; ++i) {
    method = methods[i];
    routes = this.routes[method];
    if (!routes) continue;
    for (var j = 0, jlen = routes.length; j < jlen; ++j) {
      route = routes[j];
      if (fn(route)) ret.push(route);
    }
  }

  return ret;
};

/**
 * Route dispatcher aka the route "middleware".
 *
 * @param {IncomingMessage} req
 * @param {ServerResponse} res
 * @param {Function} next
 * @api private
 */

Router.prototype._dispatch = function(req, res, next){
  var params = this.params
    , self = this;

  // route dispatch
  (function pass(i){
    var paramCallbacks
      , paramIndex = 0
      , paramVal
      , route
      , keys
      , key
      , ret;

    // match next route
    function nextRoute() {
      pass(req._route_index + 1);
    }

    // match route
    req.route = route = self._match(req, i);

    // implied OPTIONS
    if (!route && 'OPTIONS' == req.method) return self._options(req, res);

    // no route
    if (!route) return next();

    // we have a route
    // start at param 0
    req.params = route.params;
    keys = route.keys;
    i = 0;

    // param callbacks
    function param(err) {
      key = keys[i++];
      paramVal = key && req.params[key.name];
      paramCallbacks = key && params[key.name];

      try {
        if ('route' == err) {
          nextRoute();
        } else if (err) {
          next(err);
        } else if (paramCallbacks && undefined !== paramVal) {
          paramCallback();
        } else if (key) {
          param();
        } else {
          i = 0;
          middleware();
        }
      } catch (err) {
        next(err);
      }
    };

    param();

    // single param callbacks
    function paramCallback(err) {
      var fn = paramCallbacks[paramIndex++];
      if (err || !fn) return param(err);
      fn(req, res, paramCallback, paramVal, key.name);
    }

    // invoke route middleware
    function middleware(err) {
      var fn = route.middleware[i++];
      if ('route' == err) {
        nextRoute();
      } else if (err) {
        next(err);
      } else if (fn) {
        fn(req, res, middleware);
      } else {
        done();
      }
    };

    // invoke middleware callback
    function done() {
      route.callback.call(self, req, res, function(err){
        if (err) return next(err);
        pass(req._route_index + 1);
      });
    }
  })(0);
};

/**
 * Respond to __OPTIONS__ method.
 *
 * @param {IncomingMessage} req
 * @param {ServerResponse} res
 * @api private
 */

Router.prototype._options = function(req, res){
  var path = parse(req.url).pathname
    , body = this._optionsFor(path).join(',');
  res.header('Allow', body).send(body);
};

/**
 * Return an array of HTTP verbs or "options" for `path`.
 *
 * @param {String} path
 * @return {Array}
 * @api private
 */

Router.prototype._optionsFor = function(path){
  var self = this;
  return methods.filter(function(method){
    var routes = self.routes[method];
    if (!routes || 'options' == method) return;
    for (var i = 0, len = routes.length; i < len; ++i) {
      if (routes[i].match(path)) return true;
    }
  }).map(function(method){
    return method.toUpperCase();
  });
};

/**
 * Attempt to match a route for `req`
 * starting from offset `i`.
 *
 * @param {IncomingMessage} req
 * @param {Number} i
 * @return {Route}
 * @api private
 */

Router.prototype._match = function(req, i){
  var method = req.method.toLowerCase()
    , url = parse(req.url)
    , path = url.pathname
    , routes = this.routes
    , captures
    , route
    , keys;

  // pass HEAD to GET routes
  if ('head' == method) method = 'get';

  // routes for this method
  if (routes = routes[method]) {

    // matching routes
    for (var len = routes.length; i < len; ++i) {
      route = routes[i];
      if (captures = route.match(path)) {
        keys = route.keys;
        route.params = [];

        // params from capture groups
        for (var j = 1, jlen = captures.length; j < jlen; ++j) {
          var key = keys[j-1]
            , val = 'string' == typeof captures[j]
              ? decodeURIComponent(captures[j])
              : captures[j];
          if (key) {
            route.params[key.name] = val;
          } else {
            route.params.push(val);
          }
        }

        // all done
        req._route_index = i;
        return route;
      }
    }
  }
};

/**
 * Route `method`, `path`, and optional middleware
 * to the callback `fn`.
 *
 * @param {String} method
 * @param {String} path
 * @param {Function} ...
 * @param {Function} fn
 * @return {Router} for chaining
 * @api private
 */

Router.prototype._route = function(method, path, fn){
  var app = this.app
    , middleware = [];

  // slice middleware
  if (arguments.length > 3) {
    middleware = toArray(arguments, 2);
    fn = middleware.pop();
    middleware = utils.flatten(middleware);
  }

  // ensure path and callback are given
  if (!path) throw new Error(method + 'route requires a path');
  if (!fn) throw new Error(method + ' route ' + path + ' requires a callback');

  // create the route
  var route = new Route(method, path, fn, {
      sensitive: app.enabled('case sensitive routes')
    , strict: app.enabled('strict routing')
    , middleware: middleware
  });

  // add it
  (this.routes[method] = this.routes[method] || [])
    .push(route);
  return this;
};
<commit_msg>Changed: removed .call(self) for route callbacks<commit_after>
/*!
 * Express - Router
 * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Route = require('./route')
  , Collection = require('./collection')
  , utils = require('../utils')
  , parse = require('url').parse
  , toArray = utils.toArray;

/**
 * Expose `Router` constructor.
 */

exports = module.exports = Router;

/**
 * Expose HTTP methods.
 */

var methods = exports.methods = require('./methods');

/**
 * Initialize a new `Router` with the given `app`.
 *
 * @param {express.HTTPServer} app
 * @api private
 */

function Router(app) {
  var self = this;
  this.app = app;
  this.routes = {};
  this.params = {};
  this._params = [];

  this.middleware = function(req, res, next){
    self._dispatch(req, res, next);
  };
}

/**
 * Register a param callback `fn` for the given `name`.
 *
 * @param {String|Function} name
 * @param {Function} fn
 * @return {Router} for chaining
 * @api public
 */

Router.prototype.param = function(name, fn){
  // param logic
  if ('function' == typeof name) {
    this._params.push(name);
    return;
  }

  // apply param functions
  var params = this._params
    , len = params.length
    , ret;

  for (var i = 0; i < len; ++i) {
    if (ret = params[i](name, fn)) {
      fn = ret;
    }
  }

  // ensure we end up with a
  // middleware function
  if ('function' != typeof fn) {
    throw new Error('invalid param() call for ' + name + ', got ' + fn);
  }

  (this.params[name] = this.params[name] || []).push(fn);
  return this;
};

/**
 * Return a `Collection` of all routes defined.
 *
 * @return {Collection}
 * @api public
 */

Router.prototype.all = function(){
  return this.find(function(){
    return true;
  });
};

/**
 * Remove the given `route`, returns
 * a bool indicating if the route was present
 * or not.
 *
 * @param {Route} route
 * @return {Boolean}
 * @api public
 */

Router.prototype.remove = function(route){
  var routes = this.routes[route.method]
    , len = routes.length;

  for (var i = 0; i < len; ++i) {
    if (route == routes[i]) {
      routes.splice(i, 1);
      return true;
    }
  }
};

/**
 * Return routes with route paths matching `path`.
 *
 * @param {String} method
 * @param {String} path
 * @return {Collection}
 * @api public
 */

Router.prototype.lookup = function(method, path){
  return this.find(function(route){
    return path == route.path
      && (route.method == method
      || method == 'all');
  });
};

/**
 * Return routes with regexps that match the given `url`.
 *
 * @param {String} method
 * @param {String} url
 * @return {Collection}
 * @api public
 */

Router.prototype.match = function(method, url){
  return this.find(function(route){
    return route.match(url)
      && (route.method == method
      || method == 'all');
  });
};

/**
 * Find routes based on the return value of `fn`
 * which is invoked once per route.
 *
 * @param {Function} fn
 * @return {Collection}
 * @api public
 */

Router.prototype.find = function(fn){
  var len = methods.length
    , ret = new Collection(this)
    , method
    , routes
    , route;

  for (var i = 0; i < len; ++i) {
    method = methods[i];
    routes = this.routes[method];
    if (!routes) continue;
    for (var j = 0, jlen = routes.length; j < jlen; ++j) {
      route = routes[j];
      if (fn(route)) ret.push(route);
    }
  }

  return ret;
};

/**
 * Route dispatcher aka the route "middleware".
 *
 * @param {IncomingMessage} req
 * @param {ServerResponse} res
 * @param {Function} next
 * @api private
 */

Router.prototype._dispatch = function(req, res, next){
  var params = this.params
    , self = this;

  // route dispatch
  (function pass(i){
    var paramCallbacks
      , paramIndex = 0
      , paramVal
      , route
      , keys
      , key
      , ret;

    // match next route
    function nextRoute() {
      pass(req._route_index + 1);
    }

    // match route
    req.route = route = self._match(req, i);

    // implied OPTIONS
    if (!route && 'OPTIONS' == req.method) return self._options(req, res);

    // no route
    if (!route) return next();

    // we have a route
    // start at param 0
    req.params = route.params;
    keys = route.keys;
    i = 0;

    // param callbacks
    function param(err) {
      key = keys[i++];
      paramVal = key && req.params[key.name];
      paramCallbacks = key && params[key.name];

      try {
        if ('route' == err) {
          nextRoute();
        } else if (err) {
          next(err);
        } else if (paramCallbacks && undefined !== paramVal) {
          paramCallback();
        } else if (key) {
          param();
        } else {
          i = 0;
          middleware();
        }
      } catch (err) {
        next(err);
      }
    };

    param();

    // single param callbacks
    function paramCallback(err) {
      var fn = paramCallbacks[paramIndex++];
      if (err || !fn) return param(err);
      fn(req, res, paramCallback, paramVal, key.name);
    }

    // invoke route middleware
    function middleware(err) {
      var fn = route.middleware[i++];
      if ('route' == err) {
        nextRoute();
      } else if (err) {
        next(err);
      } else if (fn) {
        fn(req, res, middleware);
      } else {
        done();
      }
    };

    // invoke middleware callback
    function done() {
      route.callback(req, res, function(err){
        if (err) return next(err);
        pass(req._route_index + 1);
      });
    }
  })(0);
};

/**
 * Respond to __OPTIONS__ method.
 *
 * @param {IncomingMessage} req
 * @param {ServerResponse} res
 * @api private
 */

Router.prototype._options = function(req, res){
  var path = parse(req.url).pathname
    , body = this._optionsFor(path).join(',');
  res.header('Allow', body).send(body);
};

/**
 * Return an array of HTTP verbs or "options" for `path`.
 *
 * @param {String} path
 * @return {Array}
 * @api private
 */

Router.prototype._optionsFor = function(path){
  var self = this;
  return methods.filter(function(method){
    var routes = self.routes[method];
    if (!routes || 'options' == method) return;
    for (var i = 0, len = routes.length; i < len; ++i) {
      if (routes[i].match(path)) return true;
    }
  }).map(function(method){
    return method.toUpperCase();
  });
};

/**
 * Attempt to match a route for `req`
 * starting from offset `i`.
 *
 * @param {IncomingMessage} req
 * @param {Number} i
 * @return {Route}
 * @api private
 */

Router.prototype._match = function(req, i){
  var method = req.method.toLowerCase()
    , url = parse(req.url)
    , path = url.pathname
    , routes = this.routes
    , captures
    , route
    , keys;

  // pass HEAD to GET routes
  if ('head' == method) method = 'get';

  // routes for this method
  if (routes = routes[method]) {

    // matching routes
    for (var len = routes.length; i < len; ++i) {
      route = routes[i];
      if (captures = route.match(path)) {
        keys = route.keys;
        route.params = [];

        // params from capture groups
        for (var j = 1, jlen = captures.length; j < jlen; ++j) {
          var key = keys[j-1]
            , val = 'string' == typeof captures[j]
              ? decodeURIComponent(captures[j])
              : captures[j];
          if (key) {
            route.params[key.name] = val;
          } else {
            route.params.push(val);
          }
        }

        // all done
        req._route_index = i;
        return route;
      }
    }
  }
};

/**
 * Route `method`, `path`, and optional middleware
 * to the callback `fn`.
 *
 * @param {String} method
 * @param {String} path
 * @param {Function} ...
 * @param {Function} fn
 * @return {Router} for chaining
 * @api private
 */

Router.prototype._route = function(method, path, fn){
  var app = this.app
    , middleware = [];

  // slice middleware
  if (arguments.length > 3) {
    middleware = toArray(arguments, 2);
    fn = middleware.pop();
    middleware = utils.flatten(middleware);
  }

  // ensure path and callback are given
  if (!path) throw new Error(method + 'route requires a path');
  if (!fn) throw new Error(method + ' route ' + path + ' requires a callback');

  // create the route
  var route = new Route(method, path, fn, {
      sensitive: app.enabled('case sensitive routes')
    , strict: app.enabled('strict routing')
    , middleware: middleware
  });

  // add it
  (this.routes[method] = this.routes[method] || [])
    .push(route);
  return this;
};
<|endoftext|>