<commit_before>const {
  Branch,
  Commit,
  Merge,
  Repository,
  Signature,
  Tree,
  setThreadSafetyStatus,
  TreeEntry: { FILEMODE }
} = require('nodegit');
const {
  MutableTree,
  NotFound,
  OverwriteRejected
} = require('./mutable-tree');
const moment = require('moment-timezone');
const crypto = require('crypto');
const delay = require('delay');
const log = require('@cardstack/logger')('cardstack/git');

// This is supposed to enable thread-safe locking around all async
// operations.
setThreadSafetyStatus(1);

class Change {
  static async createInitial(repoPath, targetBranch) {
    let repo = await Repository.init(repoPath, 1);
    return new this(repo, targetBranch, null, [], null, null, null);
  }

  static async createBranch(repo, parentId, targetBranch) {
    let parentCommit;
    if (parentId) {
      parentCommit = await Commit.lookup(repo, parentId);
    }

    let parentTree;
    let parents = [];
    if (parentCommit) {
      parentTree = await parentCommit.getTree();
      parents.push(parentCommit);
    }
    return new this(repo, targetBranch, parentTree, parents, parentCommit, null, null);
  }

  static async create(repo, parentId, targetBranch, fetchOpts) {
    let parentCommit;
    if (parentId) {
      parentCommit = await Commit.lookup(repo, parentId);
    } else {
      parentCommit = await headCommit(repo, targetBranch, fetchOpts);
    }

    let parentTree;
    let parents = [];
    if (parentCommit) {
      parentTree = await parentCommit.getTree();
      parents.push(parentCommit);
    }
    return new this(repo, targetBranch, parentTree, parents, parentCommit, fetchOpts);
  }

  constructor(repo, targetBranch, parentTree, parents, parentCommit, fetchOpts) {
    this.repo = repo;
    this.parentTree = parentTree;
    this.root = new MutableTree(repo, parentTree);
    this.parents = parents;
    this.parentCommit = parentCommit;
    this.targetBranch = targetBranch;
    this.fetchOpts = fetchOpts;
  }

  async _headCommit() {
    return headCommit(this.repo, this.targetBranch, this.fetchOpts);
  }

  async get(path, { allowCreate, allowUpdate } = {}) {
    let { tree, leaf, leafName } = await this.root.fileAtPath(path, allowCreate);
    return new FileHandle(tree, leaf, leafName, allowUpdate, path);
  }

  async finalize(commitOpts) {
    let newCommit = await this._makeCommit(commitOpts);
    let commitId;

    if(this.fetchOpts) {
      commitId = await this._pushCommit(newCommit, commitOpts);
    } else {
      let mergeCommit = await this._makeMergeCommit(newCommit, commitOpts);
      await this._applyCommit(mergeCommit);
      commitId = mergeCommit.id().tostrS();
    }

    return commitId;
  }

  async _makeCommit(commitOpts) {
    let treeOid = await this.root.write(true);

    if (treeOid && this.parentTree && treeOid.equal(this.parentTree.id())) {
      return this.parentCommit;
    }

    let tree = await Tree.lookup(this.repo, treeOid, null);
    let { author, committer } = signature(commitOpts);
    let commitOid = await Commit.create(this.repo, null, author, committer, 'UTF-8', commitOpts.message, tree, this.parents.length, this.parents);
    return Commit.lookup(this.repo, commitOid);
  }

  async _pushCommit(newCommit, commitOpts) {
    let delayTime = 500;
    while (delayTime <= 5000) {
      let mergeCommit = await this._makeMergeCommit(newCommit, commitOpts);
      const remoteBranchName = `temp-remote-${crypto.randomBytes(20).toString('hex')}`;
      await Branch.create(this.repo, remoteBranchName, mergeCommit, false);

      let remote = await this.repo.getRemote('origin');

      try {
        await remote.push([`refs/heads/${remoteBranchName}:refs/heads/${this.targetBranch}`], this.fetchOpts);
        return newCommit.id().tostrS();
      } catch (err) {
        // pull remote and retry with longer delay
        await delay(delayTime);
        await this.repo.fetchAll(this.fetchOpts);

        log.warn('Push to remote failed "%s"', err);

        delayTime *= 2;
      }
    }
    throw new Error('Push failed');
  }

  async _makeMergeCommit(newCommit, commitOpts) {
    let headCommit = await this._headCommit();

    if (!headCommit) {
      // new branch, so no merge needed
      return newCommit;
    }
    let baseOid = await Merge.base(this.repo, newCommit, headCommit);
    if (baseOid.equal(headCommit.id())) {
      // fast forward (we think), so no merge needed
      return newCommit;
    }
    let index = await Merge.commits(this.repo, newCommit, headCommit, null);
    if (index.hasConflicts()) {
      throw new GitConflict(index);
    }
    let treeOid = await index.writeTreeTo(this.repo);
    let tree = await Tree.lookup(this.repo, treeOid, null);
    let { author, committer } = signature(commitOpts);
    let mergeCommitOid = await Commit.create(this.repo, null, author, committer, 'UTF-8', `Clean merge into ${this.targetBranch}`, tree, 2, [newCommit, headCommit]);
    return await Commit.lookup(this.repo, mergeCommitOid);
  }

  async _applyCommit(commit) {
    let headCommit = await this._headCommit();

    if (!headCommit) {
      return await this._newBranch(commit);
    }

    let headRef = await Branch.lookup(this.repo, this.targetBranch, Branch.BRANCH.LOCAL);
    await headRef.setTarget(commit.id(), 'fast forward');
  }

  async _newBranch(newCommit) {
    await Branch.create(this.repo, this.targetBranch, newCommit, false);
  }
}

function signature(commitOpts) {
  let date = commitOpts.authorDate || moment();
  let author = Signature.create(commitOpts.authorName, commitOpts.authorEmail, date.unix(), date.utcOffset());
  let committer = commitOpts.committerName ? Signature.create(commitOpts.committerName, commitOpts.committerEmail, date.unix(), date.utcOffset()) : author;
  return {
    author,
    committer
  };
}

class GitConflict extends Error {
  constructor(index) {
    super();
    this.index = index;
  }
}

class FileHandle {
  constructor(tree, leaf, name, allowUpdate, path) {
    this.tree = tree;
    this.leaf = leaf;
    this.name = name;
    this.allowUpdate = allowUpdate;
    this.path = path;
    if (leaf) {
      this.mode = leaf.filemode();
    } else {
      this.mode = FILEMODE.BLOB;
    }
  }
  async getBuffer() {
    if (this.leaf) {
      return (await this.leaf.getBlob()).content();
    }
  }
  exists() {
    return !!this.leaf;
  }
  setContent(buffer) {
    if (typeof buffer === 'string') {
      buffer = Buffer.from(buffer, 'utf8');
    }
    if (!(buffer instanceof Buffer)) {
      throw new Error("setContent got something that was not a Buffer or String");
    }
    if (!this.allowUpdate && this.leaf) {
      throw new OverwriteRejected(`Refusing to overwrite ${this.path}`);
    }
    this.leaf = this.tree.insert(this.name, buffer, this.mode);
  }
  delete() {
    if (!this.leaf) {
      throw new NotFound(`No such file ${this.path}`);
    }
    this.tree.delete(this.name);
    this.leaf = null;
  }
  savedId() {
    // this is available only after our change has been finalized
    if (this.leaf.savedId) {
      return this.leaf.savedId.tostrS();
    }
  }
}

Change.GitConflict = GitConflict;
Change.NotFound = NotFound;
Change.OverwriteRejected = OverwriteRejected;

module.exports = Change;

async function headCommit(repo, targetBranch, fetchOpts) {
  let headRef;
  try {
    if (fetchOpts) {
      headRef = await Branch.lookup(repo, `origin/${targetBranch}`, Branch.BRANCH.REMOTE);
    } else {
      headRef = await Branch.lookup(repo, targetBranch, Branch.BRANCH.LOCAL);
    }
  } catch(err) {
    if (err.errorFunction !== 'Branch.lookup') {
      throw err;
    }
  }
  if (headRef) {
    return await Commit.lookup(repo, headRef.target());
  }
}
<commit_msg>moving the looping behaviour to the finalize function<commit_after>const {
  Branch,
  Commit,
  Merge,
  Repository,
  Signature,
  Tree,
  setThreadSafetyStatus,
  TreeEntry: { FILEMODE }
} = require('nodegit');
const {
  MutableTree,
  NotFound,
  OverwriteRejected
} = require('./mutable-tree');
const moment = require('moment-timezone');
const crypto = require('crypto');
const delay = require('delay');
const log = require('@cardstack/logger')('cardstack/git');

// This is supposed to enable thread-safe locking around all async
// operations.
setThreadSafetyStatus(1);

class Change {
  static async createInitial(repoPath, targetBranch) {
    let repo = await Repository.init(repoPath, 1);
    return new this(repo, targetBranch, null, [], null, null, null);
  }

  static async createBranch(repo, parentId, targetBranch) {
    let parentCommit;
    if (parentId) {
      parentCommit = await Commit.lookup(repo, parentId);
    }

    let parentTree;
    let parents = [];
    if (parentCommit) {
      parentTree = await parentCommit.getTree();
      parents.push(parentCommit);
    }
    return new this(repo, targetBranch, parentTree, parents, parentCommit, null, null);
  }

  static async create(repo, parentId, targetBranch, fetchOpts) {
    let parentCommit;
    if (parentId) {
      parentCommit = await Commit.lookup(repo, parentId);
    } else {
      parentCommit = await headCommit(repo, targetBranch, fetchOpts);
    }

    let parentTree;
    let parents = [];
    if (parentCommit) {
      parentTree = await parentCommit.getTree();
      parents.push(parentCommit);
    }
    return new this(repo, targetBranch, parentTree, parents, parentCommit, fetchOpts);
  }

  constructor(repo, targetBranch, parentTree, parents, parentCommit, fetchOpts) {
    this.repo = repo;
    this.parentTree = parentTree;
    this.root = new MutableTree(repo, parentTree);
    this.parents = parents;
    this.parentCommit = parentCommit;
    this.targetBranch = targetBranch;
    this.fetchOpts = fetchOpts;
  }

  async _headCommit() {
    return headCommit(this.repo, this.targetBranch, this.fetchOpts);
  }

  async get(path, { allowCreate, allowUpdate } = {}) {
    let { tree, leaf, leafName } = await this.root.fileAtPath(path, allowCreate);
    return new FileHandle(tree, leaf, leafName, allowUpdate, path);
  }

  async finalize(commitOpts) {
    let newCommit = await this._makeCommit(commitOpts);

    let delayTime = 500;
    let mergeCommit;
    while (delayTime <= 5000) {
      mergeCommit = await this._makeMergeCommit(newCommit, commitOpts);

      try {
        if(this.fetchOpts) {
          await this._pushCommit(mergeCommit);
        } else {
          await this._applyCommit(mergeCommit);
        }
      } catch (err) {
        await delay(delayTime);
        log.warn('Failed to finalize commit "%s"', err);

        delayTime *= 2;
      }

    return mergeCommit.id().tostrS();
  }

  throw new Error('Failed to finalise commit and could not recover');
}

  async _makeCommit(commitOpts) {
    let treeOid = await this.root.write(true);

    if (treeOid && this.parentTree && treeOid.equal(this.parentTree.id())) {
      return this.parentCommit;
    }

    let tree = await Tree.lookup(this.repo, treeOid, null);
    let { author, committer } = signature(commitOpts);
    let commitOid = await Commit.create(this.repo, null, author, committer, 'UTF-8', commitOpts.message, tree, this.parents.length, this.parents);
    return Commit.lookup(this.repo, commitOid);
  }

  async _pushCommit(mergeCommit) {
    const remoteBranchName = `temp-remote-${crypto.randomBytes(20).toString('hex')}`;
    await Branch.create(this.repo, remoteBranchName, mergeCommit, false);

    let remote = await this.repo.getRemote('origin');

    try {
      await remote.push([`refs/heads/${remoteBranchName}:refs/heads/${this.targetBranch}`], this.fetchOpts);
    } catch (err) {
      // pull remote before allowing process to continue
      await this.repo.fetchAll(this.fetchOpts);
      throw err;
    }
  }

  async _makeMergeCommit(newCommit, commitOpts) {
    let headCommit = await this._headCommit();

    if (!headCommit) {
      // new branch, so no merge needed
      return newCommit;
    }
    let baseOid = await Merge.base(this.repo, newCommit, headCommit);
    if (baseOid.equal(headCommit.id())) {
      // fast forward (we think), so no merge needed
      return newCommit;
    }
    let index = await Merge.commits(this.repo, newCommit, headCommit, null);
    if (index.hasConflicts()) {
      throw new GitConflict(index);
    }
    let treeOid = await index.writeTreeTo(this.repo);
    let tree = await Tree.lookup(this.repo, treeOid, null);
    let { author, committer } = signature(commitOpts);
    let mergeCommitOid = await Commit.create(this.repo, null, author, committer, 'UTF-8', `Clean merge into ${this.targetBranch}`, tree, 2, [newCommit, headCommit]);
    return await Commit.lookup(this.repo, mergeCommitOid);
  }

  async _applyCommit(commit) {
    let headCommit = await this._headCommit();

    if (!headCommit) {
      return await this._newBranch(commit);
    }

    let headRef = await Branch.lookup(this.repo, this.targetBranch, Branch.BRANCH.LOCAL);
    await headRef.setTarget(commit.id(), 'fast forward');
  }

  async _newBranch(newCommit) {
    await Branch.create(this.repo, this.targetBranch, newCommit, false);
  }
}

function signature(commitOpts) {
  let date = commitOpts.authorDate || moment();
  let author = Signature.create(commitOpts.authorName, commitOpts.authorEmail, date.unix(), date.utcOffset());
  let committer = commitOpts.committerName ? Signature.create(commitOpts.committerName, commitOpts.committerEmail, date.unix(), date.utcOffset()) : author;
  return {
    author,
    committer
  };
}

class GitConflict extends Error {
  constructor(index) {
    super();
    this.index = index;
  }
}

class FileHandle {
  constructor(tree, leaf, name, allowUpdate, path) {
    this.tree = tree;
    this.leaf = leaf;
    this.name = name;
    this.allowUpdate = allowUpdate;
    this.path = path;
    if (leaf) {
      this.mode = leaf.filemode();
    } else {
      this.mode = FILEMODE.BLOB;
    }
  }
  async getBuffer() {
    if (this.leaf) {
      return (await this.leaf.getBlob()).content();
    }
  }
  exists() {
    return !!this.leaf;
  }
  setContent(buffer) {
    if (typeof buffer === 'string') {
      buffer = Buffer.from(buffer, 'utf8');
    }
    if (!(buffer instanceof Buffer)) {
      throw new Error("setContent got something that was not a Buffer or String");
    }
    if (!this.allowUpdate && this.leaf) {
      throw new OverwriteRejected(`Refusing to overwrite ${this.path}`);
    }
    this.leaf = this.tree.insert(this.name, buffer, this.mode);
  }
  delete() {
    if (!this.leaf) {
      throw new NotFound(`No such file ${this.path}`);
    }
    this.tree.delete(this.name);
    this.leaf = null;
  }
  savedId() {
    // this is available only after our change has been finalized
    if (this.leaf.savedId) {
      return this.leaf.savedId.tostrS();
    }
  }
}

Change.GitConflict = GitConflict;
Change.NotFound = NotFound;
Change.OverwriteRejected = OverwriteRejected;

module.exports = Change;

async function headCommit(repo, targetBranch, fetchOpts) {
  let headRef;
  try {
    if (fetchOpts) {
      headRef = await Branch.lookup(repo, `origin/${targetBranch}`, Branch.BRANCH.REMOTE);
    } else {
      headRef = await Branch.lookup(repo, targetBranch, Branch.BRANCH.LOCAL);
    }
  } catch(err) {
    if (err.errorFunction !== 'Branch.lookup') {
      throw err;
    }
  }
  if (headRef) {
    return await Commit.lookup(repo, headRef.target());
  }
}
<|endoftext|>


<commit_before>/* eslint-disable ember/no-array-prototype-extensions, ember/no-mixins, ember/no-classic-classes, ember/no-get, ember/avoid-leaking-state-in-ember-objects */
import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
import Model, { attr, hasMany, belongsTo } from '@ember-data/model';
import BaseModelMixin from 'irene/mixins/base-model';
import ENUMS from 'irene/enums';
import { t } from 'ember-intl';
import { RISK_COLOR_CODE } from 'irene/utils/constants';

const _getAnalysesCount = (analysis, risk) => {
  return analysis.filterBy('computedRisk', risk).get('length');
};

const File = Model.extend(BaseModelMixin, {
  intl: service(),
  project: belongsTo('project', {
    inverse: 'files',
  }),
  profile: belongsTo('profile', {
    inverse: 'files',
  }),
  uuid: attr('string'),
  deviceToken: attr('string'),
  version: attr('string'),
  versionCode: attr('string'),
  iconUrl: attr('string'),
  md5hash: attr('string'),
  sha1hash: attr('string'),
  name: attr('string'),
  dynamicStatus: attr('number'),
  analyses: hasMany('analysis', {
    inverse: 'file',
  }),
  report: attr('string'),
  manual: attr('number'),
  apiScanProgress: attr('number'),
  staticScanProgress: attr('number'),
  isActive: attr('boolean'),
  isStaticDone: attr('boolean'),
  isDynamicDone: attr('boolean'),
  isManualDone: attr('boolean'),
  isApiDone: attr('boolean'),
  apiScanStatus: attr('number'),
  tags: hasMany('tag'),
  minOsVersion: attr('string'),
  supportedCpuArchitectures: attr('string'),
  supportedDeviceTypes: attr('string'),
  canRunAutomatedDynamicscan: attr('boolean'),
  reports: hasMany('file-report', {
    async: true,
  }),

  isManualRequested: computed('manual', function () {
    return this.get('manual') !== ENUMS.MANUAL.NONE;
  }),

  isRunningApiScan: computed('apiScanStatus', function () {
    const apiScanStatus = this.get('apiScanStatus');
    return apiScanStatus == ENUMS.SCAN_STATUS.RUNNING;
  }),

  isApiNotDone: computed.not('isApiDone'),

  scanProgressClass(type) {
    if (type === true) {
      return true;
    }
    return false;
  },

  isStaticCompleted: computed('isStaticDone', function () {
    const isStaticDone = this.get('isStaticDone');
    return this.scanProgressClass(isStaticDone);
  }),

  tDeviceInQueue: t('deviceInQueue'),
  tDeviceBooting: t('deviceBooting'),
  tDeviceDownloading: t('deviceDownloading'),
  tDeviceInstalling: t('deviceInstalling'),
  tDeviceLaunching: t('deviceLaunching'),
  tDeviceHooking: t('deviceHooking'),
  tDeviceShuttingDown: t('deviceShuttingDown'),
  tDeviceCompleted: t('deviceCompleted'),

  analysesSorting: ['computedRisk:desc'],
  sortedAnalyses: computed.sort('analyses', 'analysesSorting'),

  countRiskCritical: 0,
  countRiskHigh: 0,
  countRiskMedium: 0,
  countRiskLow: 0,
  countRiskNone: 0,
  countRiskUnknown: 0,

  canGenerateReport: attr('boolean'),

  doughnutData: computed('analyses.@each.computedRisk', function () {
    const analyses = this.get('analyses');
    const r = ENUMS.RISK;
    const countRiskCritical = _getAnalysesCount(analyses, r.CRITICAL);
    const countRiskHigh = _getAnalysesCount(analyses, r.HIGH);
    const countRiskMedium = _getAnalysesCount(analyses, r.MEDIUM);
    const countRiskLow = _getAnalysesCount(analyses, r.LOW);
    const countRiskNone = _getAnalysesCount(analyses, r.NONE);
    const countRiskUnknown = _getAnalysesCount(analyses, r.UNKNOWN);

    this.set('countRiskCritical', countRiskCritical); // eslint-disable-line
    this.set('countRiskHigh', countRiskHigh); // eslint-disable-line
    this.set('countRiskMedium', countRiskMedium); // eslint-disable-line
    this.set('countRiskLow', countRiskLow); // eslint-disable-line
    this.set('countRiskNone', countRiskNone); // eslint-disable-line
    this.set('countRiskUnknown', countRiskUnknown); // eslint-disable-line

    return {
      labels: ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'PASSED', 'UNKNOWN'],
      datasets: [
        {
          label: 'Risks',
          data: [
            countRiskCritical,
            countRiskHigh,
            countRiskMedium,
            countRiskLow,
            countRiskNone,
            countRiskUnknown,
          ],
          backgroundColor: [
            RISK_COLOR_CODE.CRITICAL,
            RISK_COLOR_CODE.DANGER,
            RISK_COLOR_CODE.WARNING,
            RISK_COLOR_CODE.INFO,
            RISK_COLOR_CODE.SUCCESS,
            RISK_COLOR_CODE.DEFAULT,
          ],
        },
      ],
    };
  }),

  isNoneStatus: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return status === ENUMS.DYNAMIC_STATUS.NONE;
  }),

  isNotNoneStatus: computed.not('isNoneStatus'),

  isReady: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return status === ENUMS.DYNAMIC_STATUS.READY;
  }),

  isNotReady: computed.not('isReady'),

  isDynamicStatusNone: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return status === ENUMS.DYNAMIC_STATUS.NONE;
  }),

  isDynamicStatusError: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return status === ENUMS.DYNAMIC_STATUS.ERROR;
  }),

  isDynamicStatusQueueAndHasAutomation: computed(
    'dynamicStatus',
    'canRunAutomatedDynamicscan',
    function () {
      const status = this.get('dynamicStatus');
      return (
        status === ENUMS.DYNAMIC_STATUS.INQUEUE &&
        this.get('canRunAutomatedDynamicscan')
      );
    }
  ),
  isDynamicStatusReady: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return status === ENUMS.DYNAMIC_STATUS.READY;
  }),

  isDynamicStatusNotReady: computed.not('isDynamicStatusReady'),
  isDynamicStatusNotNone: computed.not('isDynamicStatusNone'),

  isDynamicStatusNeitherNoneNorReadyNorError: computed(
    'dynamicStatus',
    function () {
      const status = this.get('dynamicStatus');
      return ![
        ENUMS.DYNAMIC_STATUS.READY,
        ENUMS.DYNAMIC_STATUS.NONE,
        ENUMS.DYNAMIC_STATUS.ERROR,
      ].includes(status);
    }
  ),

  isDynamicStatusNoneOrError: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return [ENUMS.DYNAMIC_STATUS.NONE, ENUMS.DYNAMIC_STATUS.ERROR].includes(
      status
    );
  }),

  isDynamicStatusNoneOrReady: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return [ENUMS.DYNAMIC_STATUS.READY, ENUMS.DYNAMIC_STATUS.NONE].includes(
      status
    );
  }),

  isDynamicStatusStarting: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return ![
      ENUMS.DYNAMIC_STATUS.READY,
      ENUMS.DYNAMIC_STATUS.NONE,
      ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN,
    ].includes(status);
  }),

  isDynamicStatusInProgress: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return [
      ENUMS.DYNAMIC_STATUS.INQUEUE,
      ENUMS.DYNAMIC_STATUS.BOOTING,
      ENUMS.DYNAMIC_STATUS.DOWNLOADING,
      ENUMS.DYNAMIC_STATUS.INSTALLING,
      ENUMS.DYNAMIC_STATUS.LAUNCHING,
      ENUMS.DYNAMIC_STATUS.HOOKING,
      ENUMS.DYNAMIC_STATUS.READY,
      ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN,
    ].includes(status);
  }),

  isNeitherNoneNorReady: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return ![ENUMS.DYNAMIC_STATUS.READY, ENUMS.DYNAMIC_STATUS.NONE].includes(
      status
    );
  }),

  startingScanStatus: computed('dynamicStatus', function () {
    const status = this.get('dynamicStatus');
    return ![
      ENUMS.DYNAMIC_STATUS.READY,
      ENUMS.DYNAMIC_STATUS.NONE,
      ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN,
    ].includes(status);
  }),

  showScheduleAutomatedDynamicScan: computed(
    'dynamicStatus',
    'canRunAutomatedDynamicscan',
    function () {
      const status = this.get('dynamicStatus');
      return (
        status !== ENUMS.DYNAMIC_STATUS.INQUEUE &&
        this.get('canRunAutomatedDynamicscan')
      );
    }
  ),

  statusText: computed(
    'dynamicStatus',
    'tDeviceBooting',
    'tDeviceDownloading',
    'tDeviceHooking',
    'tDeviceInQueue',
    'tDeviceInstalling',
    'tDeviceLaunching',
    'tDeviceShuttingDown',
    'tdeviceCompleted',
    function () {
      const tDeviceInQueue = this.get('tDeviceInQueue');
      const tDeviceBooting = this.get('tDeviceBooting');
      const tDeviceDownloading = this.get('tDeviceDownloading');
      const tDeviceInstalling = this.get('tDeviceInstalling');
      const tDeviceLaunching = this.get('tDeviceLaunching');
      const tDeviceHooking = this.get('tDeviceHooking');
      const tDeviceShuttingDown = this.get('tDeviceShuttingDown');
      const tDeviceCompleted = this.get('tdeviceCompleted');

      switch (this.get('dynamicStatus')) {
        case ENUMS.DYNAMIC_STATUS.INQUEUE:
          return tDeviceInQueue;
        case ENUMS.DYNAMIC_STATUS.BOOTING:
          return tDeviceBooting;
        case ENUMS.DYNAMIC_STATUS.DOWNLOADING:
          return tDeviceDownloading;
        case ENUMS.DYNAMIC_STATUS.INSTALLING:
          return tDeviceInstalling;
        case ENUMS.DYNAMIC_STATUS.LAUNCHING:
          return tDeviceLaunching;
        case ENUMS.DYNAMIC_STATUS.HOOKING:
          return tDeviceHooking;
        case ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN:
          return tDeviceShuttingDown;
        case ENUMS.DYNAMIC_STATUS.COMPLETED:
          return tDeviceCompleted;
        default:
          return 'Unknown Status';
      }
    }
  ),

  setDynamicStatus(status) {
    this.store.push({
      data: {
        id: this.id,
        type: this.constructor.modelName,
        attributes: {
          dynamicStatus: status,
        },
      },
    });
  },

  setBootingStatus() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.BOOTING);
  },

  setInQueueStatus() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.INQUEUE);
  },

  setShuttingDown() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN);
  },

  setNone() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.NONE);
  },

  setDynamicStatusNone() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.NONE);
  },

  setReady() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.READY);
  },
});

export default File;
<commit_msg>complete file model migration<commit_after>/* eslint-disable ember/no-computed-properties-in-native-classes */
/* eslint-disable ember/no-mixins */
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
import { computed } from '@ember/object';
import { sort } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import ENUMS from 'irene/enums';
import { ModelBaseMixin } from 'irene/mixins/base-model';
import { RISK_COLOR_CODE } from 'irene/utils/constants';

const _getAnalysesCount = (analysis, risk) => {
  return analysis.filter((analysis) => analysis.computedRisk === risk).length;
};

class File extends ModelBaseMixin(Model) {
  @service intl;
  @service store;

  @attr('string') uuid;
  @attr('string') deviceToken;
  @attr('string') version;
  @attr('string') versionCode;
  @attr('string') iconUrl;
  @attr('string') md5hash;
  @attr('string') sha1hash;
  @attr('string') name;
  @attr('string') minOsVersion;
  @attr('string') supportedCpuArchitectures;
  @attr('string') supportedDeviceTypes;
  @attr('string') report;

  @attr('number') manual;
  @attr('number') dynamicStatus;
  @attr('number') apiScanProgress;
  @attr('number') staticScanProgress;
  @attr('number') apiScanStatus;

  @attr('boolean') isActive;
  @attr('boolean') isApiDone;
  @attr('boolean') isStaticDone;
  @attr('boolean') isManualDone;
  @attr('boolean') isDynamicDone;
  @attr('boolean') canGenerateReport;
  @attr('boolean') canRunAutomatedDynamicscan;

  @hasMany('tag') tags;
  @hasMany('file-report', { async: true }) reports;
  @hasMany('analysis', { inverse: 'file' }) analyses;

  @belongsTo('project', { inverse: 'files' }) project;
  @belongsTo('profile', { inverse: 'files' }) profile;

  tDeviceInQueue = this.intl.t('deviceInQueue');
  tDeviceBooting = this.intl.t('deviceBooting');
  tDeviceDownloading = this.intl.t('deviceDownloading');
  tDeviceInstalling = this.intl.t('deviceInstalling');
  tDeviceLaunching = this.intl.t('deviceLaunching');
  tDeviceHooking = this.intl.t('deviceHooking');
  tDeviceShuttingDown = this.intl.t('deviceShuttingDown');
  tDeviceCompleted = this.intl.t('deviceCompleted');

  analysesSorting = ['computedRisk:desc'];
  countRiskCritical = 0;
  countRiskHigh = 0;
  countRiskMedium = 0;
  countRiskLow = 0;
  countRiskNone = 0;
  countRiskUnknown = 0;

  scanProgressClass(type) {
    if (type === true) {
      return true;
    }
    return false;
  }

  get isManualRequested() {
    return this.manual !== ENUMS.MANUAL.NONE;
  }

  get isRunningApiScan() {
    const apiScanStatus = this.apiScanStatus;
    return apiScanStatus == ENUMS.SCAN_STATUS.RUNNING;
  }

  get isApiNotDone() {
    return !this.isApiDone;
  }

  get isStaticCompleted() {
    const isStaticDone = this.isStaticDone;
    return this.scanProgressClass(isStaticDone);
  }

  get isNoneStatus() {
    const status = this.dynamicStatus;
    return status === ENUMS.DYNAMIC_STATUS.NONE;
  }

  get isNotNoneStatus() {
    return !this.isNoneStatus;
  }
  get isNotReady() {
    return !this.isReady;
  }

  get isReady() {
    const status = this.dynamicStatus;
    return status === ENUMS.DYNAMIC_STATUS.READY;
  }

  get isDynamicStatusNone() {
    const status = this.dynamicStatus;
    return status === ENUMS.DYNAMIC_STATUS.NONE;
  }

  get isDynamicStatusError() {
    const status = this.dynamicStatus;
    return status === ENUMS.DYNAMIC_STATUS.ERROR;
  }

  get isDynamicStatusQueueAndHasAutomation() {
    const status = this.dynamicStatus;
    return (
      status === ENUMS.DYNAMIC_STATUS.INQUEUE && this.canRunAutomatedDynamicscan
    );
  }

  get isDynamicStatusReady() {
    const status = this.dynamicStatus;
    return status === ENUMS.DYNAMIC_STATUS.READY;
  }

  get isDynamicStatusNotReady() {
    return !this.isDynamicStatusReady;
  }

  get isDynamicStatusNotNone() {
    return !this.isDynamicStatusNone;
  }

  get isDynamicStatusNeitherNoneNorReadyNorError() {
    const status = this.dynamicStatus;
    return ![
      ENUMS.DYNAMIC_STATUS.READY,
      ENUMS.DYNAMIC_STATUS.NONE,
      ENUMS.DYNAMIC_STATUS.ERROR,
    ].includes(status);
  }

  get isDynamicStatusNoneOrError() {
    const status = this.dynamicStatus;
    return [ENUMS.DYNAMIC_STATUS.NONE, ENUMS.DYNAMIC_STATUS.ERROR].includes(
      status
    );
  }

  get isDynamicStatusNoneOrReady() {
    const status = this.dynamicStatus;
    return [ENUMS.DYNAMIC_STATUS.READY, ENUMS.DYNAMIC_STATUS.NONE].includes(
      status
    );
  }

  get isDynamicStatusStarting() {
    const status = this.dynamicStatus;
    return ![
      ENUMS.DYNAMIC_STATUS.READY,
      ENUMS.DYNAMIC_STATUS.NONE,
      ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN,
    ].includes(status);
  }

  get isDynamicStatusInProgress() {
    const status = this.dynamicStatus;
    return [
      ENUMS.DYNAMIC_STATUS.INQUEUE,
      ENUMS.DYNAMIC_STATUS.BOOTING,
      ENUMS.DYNAMIC_STATUS.DOWNLOADING,
      ENUMS.DYNAMIC_STATUS.INSTALLING,
      ENUMS.DYNAMIC_STATUS.LAUNCHING,
      ENUMS.DYNAMIC_STATUS.HOOKING,
      ENUMS.DYNAMIC_STATUS.READY,
      ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN,
    ].includes(status);
  }

  get isNeitherNoneNorReady() {
    const status = this.dynamicStatus;
    return ![ENUMS.DYNAMIC_STATUS.READY, ENUMS.DYNAMIC_STATUS.NONE].includes(
      status
    );
  }

  get startingScanStatus() {
    return this.isDynamicStatusStarting;
  }

  get showScheduleAutomatedDynamicScan() {
    const status = this.dynamicStatus;
    return (
      status !== ENUMS.DYNAMIC_STATUS.INQUEUE && this.canRunAutomatedDynamicscan
    );
  }

  get statusText() {
    const tDeviceInQueue = this.tDeviceInQueue;
    const tDeviceBooting = this.tDeviceBooting;
    const tDeviceDownloading = this.tDeviceDownloading;
    const tDeviceInstalling = this.tDeviceInstalling;
    const tDeviceLaunching = this.tDeviceLaunching;
    const tDeviceHooking = this.tDeviceHooking;
    const tDeviceShuttingDown = this.tDeviceShuttingDown;
    const tDeviceCompleted = this.tdeviceCompleted;

    switch (this.dynamicStatus) {
      case ENUMS.DYNAMIC_STATUS.INQUEUE:
        return tDeviceInQueue;
      case ENUMS.DYNAMIC_STATUS.BOOTING:
        return tDeviceBooting;
      case ENUMS.DYNAMIC_STATUS.DOWNLOADING:
        return tDeviceDownloading;
      case ENUMS.DYNAMIC_STATUS.INSTALLING:
        return tDeviceInstalling;
      case ENUMS.DYNAMIC_STATUS.LAUNCHING:
        return tDeviceLaunching;
      case ENUMS.DYNAMIC_STATUS.HOOKING:
        return tDeviceHooking;
      case ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN:
        return tDeviceShuttingDown;
      case ENUMS.DYNAMIC_STATUS.COMPLETED:
        return tDeviceCompleted;
      default:
        return 'Unknown Status';
    }
  }

  setDynamicStatus(status) {
    this.store.push({
      data: {
        id: this.id,
        type: this.constructor.modelName,
        attributes: {
          dynamicStatus: status,
        },
      },
    });
  }

  setBootingStatus() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.BOOTING);
  }

  setInQueueStatus() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.INQUEUE);
  }

  setShuttingDown() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.SHUTTING_DOWN);
  }

  setNone() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.NONE);
  }

  setDynamicStatusNone() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.NONE);
  }

  setReady() {
    this.setDynamicStatus(ENUMS.DYNAMIC_STATUS.READY);
  }

  @sort('analyses', 'analysesSorting') sortedAnalyses;

  @computed('analyses.@each.computedRisk')
  get doughnutData() {
    const analyses = this.analyses;
    const r = ENUMS.RISK;
    const countRiskCritical = _getAnalysesCount(analyses, r.CRITICAL);
    const countRiskHigh = _getAnalysesCount(analyses, r.HIGH);
    const countRiskMedium = _getAnalysesCount(analyses, r.MEDIUM);
    const countRiskLow = _getAnalysesCount(analyses, r.LOW);
    const countRiskNone = _getAnalysesCount(analyses, r.NONE);
    const countRiskUnknown = _getAnalysesCount(analyses, r.UNKNOWN);

    this.countRiskCritical = countRiskCritical; // eslint-disable-line
    this.countRiskHigh = countRiskHigh; // eslint-disable-line
    this.countRiskMedium = countRiskMedium; // eslint-disable-line
    this.countRiskLow = countRiskLow; // eslint-disable-line
    this.countRiskNone = countRiskNone; // eslint-disable-line
    this.countRiskUnknown = countRiskUnknown; // eslint-disable-line

    return {
      labels: ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'PASSED', 'UNKNOWN'],
      datasets: [
        {
          label: 'Risks',
          data: [
            countRiskCritical,
            countRiskHigh,
            countRiskMedium,
            countRiskLow,
            countRiskNone,
            countRiskUnknown,
          ],
          backgroundColor: [
            RISK_COLOR_CODE.CRITICAL,
            RISK_COLOR_CODE.DANGER,
            RISK_COLOR_CODE.WARNING,
            RISK_COLOR_CODE.INFO,
            RISK_COLOR_CODE.SUCCESS,
            RISK_COLOR_CODE.DEFAULT,
          ],
        },
      ],
    };
  }
}

export default File;
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import Header from 'Header'
import MainSection from 'MainSection'

//require (un-named) stores as a good habit
var req = require.context("stores", true, /^(.*\.(js$))[^.]*$/igm);
req.keys().forEach((key)=>{
  req(key);
});

class App extends Component {
  render() {
    return (

        <MainSection/>

    )
  }
}
<commit_msg>export App<commit_after>import React, { Component, PropTypes } from 'react'
import Header from './Header'
import MainSection from './MainSection'

//require (un-named) stores as a good habit
var req = require.context("../store", true, /^(.*\.(js$))[^.]*$/igm);
req.keys().forEach((key)=>{
  req(key);
});

class App extends Component {
  render() {
    return (

    )
  }
}
//<MainSection/>
export default App;<|endoftext|>


<commit_before>/*
===============================================================================

	Element, that perform game preload and initialization.
	Uses Modernizr library ( load() module from YepNope library ).
	Loads game files and initializes the game.

===============================================================================
*/

/*
================
	Main game object.
	Used as name space.
================
*/
function Doa() {
	if ( !(this instanceof Doa) ) return new Doa();

	// Libraries
	this.lib = [
		"lib/three",
		"lib/stats",
		"lib/dat.gui"
	];

	// Essential game files
	this.files = [
		"base/Utils",
		"base/Settings",
		"base/Objects",
		"base/Caches",
		"base/Player",
		"base/UI",
		"base/World",
		"base/Engine",
		"base/Game"];

	// Non-essential game files.
	// #@ use preload "preload!base/data/textures/img.gif" @#
	this.data = [];
}

/*
================
logVerify
Log the pretty info messages to console. Unsed in `Doa.verify()`.
================
*/
Doa.prototype.logVerify = function ( isVerified, message ) {
	// Fill msg with the whitespace to length of 20
	message = message +
			  ( new Array( 20 - message.length ).join( " " )) +
			  ( isVerified ? " : YES" : " : NO" );

	console.info( message );

	return isVerified;
};

/*
================
verify
Checks compatibility and prevent further execution.
================
*/
Doa.prototype.verify = function () {
	var isSupported = true;

	console.groupCollapsed( "Verification" );

	isSupported &= this.logVerify(
		typeof Storage !== "undefined",
		"Storage support"
	);

	var audio = document.createElement('audio');
	isSupported &= this.logVerify(
		!!audio.canPlayType,
		"Audio support"
	);

	isSupported &= this.logVerify(
		typeof Worker !== "undefined",
		"Webworkers support"
	);

	isSupported &= this.logVerify(
		'pointerLockElement' in document ||
		'mozPointerLockElement' in document ||
		'webkitPointerLockElement' in document,
		"PointerLock support"
	);

	isSupported &= this.logVerify(
		'mozFullScreenElement' in document ||
		'mozFullscreenElement' in document ||
		'webkitFullscreenElement' in document,
		"Fullscreen support"
	);

	console.groupEnd(); // close Browser

	if ( !isSupported ) {
		console.warn( "Execution will be aborted due to previous errors." );
		throw new Error( "Verification failed. Browser not fully supported." );
	}
};

// DOA object
var DOA = new Doa();

/*
---------------------------------------------------------------------------
RequireJS
---------------------------------------------------------------------------
*/
require.config({
	baseUrl: ""
});

function chainRequire( files, index ) {
	files = files || [];
	index = index || 0;

	document.dispatchEvent( new CustomEvent( 'required', {
		'detail': {
			'name' : files[ index ],
			'count': index + 1,
			'total': files.length
			}
		}));

	if ( index <= files.length - 1 ) {
		require( [ files[ index ] ], function () {
			index++;
			chainRequire( files, index );
		});
	}
}

/*
---------------------------------------------------------------------------
Loader
---------------------------------------------------------------------------
*/
var reqiuredListener =
document.addEventListener( 'required', function ( e ) {

	if ( e.detail.count > e.detail.total ) {
		console.groupEnd();
		this.removeEventListener( 'required', reqiuredListener );

		var progress = document.getElementById( 'loading-tip' ),
			preload  = document.getElementById( 'preload' );

			document.onkeydown = hidePreload;
			preload.onclick    = hidePreload;

			progress.textContent = "Press any key to continue";

			DOA.Game.init();
			//@#
			hidePreload();
			//#@
	} else {
		console.info(
			"[" + e.detail.count + "/" + e.detail.total + "]'" +
			e.detail.name + "' loading."
		);
	}

}, false );

function hidePreload() {
	document.onkeydown = null;
	preload.onclick = null;
	preload.remove();
	DOA.Engine.renderer.domElement.style.display = 'block';

	DOA.Game.bind();
	DOA.Game.animate();

	DOA.Game.isRunnig = true;
	DOA.Game.status = 1;

	DOA.Game.canvas = DOA.Engine.renderer.domElement;
	DOA.Game.canvas.requestPointerLock =
					  DOA.Game.canvas.requestPointerLock    ||
					  DOA.Game.canvas.mozRequestPointerLock ||
					  DOA.Game.canvas.webkitRequestPointerLock;
	document.exitPointerLock =
					  document.exitPointerLock    ||
					  document.mozExitPointerLock ||
					  document.webkitExitPointerLock;
	DOA.Game.fullscreen = document.body;
	DOA.Game.fullscreen.requestFullscreen =
					  DOA.Game.canvas.requestFullscreen    ||
					  DOA.Game.canvas.mozRequestFullscreen ||
					  DOA.Game.canvas.mozRequestFullScreen ||
					  DOA.Game.canvas.webkitRequestFullscreen;
}

/*
---------------------------------------------------------------------------
Start application
---------------------------------------------------------------------------
*/
function start() {
	if ( document.readyState === 'complete' ) {
		DOA.verify();

		console.groupCollapsed( 'Preload' );

		require (DOA.lib, function () {
			chainRequire( DOA.files );
		});
	}
}

// Start, when the document is loaded
document.onreadystatechange = function () {
	start();
};
// ...or start right away, if the page is cached
start();
<commit_msg>:art: Updating loader code aligning.<commit_after>/*
===============================================================================

	Element, that perform game preload and initialization.
	Uses Modernizr library ( load() module from YepNope library ).
	Loads game files and initializes the game.

===============================================================================
*/

/*
================
	Main game object.
	Used as name space.
================
*/
function Doa() {
	if ( !(this instanceof Doa) ) return new Doa();

	// Libraries
	this.lib = [
		"lib/three",
		"lib/stats",
		"lib/dat.gui"
	];

	// Essential game files
	this.files = [
		"base/Utils",
		"base/Settings",
		"base/Objects",
		"base/Caches",
		"base/Player",
		"base/UI",
		"base/World",
		"base/Engine",
		"base/Game"
	];

	// Non-essential game files.
	// #@ use preload "preload!base/data/textures/img.gif" @#
	this.data = [];
}

/*
================
logVerify
Log the pretty info messages to console. Unsed in `Doa.verify()`.
================
*/
Doa.prototype.logVerify = function ( isVerified, message ) {
	// Fill msg with the whitespace to length of 20
	message = message +
		( new Array( 20 - message.length ).join( " " ) ) +
		( isVerified ? " : YES" : " : NO" );

	console.info( message );

	return isVerified;
};

/*
================
verify
Checks compatibility and prevent further execution.
================
*/
Doa.prototype.verify = function () {
	var isSupported = true;

	console.groupCollapsed( "Verification" );

	isSupported &= this.logVerify(
		typeof Storage !== "undefined",
		"Storage support"
	);

	var audio = document.createElement('audio');
	isSupported &= this.logVerify(
		!!audio.canPlayType,
		"Audio support"
	);

	isSupported &= this.logVerify(
		typeof Worker !== "undefined",
		"Webworkers support"
	);

	isSupported &= this.logVerify(
		'pointerLockElement' in document ||
		'mozPointerLockElement' in document ||
		'webkitPointerLockElement' in document,
		"PointerLock support"
	);

	isSupported &= this.logVerify(
		'mozFullScreenElement' in document ||
		'mozFullscreenElement' in document ||
		'webkitFullscreenElement' in document,
		"Fullscreen support"
	);

	console.groupEnd(); // close Browser

	if ( !isSupported ) {
		console.warn( "Execution will be aborted due to previous errors." );
		throw new Error( "Verification failed. Browser not fully supported." );
	}
};

// DOA object
var DOA = new Doa();

/*
---------------------------------------------------------------------------
RequireJS
---------------------------------------------------------------------------
*/
require.config({
	baseUrl: ""
});

function chainRequire( files, index ) {
	files = files || [];
	index = index || 0;

	document.dispatchEvent( new CustomEvent( 'required', {
		'detail': {
			'name' : files[ index ],
			'count': index + 1,
			'total': files.length
			}
		}));

	if ( index <= files.length - 1 ) {
		require( [ files[ index ] ], function () {
			index++;
			chainRequire( files, index );
		});
	}
}

/*
---------------------------------------------------------------------------
Loader
---------------------------------------------------------------------------
*/
var reqiuredListener =
document.addEventListener( 'required', function ( e ) {

	if ( e.detail.count > e.detail.total ) {
		console.groupEnd();
		this.removeEventListener( 'required', reqiuredListener );

		var progress = document.getElementById( 'loading-tip' ),
			preload  = document.getElementById( 'preload' );

			document.onkeydown = hidePreload;
			preload.onclick    = hidePreload;

			progress.textContent = "Press any key to continue";

			DOA.Game.init();
			//@#
			hidePreload();
			//#@
	} else {
		console.info(
			"[" + e.detail.count + "/" + e.detail.total + "]'" +
			e.detail.name + "' loading."
		);
	}

}, false );

function hidePreload() {
	document.onkeydown = null;
	preload.onclick = null;
	preload.remove();
	DOA.Engine.renderer.domElement.style.display = 'block';

	DOA.Game.bind();
	DOA.Game.animate();

	DOA.Game.isRunnig = true;
	DOA.Game.status = 1;

	DOA.Game.canvas = DOA.Engine.renderer.domElement;
	DOA.Game.canvas.requestPointerLock =
		DOA.Game.canvas.requestPointerLock    ||
		DOA.Game.canvas.mozRequestPointerLock ||
		DOA.Game.canvas.webkitRequestPointerLock;
	document.exitPointerLock =
		document.exitPointerLock    ||
		document.mozExitPointerLock ||
		document.webkitExitPointerLock;
	DOA.Game.fullscreen = document.body;
	DOA.Game.fullscreen.requestFullscreen =
		DOA.Game.canvas.requestFullscreen    ||
		DOA.Game.canvas.mozRequestFullscreen ||
		DOA.Game.canvas.mozRequestFullScreen ||
		DOA.Game.canvas.webkitRequestFullscreen;
}

/*
---------------------------------------------------------------------------
Start application
---------------------------------------------------------------------------
*/
function start() {
	if ( document.readyState === 'complete' ) {
		DOA.verify();

		console.groupCollapsed( 'Preload' );

		require (DOA.lib, function () {
			chainRequire( DOA.files );
		});
	}
}

// Start, when the document is loaded
document.onreadystatechange = function () {
	start();
};
// ...or start right away, if the page is cached
start();
<|endoftext|>


<commit_before>//     storage.js v0.5.0
//     (c)(by) Jan Muehlemann (jamuhl)
//        , Adriano Raiano (adrai)

// The storage is the database driver for mongoDb.
//
// __Example:__
//
//      require('[pathToStorage]/storage').createStorage({}, function(err, storage) {
//          ...
//      });

var mongo = require('mongodb')
  , tolerate = require('tolerance')
  , ObjectID = mongo.BSONPure.ObjectID
  , root = this
  , mongoDbStorage
  , Storage;

if (typeof exports !== 'undefined') {
    mongoDbStorage = exports;
} else {
    mongoDbStorage = root.mongoDbStorage = {};
}

mongoDbStorage.VERSION = '0.6.1';

// Create new instance of storage.
mongoDbStorage.createStorage = function(options, callback) {
    return new Storage(options, callback);
};

// ## MongoDb storage
Storage = function(options, callback) {

    this.filename = __filename;
    this.isConnected = false;

    if (typeof options === 'function')
        callback = options;

    var defaults = {
        host: 'localhost',
        port: 27017,
        dbName: 'eventstore',
        eventsCollectionName: 'events',
        snapshotsCollectionName: 'snapshots',
        transactionsCollectionName: 'transactions'
    };

    this.options = mergeOptions(options, defaults);

    var defaultOpt = {
        auto_reconnect: true,
        ssl: false
    };

    this.options.options = this.options.options || {};

    this.options.options = mergeOptions(this.options.options, defaultOpt);

    if (callback) {
        this.connect(callback);
    }
};

Storage.prototype = {

    // __connect:__ connects the underlaying database.
    //
    // `storage.connect(callback)`
    //
    // - __callback:__ `function(err, storage){}`
    connect: function(callback) {
        var self = this;

        tolerate(function(callback) {
            var server = new mongo.Server(self.options.host, self.options.port, self.options.options);
            new mongo.Db(self.options.dbName , server, { safe: true }).open(callback);
        }, this.options.timeout || 0, function(err, client) {
            if (err) {
                if (callback) callback(err);
            } else {
                var finish = function(err) {
                    self.client = client;
                    self.isConnected = true;

                    self.events = new mongo.Collection(client, self.options.eventsCollectionName);
                    self.ensureIndex(self.options.eventsCollectionName, {streamId: 1}, {})
                    self.snapshots = new mongo.Collection(client, self.options.snapshotsCollectionName);
                    self.ensureIndex(self.options.snapshotsCollectionName, {streamId: 1}, {})
                    self.transactions = new mongo.Collection(client, self.options.transactionsCollectionName);

                    if (callback) callback(err, self);
                };

                if (self.options.username) {
                    client.authenticate(self.options.username, self.options.password, finish);
                } else {
                    finish();
                }
            }
        });
    },

    ensureIndex: function(collectionName, index, options, callback) {
        if (!this.isConnected) return;

        this.client.ensureIndex(self.collectionName, index, options, function(err, indexName) {
            if (callback) callback(err, indexName);
        });
    }

    // __addEvents:__ saves all events.
    //
    // `storage.addEvents(events, callback)`
    //
    // - __events:__ the events array
    // - __callback:__ `function(err){}`
    addEvents: function(events, callback) {
        for (var i in events) {
            events[i]._id = events[i].commitId + events[i].commitSequence;
            events[i].dispatched = false;
        }

        var self = this;

        if (events.length > 1) {
            var tx = {
                _id: events[0].commitId,
                events: events
            };
            this.transactions.insert(tx, {keepGoing: true}, function(err) {
                self.events.insert(events, {keepGoing: true}, function(err) {
                    self.transactions.remove({ _id: tx._id }, function(err) {});
                    if (callback) { callback(err); }
                });
            });
        } else {
            this.events.insert(events, {keepGoing: true}, callback);
        }
    },

    // __addSnapshot:__ stores the snapshot
    //
    // `storage.addSnapshot(snapshot, callback)`
    //
    // - __snapshot:__ the snaphot to store
    // - __callback:__ `function(err){}` [optional]
    addSnapshot: function(snapshot, callback) {
        snapshot._id = snapshot.snapshotId;
        this.snapshots.insert(snapshot, callback);
    },

    // __getEvents:__ loads the events from _minRev_ to _maxRev_.
    //
    // `storage.getEvents(streamId, minRev, maxRev, callback)`
    //
    // - __streamId:__ id for requested stream
    // - __minRev:__ revision startpoint
    // - __maxRev:__ revision endpoint (hint: -1 = to end) [optional]
    // - __callback:__ `function(err, events){}`
    getEvents: function(streamId, minRev, maxRev, callback) {

        if (typeof maxRev === 'function') {
            callback = maxRev;
            maxRev = -1;
        }

        var options = {'$gte':minRev, '$lt':maxRev};
        if (maxRev == -1) options = {'$gte':minRev};

        var findStatement = {
            'streamId' : streamId,
            'streamRevision': options
        };

        var self = this;

        this.events.find(findStatement, {sort:[['streamRevision','asc']]}).toArray(function(err, res) {
            if (maxRev != -1 || !res || res.length === 0) {
                return callback(err, res);
            }

            var lastEvt = res[res.length - 1];

            if (lastEvt.restInCommitStream === 0 || !lastEvt.restInCommitStream) {
                callback(err, res);
                self.transactions.remove({ _id: lastEvt.commitId }, function(err) {});
                return;
            }

            self.transactions.findOne({ _id: lastEvt.commitId }, function(err, tx) {
                if (!tx) {
                    return callback(err, res);
                }

                var missingEvts = tx.events.slice(tx.events.length - lastEvt.restInCommitStream);

                self.events.insert(missingEvts, {keepGoing: true}, function(err) {
                    self.transactions.remove({ _id: tx._id }, function(err) {});
                    self.getEvents(streamId, minRev, maxRev, callback);
                });
            });
        });
    },

    // __getEventRange:__ loads the range of events from given storage.
    //
    // `storage.getEventRange(match, amount, callback)`
    //
    // - __match:__ match query in inner event (payload)
    // - __amount:__ amount of events
    // - __callback:__ `function(err, events){}`
    getEventRange: function(match, amount, callback) {
        var self = this;
        var query = {};

        if (match) {
            for (var m in match) {
                if (match.hasOwnProperty(m)) {

                    query['payload.' + m] = match[m];

                    break;
                }
            }
        }

        this.events.findOne(query, function(err, evt) {

            self.events.find({
                'commitStamp': {'$gte': evt.commitStamp},
                '$or': [
                    { 'streamId': {'$ne': evt.streamId}},
                    {'commitId': {'$ne': evt.commitId}} ]},
                {sort:[['commitStamp','asc']], limit: amount}).toArray(callback);

        });
    },

    // __getEvents:__ loads the events from _minRev_ to _maxRev_.
    //
    // `storage.getAllEvents(from, amount, callback)`
    //
    // - __from:__ from entry index [optional, default 0]
    // - __amount:__ amount of results (hint: -1 = to end) [optional]
    // - __callback:__ `function(err, events){}`
    getAllEvents: function(from, amount, callback) {

        if (typeof amount === 'function') {
            callback = amount;
            amount = -1;
        }

        if (typeof from === 'function') {
            callback = from;
            from = 0;
            amount = -1;
        }

        if (amount === -1) {
            return this.events.find({}, {sort:[['commitStamp','asc']]}).skip(from).toArray(callback);
        }

        this.events.find({}, {sort:[['commitStamp','asc']]}).skip(from).limit(amount).toArray(callback);
    },

    // __getSnapshot:__ loads the next snapshot back from given max revision or the latest if you
    // don't pass in a _maxRev_.
    //
    // `storage.getSnapshot(streamId, maxRev, callback)`
    //
    // - __streamId:__ id for requested stream
    // - __maxRev:__ revision endpoint (hint: -1 = to end)
    // - __callback:__ `function(err, snapshot){}`
    getSnapshot: function(streamId, maxRev, callback) {

        if (typeof maxRev === 'function') {
            callback = maxRev;
            maxRev = -1;
        }

        var findStatement = {'streamId' : streamId};
        if (maxRev > -1) findStatement = { 'streamId' : streamId, 'revision': {'$lte':maxRev} };

        this.snapshots.find(findStatement, {sort:[['revision','desc']], limit: 1}).toArray(function(err, snapshots) {
            if (err) {
                callback(err);
            } else {
                snapshots.length > 0 ? callback(null, snapshots[0]) : callback(null, {});
            }
        });
    },

    // __getUndispatchedEvents:__ loads all undispatched events.
    //
    // `storage.getUndispatchedEvents(callback)`
    //
    // - __callback:__ `function(err, events){}`
    getUndispatchedEvents: function(callback) {
        this.events.find({'dispatched' : false}, {sort:[['streamId','asc'], ['streamRevision','asc']]}).toArray(callback);
    },

    // __setEventToDispatched:__ sets the given event to dispatched.
    //
    // __hint:__ instead of the whole event object you can pass: {_id: 'commitId'}
    //
    // `storage.setEventToDispatched(event, callback)`
    //
    // - __event:__ the event
    // - __callback:__ `function(err, events){}` [optional]
    setEventToDispatched: function(event, callback) {
        var updateCommand = { '$set' : {'dispatched': true} };
        this.events.update({'_id' : event._id}, updateCommand, callback);
    },

    // __getId:__ loads a new id from storage.
    //
    // `storage.getId(callback)`
    //
    // - __callback:__ `function(err, id){}`
    getId: function(callback) {
        callback(null, new ObjectID().toString());
    }
};

// helper
var mergeOptions = function(options, defaultOptions) {
    if (!options || typeof options === 'function') {
        return defaultOptions;
    }

    var merged = {};
    for (var attrname in defaultOptions) { merged[attrname] = defaultOptions[attrname]; }
    for (attrname in options) { if (options[attrname]) merged[attrname] = options[attrname]; }
    return merged;
};
<commit_msg>fixes missing ,<commit_after>//     storage.js v0.5.0
//     (c)(by) Jan Muehlemann (jamuhl)
//        , Adriano Raiano (adrai)

// The storage is the database driver for mongoDb.
//
// __Example:__
//
//      require('[pathToStorage]/storage').createStorage({}, function(err, storage) {
//          ...
//      });

var mongo = require('mongodb')
  , tolerate = require('tolerance')
  , ObjectID = mongo.BSONPure.ObjectID
  , root = this
  , mongoDbStorage
  , Storage;

if (typeof exports !== 'undefined') {
    mongoDbStorage = exports;
} else {
    mongoDbStorage = root.mongoDbStorage = {};
}

mongoDbStorage.VERSION = '0.6.1';

// Create new instance of storage.
mongoDbStorage.createStorage = function(options, callback) {
    return new Storage(options, callback);
};

// ## MongoDb storage
Storage = function(options, callback) {

    this.filename = __filename;
    this.isConnected = false;

    if (typeof options === 'function')
        callback = options;

    var defaults = {
        host: 'localhost',
        port: 27017,
        dbName: 'eventstore',
        eventsCollectionName: 'events',
        snapshotsCollectionName: 'snapshots',
        transactionsCollectionName: 'transactions'
    };

    this.options = mergeOptions(options, defaults);

    var defaultOpt = {
        auto_reconnect: true,
        ssl: false
    };

    this.options.options = this.options.options || {};

    this.options.options = mergeOptions(this.options.options, defaultOpt);

    if (callback) {
        this.connect(callback);
    }
};

Storage.prototype = {

    // __connect:__ connects the underlaying database.
    //
    // `storage.connect(callback)`
    //
    // - __callback:__ `function(err, storage){}`
    connect: function(callback) {
        var self = this;

        tolerate(function(callback) {
            var server = new mongo.Server(self.options.host, self.options.port, self.options.options);
            new mongo.Db(self.options.dbName , server, { safe: true }).open(callback);
        }, this.options.timeout || 0, function(err, client) {
            if (err) {
                if (callback) callback(err);
            } else {
                var finish = function(err) {
                    self.client = client;
                    self.isConnected = true;

                    self.events = new mongo.Collection(client, self.options.eventsCollectionName);
                    self.ensureIndex(self.options.eventsCollectionName, {streamId: 1}, {})
                    self.snapshots = new mongo.Collection(client, self.options.snapshotsCollectionName);
                    self.ensureIndex(self.options.snapshotsCollectionName, {streamId: 1}, {})
                    self.transactions = new mongo.Collection(client, self.options.transactionsCollectionName);

                    if (callback) callback(err, self);
                };

                if (self.options.username) {
                    client.authenticate(self.options.username, self.options.password, finish);
                } else {
                    finish();
                }
            }
        });
    },

    ensureIndex: function(collectionName, index, options, callback) {
        if (!this.isConnected) return;

        this.client.ensureIndex(self.collectionName, index, options, function(err, indexName) {
            if (callback) callback(err, indexName);
        });
    },

    // __addEvents:__ saves all events.
    //
    // `storage.addEvents(events, callback)`
    //
    // - __events:__ the events array
    // - __callback:__ `function(err){}`
    addEvents: function(events, callback) {
        for (var i in events) {
            events[i]._id = events[i].commitId + events[i].commitSequence;
            events[i].dispatched = false;
        }

        var self = this;

        if (events.length > 1) {
            var tx = {
                _id: events[0].commitId,
                events: events
            };
            this.transactions.insert(tx, {keepGoing: true}, function(err) {
                self.events.insert(events, {keepGoing: true}, function(err) {
                    self.transactions.remove({ _id: tx._id }, function(err) {});
                    if (callback) { callback(err); }
                });
            });
        } else {
            this.events.insert(events, {keepGoing: true}, callback);
        }
    },

    // __addSnapshot:__ stores the snapshot
    //
    // `storage.addSnapshot(snapshot, callback)`
    //
    // - __snapshot:__ the snaphot to store
    // - __callback:__ `function(err){}` [optional]
    addSnapshot: function(snapshot, callback) {
        snapshot._id = snapshot.snapshotId;
        this.snapshots.insert(snapshot, callback);
    },

    // __getEvents:__ loads the events from _minRev_ to _maxRev_.
    //
    // `storage.getEvents(streamId, minRev, maxRev, callback)`
    //
    // - __streamId:__ id for requested stream
    // - __minRev:__ revision startpoint
    // - __maxRev:__ revision endpoint (hint: -1 = to end) [optional]
    // - __callback:__ `function(err, events){}`
    getEvents: function(streamId, minRev, maxRev, callback) {

        if (typeof maxRev === 'function') {
            callback = maxRev;
            maxRev = -1;
        }

        var options = {'$gte':minRev, '$lt':maxRev};
        if (maxRev == -1) options = {'$gte':minRev};

        var findStatement = {
            'streamId' : streamId,
            'streamRevision': options
        };

        var self = this;

        this.events.find(findStatement, {sort:[['streamRevision','asc']]}).toArray(function(err, res) {
            if (maxRev != -1 || !res || res.length === 0) {
                return callback(err, res);
            }

            var lastEvt = res[res.length - 1];

            if (lastEvt.restInCommitStream === 0 || !lastEvt.restInCommitStream) {
                callback(err, res);
                self.transactions.remove({ _id: lastEvt.commitId }, function(err) {});
                return;
            }

            self.transactions.findOne({ _id: lastEvt.commitId }, function(err, tx) {
                if (!tx) {
                    return callback(err, res);
                }

                var missingEvts = tx.events.slice(tx.events.length - lastEvt.restInCommitStream);

                self.events.insert(missingEvts, {keepGoing: true}, function(err) {
                    self.transactions.remove({ _id: tx._id }, function(err) {});
                    self.getEvents(streamId, minRev, maxRev, callback);
                });
            });
        });
    },

    // __getEventRange:__ loads the range of events from given storage.
    //
    // `storage.getEventRange(match, amount, callback)`
    //
    // - __match:__ match query in inner event (payload)
    // - __amount:__ amount of events
    // - __callback:__ `function(err, events){}`
    getEventRange: function(match, amount, callback) {
        var self = this;
        var query = {};

        if (match) {
            for (var m in match) {
                if (match.hasOwnProperty(m)) {

                    query['payload.' + m] = match[m];

                    break;
                }
            }
        }

        this.events.findOne(query, function(err, evt) {

            self.events.find({
                'commitStamp': {'$gte': evt.commitStamp},
                '$or': [
                    { 'streamId': {'$ne': evt.streamId}},
                    {'commitId': {'$ne': evt.commitId}} ]},
                {sort:[['commitStamp','asc']], limit: amount}).toArray(callback);

        });
    },

    // __getEvents:__ loads the events from _minRev_ to _maxRev_.
    //
    // `storage.getAllEvents(from, amount, callback)`
    //
    // - __from:__ from entry index [optional, default 0]
    // - __amount:__ amount of results (hint: -1 = to end) [optional]
    // - __callback:__ `function(err, events){}`
    getAllEvents: function(from, amount, callback) {

        if (typeof amount === 'function') {
            callback = amount;
            amount = -1;
        }

        if (typeof from === 'function') {
            callback = from;
            from = 0;
            amount = -1;
        }

        if (amount === -1) {
            return this.events.find({}, {sort:[['commitStamp','asc']]}).skip(from).toArray(callback);
        }

        this.events.find({}, {sort:[['commitStamp','asc']]}).skip(from).limit(amount).toArray(callback);
    },

    // __getSnapshot:__ loads the next snapshot back from given max revision or the latest if you
    // don't pass in a _maxRev_.
    //
    // `storage.getSnapshot(streamId, maxRev, callback)`
    //
    // - __streamId:__ id for requested stream
    // - __maxRev:__ revision endpoint (hint: -1 = to end)
    // - __callback:__ `function(err, snapshot){}`
    getSnapshot: function(streamId, maxRev, callback) {

        if (typeof maxRev === 'function') {
            callback = maxRev;
            maxRev = -1;
        }

        var findStatement = {'streamId' : streamId};
        if (maxRev > -1) findStatement = { 'streamId' : streamId, 'revision': {'$lte':maxRev} };

        this.snapshots.find(findStatement, {sort:[['revision','desc']], limit: 1}).toArray(function(err, snapshots) {
            if (err) {
                callback(err);
            } else {
                snapshots.length > 0 ? callback(null, snapshots[0]) : callback(null, {});
            }
        });
    },

    // __getUndispatchedEvents:__ loads all undispatched events.
    //
    // `storage.getUndispatchedEvents(callback)`
    //
    // - __callback:__ `function(err, events){}`
    getUndispatchedEvents: function(callback) {
        this.events.find({'dispatched' : false}, {sort:[['streamId','asc'], ['streamRevision','asc']]}).toArray(callback);
    },

    // __setEventToDispatched:__ sets the given event to dispatched.
    //
    // __hint:__ instead of the whole event object you can pass: {_id: 'commitId'}
    //
    // `storage.setEventToDispatched(event, callback)`
    //
    // - __event:__ the event
    // - __callback:__ `function(err, events){}` [optional]
    setEventToDispatched: function(event, callback) {
        var updateCommand = { '$set' : {'dispatched': true} };
        this.events.update({'_id' : event._id}, updateCommand, callback);
    },

    // __getId:__ loads a new id from storage.
    //
    // `storage.getId(callback)`
    //
    // - __callback:__ `function(err, id){}`
    getId: function(callback) {
        callback(null, new ObjectID().toString());
    }
};

// helper
var mergeOptions = function(options, defaultOptions) {
    if (!options || typeof options === 'function') {
        return defaultOptions;
    }

    var merged = {};
    for (var attrname in defaultOptions) { merged[attrname] = defaultOptions[attrname]; }
    for (attrname in options) { if (options[attrname]) merged[attrname] = options[attrname]; }
    return merged;
};
<|endoftext|>


<commit_before>var LayoutAnimation = require('react-native').LayoutAnimation;
var DEFAULT_ANIMATION = 'linear';

var animations = {
  layout: {
    spring: {
      duration: 500,
      create: {
        duration: 300,
        type: LayoutAnimation.Types.easeInEaseOut,
        property: LayoutAnimation.Properties.opacity,
      },
      update: {
        type: LayoutAnimation.Types.spring,
        springDamping: 0.7,
      },
    },
    linear: {
      duration: 300,
      create: {
        type: LayoutAnimation.Types.linear,
      },
      update: {
        type: LayoutAnimation.Types.linear,
        springDamping: 0.7,
      },
    },
    easeInEaseOut: {
      duration: 300,
      create: {
        type: LayoutAnimation.Types.easeInEaseOut,
        property: LayoutAnimation.Properties.scaleXY,
      },
      update: {
        delay: 100,
        type: LayoutAnimation.Types.easeInEaseOut,
      },
    },
  },
};

var layoutAnimationConfigs = {
  'spring': animations.layout.spring,
  'linear': animations.layout.linear,
  'easeInOut': animations.layout.easeInEaseOut,
};

module.exports = function(animation) {
  var _animation = layoutAnimationConfigs[animation];
  if (!_animation) {
    _animation = layoutAnimationConfigs[DEFAULT_ANIMATION];
  }

  LayoutAnimation.configureNext(_animation);
}<commit_msg>Changes proposed to remove the createConfig error<commit_after>var LayoutAnimation = require('react-native').LayoutAnimation;
var DEFAULT_ANIMATION = 'linear';

var animations = {
  layout: {
    spring: {
      duration: 500,
      create: {
        duration: 300,
        type: LayoutAnimation.Types.easeInEaseOut,
        property: LayoutAnimation.Properties.opacity,
      },
      update: {
        type: LayoutAnimation.Types.spring,
        springDamping: 0.7,
        property: LayoutAnimation.Properties.opacity,
      },
    },
    linear: {
      duration: 300,
      create: {
        type: LayoutAnimation.Types.linear,
        property: LayoutAnimation.Properties.opacity,
      },
      update: {
        type: LayoutAnimation.Types.linear,
        springDamping: 0.7,
        property: LayoutAnimation.Properties.opacity,
      },
    },
    easeInEaseOut: {
      duration: 300,
      create: {
        type: LayoutAnimation.Types.easeInEaseOut,
        property: LayoutAnimation.Properties.scaleXY,
      },
      update: {
        delay: 100,
        type: LayoutAnimation.Types.easeInEaseOut,
        property: LayoutAnimation.Properties.opacity,
      },
    },
  },
};

var layoutAnimationConfigs = {
  'spring': animations.layout.spring,
  'linear': animations.layout.linear,
  'easeInOut': animations.layout.easeInEaseOut,
};

module.exports = function(animation) {
  var _animation = layoutAnimationConfigs[animation];
  if (!_animation) {
    _animation = layoutAnimationConfigs[DEFAULT_ANIMATION];
  }

  LayoutAnimation.configureNext(_animation);
}
<|endoftext|>


<commit_before>/* global cozy */
import { getList, createFetchAction, createFetchIfNeededAction, createUpdateAction, insertAction, deleteAction } from '../lists'
import Toolbar from './components/Toolbar'
import DeleteConfirm from './components/DeleteConfirm'
import { hideSelectionBar, getSelectedIds } from '../selection'
import { FILE_DOCTYPE, FETCH_LIMIT, ALBUM_DOCTYPE } from '../../constants/config'

// constants
const TIMELINE = 'timeline'
const DEFAULT_COUCH_SELECTOR = {
  class: 'image',
  trashed: false
}

// selectors
export const getTimelineList = state => getList(state, TIMELINE)
export const isRelated = state => {
  const ids = getSelectedIds(state)
  const list = getTimelineList(state)
  if (list) {
    for (const id of ids) {
      for (const photo of list.entries) {
        if (photo._id === id && photo.relationships && photo.relationships.referenced_by && photo.relationships.referenced_by.data && photo.relationships.referenced_by.data.length > 0) {
          const refs = photo.relationships.referenced_by.data
          for (const ref of refs) {
            if (ref.type === ALBUM_DOCTYPE) {
              return true
            }
          }
        }
      }
    }
  }
  return false
}

// components
export { Toolbar }
export { DeleteConfirm }

// async actions
export const addPhotosToTimeline = photos => async dispatch => {
  dispatch(insertAction(TIMELINE, { entries: photos }))
}

export const deletePhotos = ids => async dispatch => {
  for (const id of ids) {
    try {
      await cozy.client.files.trashById(id)
      dispatch(deleteAction(TIMELINE, id))
      const file = await cozy.client.data.find(FILE_DOCTYPE, id)
      for (const ref of file.referenced_by) {
        if (ref.type === ALBUM_DOCTYPE) {
          await cozy.client.data.removeReferencedFiles({ _id: ref.id, _type: ref.type }, id)
        }
      }
    } catch (e) {
      console.log(e)
    }
    dispatch(hideSelectionBar())
  }
}

// list
const indexFilesByDate = async () => {
  const fields = [ 'class', 'trashed', 'metadata.datetime' ]
  return await cozy.client.data.defineIndex(FILE_DOCTYPE, fields)
}

const fetchPhotos = async (index, skip = 0, selector = DEFAULT_COUCH_SELECTOR) => {
  const options = {
    selector,
    // TODO: type and class should not be necessary, it's just a temp fix for a stack bug
    fields: ['_id', 'dir_id', 'name', 'size', 'updated_at', 'metadata', 'type', 'class'],
    descending: true,
    limit: FETCH_LIMIT,
    skip,
    wholeResponse: true
  }
  const { data, meta } = await cozy.client.files.query(index, options)
  return {
    entries: data.map(p => Object.assign({ _id: p.id }, p, p.attributes)),
    next: meta.count > skip + FETCH_LIMIT,
    index,
    skip
  }
}

export const fetchIfNeededPhotos = createFetchIfNeededAction(TIMELINE, (index, skip = 0) => {
  return index
    ? fetchPhotos(index, skip)
    : indexFilesByDate().then(index => fetchPhotos(index, skip))
})

export const fetchMorePhotos = createFetchAction(TIMELINE, fetchPhotos)

/**
* Updates a collection of photos based on their id
*/
export const refetchSomePhotos = createUpdateAction(TIMELINE, async (photos) => {
  let index = await indexFilesByDate()
  let selector = {
    ...DEFAULT_COUCH_SELECTOR,
    '_id': {
      '$in': photos
    }
  }
  let response = await fetchPhotos(index, 0, selector)
  return response
})

export const getPhotosByMonth = (photos, f, format) => {
  let sections = {}
  photos.forEach(p => {
    const datetime = p.metadata && p.metadata.datetime ? p.metadata.datetime : Date.now()
    // here we want to get an object whose keys are months in a l10able format
    // so we only keep the year and month part of the date
    const month = datetime.slice(0, 7) + '-01T00:00'
    /* istanbul ignore else */
    if (!sections.hasOwnProperty(month)) {
      sections[month] = []
    }
    sections[month].push(p)
  })
  // we need to sort the months here because when new photos are uploaded, they
  // are inserted on top of the list, and months can become unordered
  const sortedMonths = Object.keys(sections).sort(
    (a, b) => new Date(a).getTime() - new Date(b).getTime()
  ).reverse()

  return sortedMonths.map(month => {
    return {
      title: f(month, format),
      photos: sections[month]
    }
  })
}
<commit_msg>fix: better variable declarations<commit_after>/* global cozy */
import { getList, createFetchAction, createFetchIfNeededAction, createUpdateAction, insertAction, deleteAction } from '../lists'
import Toolbar from './components/Toolbar'
import DeleteConfirm from './components/DeleteConfirm'
import { hideSelectionBar, getSelectedIds } from '../selection'
import { FILE_DOCTYPE, FETCH_LIMIT, ALBUM_DOCTYPE } from '../../constants/config'

// constants
const TIMELINE = 'timeline'
const DEFAULT_COUCH_SELECTOR = {
  class: 'image',
  trashed: false
}

// selectors
export const getTimelineList = state => getList(state, TIMELINE)
export const isRelated = state => {
  const ids = getSelectedIds(state)
  const list = getTimelineList(state)
  if (list) {
    for (const id of ids) {
      for (const photo of list.entries) {
        if (photo._id === id && photo.relationships && photo.relationships.referenced_by && photo.relationships.referenced_by.data && photo.relationships.referenced_by.data.length > 0) {
          const refs = photo.relationships.referenced_by.data
          for (const ref of refs) {
            if (ref.type === ALBUM_DOCTYPE) {
              return true
            }
          }
        }
      }
    }
  }
  return false
}

// components
export { Toolbar }
export { DeleteConfirm }

// async actions
export const addPhotosToTimeline = photos => async dispatch => {
  dispatch(insertAction(TIMELINE, { entries: photos }))
}

export const deletePhotos = ids => async dispatch => {
  for (const id of ids) {
    try {
      await cozy.client.files.trashById(id)
      dispatch(deleteAction(TIMELINE, id))
      const file = await cozy.client.data.find(FILE_DOCTYPE, id)
      for (const ref of file.referenced_by) {
        if (ref.type === ALBUM_DOCTYPE) {
          await cozy.client.data.removeReferencedFiles({ _id: ref.id, _type: ref.type }, id)
        }
      }
    } catch (e) {
      console.log(e)
    }
    dispatch(hideSelectionBar())
  }
}

// list
const indexFilesByDate = async () => {
  const fields = [ 'class', 'trashed', 'metadata.datetime' ]
  return await cozy.client.data.defineIndex(FILE_DOCTYPE, fields)
}

const fetchPhotos = async (index, skip = 0, selector = DEFAULT_COUCH_SELECTOR) => {
  const options = {
    selector,
    // TODO: type and class should not be necessary, it's just a temp fix for a stack bug
    fields: ['_id', 'dir_id', 'name', 'size', 'updated_at', 'metadata', 'type', 'class'],
    descending: true,
    limit: FETCH_LIMIT,
    skip,
    wholeResponse: true
  }
  const { data, meta } = await cozy.client.files.query(index, options)
  return {
    entries: data.map(p => Object.assign({ _id: p.id }, p, p.attributes)),
    next: meta.count > skip + FETCH_LIMIT,
    index,
    skip
  }
}

export const fetchIfNeededPhotos = createFetchIfNeededAction(TIMELINE, (index, skip = 0) => {
  return index
    ? fetchPhotos(index, skip)
    : indexFilesByDate().then(index => fetchPhotos(index, skip))
})

export const fetchMorePhotos = createFetchAction(TIMELINE, fetchPhotos)

/**
* Updates a collection of photos based on their id
*/
export const refetchSomePhotos = createUpdateAction(TIMELINE, async (photos) => {
  const index = await indexFilesByDate()
  const selector = {
    ...DEFAULT_COUCH_SELECTOR,
    '_id': {
      '$in': photos
    }
  }
  return await fetchPhotos(index, 0, selector)
})

export const getPhotosByMonth = (photos, f, format) => {
  let sections = {}
  photos.forEach(p => {
    const datetime = p.metadata && p.metadata.datetime ? p.metadata.datetime : Date.now()
    // here we want to get an object whose keys are months in a l10able format
    // so we only keep the year and month part of the date
    const month = datetime.slice(0, 7) + '-01T00:00'
    /* istanbul ignore else */
    if (!sections.hasOwnProperty(month)) {
      sections[month] = []
    }
    sections[month].push(p)
  })
  // we need to sort the months here because when new photos are uploaded, they
  // are inserted on top of the list, and months can become unordered
  const sortedMonths = Object.keys(sections).sort(
    (a, b) => new Date(a).getTime() - new Date(b).getTime()
  ).reverse()

  return sortedMonths.map(month => {
    return {
      title: f(month, format),
      photos: sections[month]
    }
  })
}
<|endoftext|>


<commit_before>//Copyright 2015 Kyle Smith
//This is an example config for node-steam-profilecheck
//This is a module that checks steam API and optionally steamrep for scammers and private profiles
//If a user adds the provided with a scammer, private profile, no community profile the request is denied
//Minimal documentation is available here
//For more detailed documentation, please visit the GitHub wiki
//https://github.com/dragonbanshee/node-steam-profilecheck

var ProfileCheck = require('../'); //change to steam-profilecheck if not running from same directory

var Bot = new ProfileCheck('username', 'password', { //enter username and password here
	guardCode: '55QKD', //steam-guard code, comment out when sentry file is generated

	//General profile options
	gamesPlayed: [440], //array of appid integers for the bot to idle in
	sentryfile: 'username.sentry', //the filename of the sentry file containing the steamguard information
	steamrep: true, //whether to check steamrep for scammer status

	//Logger options, optional
	log_colorize: true, //whether to color the logs
	log_timestamp: true, //whether to inclue timestamps in the console
});

Bot.connect(); //call connect on your Bot object to connect to steam and login <commit_msg>Remove steamguard code, oops<commit_after>//Copyright 2015 Kyle Smith
//This is an example config for node-steam-profilecheck
//This is a module that checks steam API and optionally steamrep for scammers and private profiles
//If a user adds the provided with a scammer, private profile, no community profile the request is denied
//Minimal documentation is available here
//For more detailed documentation, please visit the GitHub wiki
//https://github.com/dragonbanshee/node-steam-profilecheck

var ProfileCheck = require('../'); //change to steam-profilecheck if not running from same directory

var Bot = new ProfileCheck('username', 'password', { //enter username and password here
	guardCode: 'XXXXX', //steam-guard code, comment out when sentry file is generated

	//General profile options
	gamesPlayed: [440], //array of appid integers for the bot to idle in
	sentryfile: 'username.sentry', //the filename of the sentry file containing the steamguard information
	steamrep: true, //whether to check steamrep for scammer status

	//Logger options, optional
	log_colorize: true, //whether to color the logs
	log_timestamp: true, //whether to inclue timestamps in the console
});

Bot.connect(); //call connect on your Bot object to connect to steam and login
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { auth as withAuth, withRouter, styled, withLangProvider, SimpleSwitch, SimpleRoute } from 'olymp';
import { withLocale } from 'olymp/locale-de';
import { ThemeProvider } from 'olymp-fela';
import { HashtaxProvider } from 'hashtax';
import { NavigationVertical } from './navigation';
import { AuthModals } from 'olymp/auth';
import { GatewayDest } from 'react-gateway';
import { EditablePageRoute, PageRoute, withNavigation } from './pages';
import { CollectionRoute } from './collection';
import { CloudinaryRoute, LightboxProvider, Lightbox } from './cloudinary';
// import { AnalyticsRoute } from './analytics';
import { SettingsRoute } from './settings';
import { TemplateRoute, withTemplates } from './templates';
import * as LANG from './lang/de';

export const Container = styled(({ deviceWidth }) => ({
  display: 'flex',
  height: '100%',
  '> :last-child': {
    flex: 1,
  },
  '> *': {
    overflowY: 'auto',
  },
}), 'div', ({ deviceWidth, ...p }) => p);

export default ({ auth, theme, hashtax, modules }) => (Wrapped) => {
  // Container for authed users
  const IfAuth = (props) => {
    const { query, templates, collections, location } = props;
    const collection = Object.keys(modules).filter(key => query[`@${key}`] !== undefined).map(key => ({ key, ...modules[key] }))[0];

    return (
      <ThemeProvider theme={theme}>
        <HashtaxProvider {...hashtax} components={{ ...hashtax.components, ...templates }}>
          <LightboxProvider>
            <Container>
              <Lightbox />
              <GatewayDest name="modal" />
              <AuthModals />
              <NavigationVertical collections={collections} deviceWidth={query[`@deviceWidth`]} {...location} location={location} />
              <SimpleSwitch>
                {/*<SimpleRoute match={query['@profile'] !== undefined} render={() => <AuthRoutes.SplitView.Profile prefix="@" />} />*/}
                {/*<SimpleRoute match={query[`@users`] !== undefined} render={() => <AuthRoutes.SplitView.Users prefix="@" />} />*/}
                <SimpleRoute match={query[`@template`] !== undefined} render={() => <TemplateRoute {...props} />} />
                <SimpleRoute match={!!collection} render={() => <CollectionRoute {...props} modules={modules} collection={collection} Wrapped={Wrapped} />} />
                <SimpleRoute match={query[`@page`] !== undefined} render={() => <EditablePageRoute {...props} Wrapped={Wrapped} />} />
                <SimpleRoute match={query[`@media`] !== undefined} render={() => <CloudinaryRoute {...props} />} />
                {/*<SimpleRoute match={query[`@stats`] !== undefined} render={() => <AnalyticsRoute {...props} />} />*/}
                <SimpleRoute match={query[`@settings`] !== undefined} render={() => <SettingsRoute {...props} />} />
                <SimpleRoute render={() => <PageRoute {...props} Wrapped={Wrapped} />} />
              </SimpleSwitch>
            </Container>
          </LightboxProvider>
        </HashtaxProvider>
      </ThemeProvider>
    );
  };

  // Container for non-authed users
  const NoAuth = (props) => {
    const { templates } = props;
    return (
      <ThemeProvider theme={theme}>
        <HashtaxProvider {...hashtax} components={{ ...hashtax.components, ...templates }}>
          <LightboxProvider>

              <Lightbox />
              <AuthModals />
              <GatewayDest name="modal" />
              <PageRoute {...props} Wrapped={Wrapped} />

          </LightboxProvider>
        </HashtaxProvider>
      </ThemeProvider>
    );
  };

  @withRouter
  @withLocale
  @withAuth(auth)
  @withNavigation
  @withLangProvider(LANG)
  @withTemplates
  class CMS extends Component {
    render() {
      const { auth } = this.props;
      /*const routes = flatNavigation.filter(x => x.slug).map(({ id, slug, binding, pageId, bindingId }) => (
        <DataRoute key={id} id={pageId || id} bindingId={bindingId} binding={binding} match={pathname === slug} component={PageSidebar} location={location} navigation={navigation} flatNavigation={flatNavigation} />
      ));*/
      if (!auth.user) {
        return <NoAuth {...this.props} />;
      } return <IfAuth {...this.props} />;
    }
  } return CMS;
};

<commit_msg>fix cms style<commit_after>import React, { Component } from 'react';
import { auth as withAuth, withRouter, styled, withLangProvider, SimpleSwitch, SimpleRoute } from 'olymp';
import { withLocale } from 'olymp/locale-de';
import { ThemeProvider } from 'olymp-fela';
import { HashtaxProvider } from 'hashtax';
import { NavigationVertical } from './navigation';
import { AuthModals } from 'olymp/auth';
import { GatewayDest } from 'react-gateway';
import { EditablePageRoute, PageRoute, withNavigation } from './pages';
import { CollectionRoute } from './collection';
import { CloudinaryRoute, LightboxProvider, Lightbox } from './cloudinary';
// import { AnalyticsRoute } from './analytics';
import { SettingsRoute } from './settings';
import { TemplateRoute, withTemplates } from './templates';
import * as LANG from './lang/de';

export const Container = styled(({ deviceWidth }) => ({
  display: 'flex',
  height: '100%',
  '> :last-child': {
    flex: 1,
    minHeight: '100%',
  },
  '> *': {
    overflowY: 'auto',
  },
}), 'div', ({ deviceWidth, ...p }) => p);

export default ({ auth, theme, hashtax, modules }) => (Wrapped) => {
  // Container for authed users
  const IfAuth = (props) => {
    const { query, templates, collections, location } = props;
    const collection = Object.keys(modules).filter(key => query[`@${key}`] !== undefined).map(key => ({ key, ...modules[key] }))[0];

    return (
      <ThemeProvider theme={theme}>
        <HashtaxProvider {...hashtax} components={{ ...hashtax.components, ...templates }}>
          <LightboxProvider>
            <Container>
              <Lightbox />
              <GatewayDest name="modal" />
              <AuthModals />
              <NavigationVertical collections={collections} deviceWidth={query[`@deviceWidth`]} {...location} location={location} />
              <SimpleSwitch>
                {/*<SimpleRoute match={query['@profile'] !== undefined} render={() => <AuthRoutes.SplitView.Profile prefix="@" />} />*/}
                {/*<SimpleRoute match={query[`@users`] !== undefined} render={() => <AuthRoutes.SplitView.Users prefix="@" />} />*/}
                <SimpleRoute match={query[`@template`] !== undefined} render={() => <TemplateRoute {...props} />} />
                <SimpleRoute match={!!collection} render={() => <CollectionRoute {...props} modules={modules} collection={collection} Wrapped={Wrapped} />} />
                <SimpleRoute match={query[`@page`] !== undefined} render={() => <EditablePageRoute {...props} Wrapped={Wrapped} />} />
                <SimpleRoute match={query[`@media`] !== undefined} render={() => <CloudinaryRoute {...props} />} />
                {/*<SimpleRoute match={query[`@stats`] !== undefined} render={() => <AnalyticsRoute {...props} />} />*/}
                <SimpleRoute match={query[`@settings`] !== undefined} render={() => <SettingsRoute {...props} />} />
                <SimpleRoute render={() => <PageRoute {...props} Wrapped={Wrapped} />} />
              </SimpleSwitch>
            </Container>
          </LightboxProvider>
        </HashtaxProvider>
      </ThemeProvider>
    );
  };

  // Container for non-authed users
  const NoAuth = (props) => {
    const { templates } = props;
    return (
      <ThemeProvider theme={theme}>
        <HashtaxProvider {...hashtax} components={{ ...hashtax.components, ...templates }}>
          <LightboxProvider>

              <Lightbox />
              <AuthModals />
              <GatewayDest name="modal" />
              <PageRoute {...props} Wrapped={Wrapped} />

          </LightboxProvider>
        </HashtaxProvider>
      </ThemeProvider>
    );
  };

  @withRouter
  @withLocale
  @withAuth(auth)
  @withNavigation
  @withLangProvider(LANG)
  @withTemplates
  class CMS extends Component {
    render() {
      const { auth } = this.props;
      /*const routes = flatNavigation.filter(x => x.slug).map(({ id, slug, binding, pageId, bindingId }) => (
        <DataRoute key={id} id={pageId || id} bindingId={bindingId} binding={binding} match={pathname === slug} component={PageSidebar} location={location} navigation={navigation} flatNavigation={flatNavigation} />
      ));*/
      if (!auth.user) {
        return <NoAuth {...this.props} />;
      } return <IfAuth {...this.props} />;
    }
  } return CMS;
};

<|endoftext|>


<commit_before>(function() {

  'use strict';
  const popupsButtons = [...document.querySelectorAll('.popup-trigger')],
        popupSelector = '.popup',
        popupContentSelector = '.popup__content';

  class Popup {
    constructor(button, popup = popupSelector) {
      this.button = button;
      this.buttonId = button.dataset.popuptrigger;
      this.popup = document.querySelector(`${popup}[data-popup=${this.buttonId}]`);
      this.popupContent = this.popup.querySelector(popupContentSelector);
      this.active = 'popup--active';
      this.fullWidth = 'popup--full-width';
      this.body = document.querySelector('body');
      this.closeButton = this.popup.querySelector('.popup__close-button');

      this.button.addEventListener('click', (e) => {
        e.preventDefault();
        this.toggle();
      });

      this.closeButton.addEventListener('click', () => {
        this.hide();
      });

      window.addEventListener('resize', () => {
        this.position();
      });

      window.addEventListener('click', (e) => {
        if ((e.target !== this.button) && (!this.popup.contains(e.target))) {
          if (this.isActive()) {
            this.hide();
          }
        }
      });
    }

    toggle() {
      if (this.isActive()) {
        this.hide();
      }
      else {
        this.show();
      }
    }

    show() {
      this.popup.classList.add(this.active);
      this.popup.open = true;
      this.popupContent.focus();
      this.position();
      window.addEventListener('keydown', this.keyboardClosePopup.bind(this));
    }

    hide() {
      this.popup.classList.remove(this.active);
      this.button.focus();
      this.popup.open = false;
    }

    position() {
      const buttonCoords = this.button.getBoundingClientRect();
      this.popup.style.setProperty('top', `${buttonCoords.height + buttonCoords.top}px`, '');
      this.popup.style.setProperty('left', `${buttonCoords.left}px`);
      this.isOutOfscreen();
    }

    isOutOfscreen() {
      const popupContentCoords = this.popup.getBoundingClientRect();

      if (window.matchMedia('(max-width: 480px)').matches) {
        this.popup.classList.add(this.fullWidth);
        this.popup.style.setProperty('left', 0);
      }
      else if (popupContentCoords.right >= this.body.clientWidth) {
        this.popup.classList.remove(this.fullWidth);
        this.popup.style.setProperty('right', 0);
        this.popup.style.setProperty('left', 'auto');
      }
    }

    isActive() {
      return this.popup.classList.contains(this.active);
    }

    keyboardClosePopup(event) {
      if (event.which === 27) {
        if (this.isActive()) {
          event.preventDefault();
          this.hide();
        }
      }
    }
  }

  popupsButtons.forEach(popupButton => {
    new Popup(popupButton);
  });
}());
<commit_msg>#35299 move popup content element selector inside Popup class<commit_after>(function() {

  'use strict';
  const popupsButtons = [...document.querySelectorAll('.popup-trigger')],
        popupSelector = '.popup';

  class Popup {
    constructor(button, popup = popupSelector) {
      this.button = button;
      this.buttonId = button.dataset.popuptrigger;
      this.popup = document.querySelector(`${popup}[data-popup=${this.buttonId}]`);
      this.popupContent = this.popup.querySelector('.popup__content');
      this.active = 'popup--active';
      this.fullWidth = 'popup--full-width';
      this.body = document.querySelector('body');
      this.closeButton = this.popup.querySelector('.popup__close-button');

      this.button.addEventListener('click', (e) => {
        e.preventDefault();
        this.toggle();
      });

      this.closeButton.addEventListener('click', () => {
        this.hide();
      });

      window.addEventListener('resize', () => {
        this.position();
      });

      window.addEventListener('click', (e) => {
        if ((e.target !== this.button) && (!this.popup.contains(e.target))) {
          if (this.isActive()) {
            this.hide();
          }
        }
      });
    }

    toggle() {
      if (this.isActive()) {
        this.hide();
      }
      else {
        this.show();
      }
    }

    show() {
      this.popup.classList.add(this.active);
      this.popup.open = true;
      this.popupContent.focus();
      this.position();
      window.addEventListener('keydown', this.keyboardClosePopup.bind(this));
    }

    hide() {
      this.popup.classList.remove(this.active);
      this.button.focus();
      this.popup.open = false;
    }

    position() {
      const buttonCoords = this.button.getBoundingClientRect();
      this.popup.style.setProperty('top', `${buttonCoords.height + buttonCoords.top}px`, '');
      this.popup.style.setProperty('left', `${buttonCoords.left}px`);
      this.isOutOfscreen();
    }

    isOutOfscreen() {
      const popupContentCoords = this.popup.getBoundingClientRect();

      if (window.matchMedia('(max-width: 480px)').matches) {
        this.popup.classList.add(this.fullWidth);
        this.popup.style.setProperty('left', 0);
      }
      else if (popupContentCoords.right >= this.body.clientWidth) {
        this.popup.classList.remove(this.fullWidth);
        this.popup.style.setProperty('right', 0);
        this.popup.style.setProperty('left', 'auto');
      }
    }

    isActive() {
      return this.popup.classList.contains(this.active);
    }

    keyboardClosePopup(event) {
      if (event.which === 27) {
        if (this.isActive()) {
          event.preventDefault();
          this.hide();
        }
      }
    }
  }

  popupsButtons.forEach(popupButton => {
    new Popup(popupButton);
  });
}());
<|endoftext|>


<commit_before>
var config = {
  // File to model mappings, see devices.js
  vendormodels: vendormodels,

  // Default language, see i18n.js
  language: 'en',

  // Data source and branch
  sources: {
    // Scrape image paths from html files
    './images/gluon-factory-example.html': 'stable',
    './images/gluon-sysupgrade-example.html': 'stable'

    // Or from directory listings
    //'https://downloads.openwrt.org/releases/17.01.5/targets/': 'stable',
    //'https://downloads.openwrt.org/snapshots/targets/': 'snapshot'

    // Or use a JSON API
    'https://downloads.openwrt.org/releases/18.06.0/targets/?json': 'stable',
    'https://downloads.openwrt.org/snapshots/targets/?json': 'snapshot'
  },

  // Debug: List images in browser console that match no model
  listUnusedMatchers: false,

  // Debug: List images in browser console that were not matched
  listMissingMatchers: false,

  // Indicate what branches are stable, unstable or testing.
  // Normally, there is no need to change this.
  stable: ['stable', 'release', 'tested'],
  unstable: ['beta', 'unstable'],
  testing: ['alpha', 'snapshot', 'nightly', 'experimental']
};
<commit_msg>update for OpenWrt 18.06.2<commit_after>
var config = {
  // File to model mappings, see devices.js
  vendormodels: vendormodels,

  // Default language, see i18n.js
  language: 'en',

  // Data source and branch
  sources: {
    // Scrape image paths from html files
    './images/gluon-factory-example.html': 'stable',
    './images/gluon-sysupgrade-example.html': 'stable'

    // Or from directory listings
    //'https://downloads.openwrt.org/releases/17.01.5/targets/': 'stable',
    //'https://downloads.openwrt.org/snapshots/targets/': 'snapshot'

    // Or use a JSON API
    'https://downloads.openwrt.org/releases/18.06.2/targets/?json': 'stable',
    'https://downloads.openwrt.org/snapshots/targets/?json': 'snapshot'
  },

  // Debug: List images in browser console that match no model
  listUnusedMatchers: false,

  // Debug: List images in browser console that were not matched
  listMissingMatchers: false,

  // Indicate what branches are stable, unstable or testing.
  // Normally, there is no need to change this.
  stable: ['stable', 'release', 'tested'],
  unstable: ['beta', 'unstable'],
  testing: ['alpha', 'snapshot', 'nightly', 'experimental']
};
<|endoftext|>