<commit_before>/* @flow */

import arrayUnique from 'lodash/uniq'
import { Disposable, Range, Point } from 'atom'
import type { TextEditor } from 'atom'
import type { Linter, Message } from './types'

export const $version = '__$sb_linter_version'
export const $activated = '__$sb_linter_activated'
export const $requestLatest = '__$sb_linter_request_latest'
export const $requestLastReceived = '__$sb_linter_request_last_received'

export function shouldTriggerLinter(linter: Linter, wasTriggeredOnChange: boolean, scopes: Array<string>): boolean {
  if (wasTriggeredOnChange && !linter.lintsOnChange) {
    return false
  }
  return scopes.some(function(scope) {
    return linter.grammarScopes.includes(scope)
  })
}

export function getEditorCursorScopes(textEditor: TextEditor): Array<string> {
  return arrayUnique(
    textEditor.getCursors().reduce((scopes, cursor) => scopes.concat(cursor.getScopeDescriptor().getScopesArray()), ['*']),
  )
}

let minimatch
export function isPathIgnored(filePath: ?string, ignoredGlob: string, ignoredVCS: boolean): boolean {
  if (!filePath) {
    return true
  }

  if (ignoredVCS) {
    let repository = null
    const projectPaths = atom.project.getPaths()
    for (let i = 0, { length } = projectPaths; i < length; ++i) {
      const projectPath = projectPaths[i]
      if (filePath.indexOf(projectPath) === 0) {
        repository = atom.project.getRepositories()[i]
        break
      }
    }
    if (repository && repository.isPathIgnored(filePath)) {
      return true
    }
  }
  const normalizedFilePath = process.platform === 'win32' ? filePath.replace(/\\/g, '/') : filePath
  if (!minimatch) {
    minimatch = require('minimatch')
  }
  return minimatch(normalizedFilePath, ignoredGlob)
}

export function subscriptiveObserve(object: Object, eventName: string, callback: Function): Disposable {
  let subscription = null
  const eventSubscription = object.observe(eventName, function(props) {
    if (subscription) {
      subscription.dispose()
    }
    subscription = callback.call(this, props)
  })

  return new Disposable(function() {
    eventSubscription.dispose()
    if (subscription) {
      subscription.dispose()
    }
  })
}

export function messageKey(message: Message) {
  const { reference } = message
  return [
    `$LINTER:${message.linterName}`,
    `$LOCATION:${message.location.file}$${message.location.position.start.row}$${message.location.position.start.column}$${
      message.location.position.end.row
    }$${message.location.position.end.column}`,
    reference
      ? `$REFERENCE:${reference.file}$${reference.position ? `${reference.position.row}$${reference.position.column}` : ''}`
      : '$REFERENCE:null',
    `$EXCERPT:${message.excerpt}`,
    `$SEVERITY:${message.severity}`,
    message.icon ? `$ICON:${message.icon}` : '$ICON:null',
    message.url ? `$URL:${message.url}` : '$URL:null',
    typeof message.description === 'string' ? `$DESCRIPTION:${message.description}` : '$DESCRIPTION:null',
  ].join('')
}

export function normalizeMessages(linterName: string, messages: Array<Message>) {
  for (let i = 0, { length } = messages; i < length; ++i) {
    const message = messages[i]
    const { reference } = message
    if (Array.isArray(message.location.position)) {
      message.location.position = Range.fromObject(message.location.position)
    }
    if (reference && Array.isArray(reference.position)) {
      reference.position = Point.fromObject(reference.position)
    }
    if (message.solutions && message.solutions.length) {
      for (let j = 0, _length = message.solutions.length, solution; j < _length; j++) {
        solution = message.solutions[j]
        if (Array.isArray(solution.position)) {
          solution.position = Range.fromObject(solution.position)
        }
      }
    }
    message.version = 2
    if (!message.linterName) {
      message.linterName = linterName
    }
    message.key = messageKey(message)
  }
}

// update the key of the given messages
export function updateKeys(messages: Array<Message>) {
  for (let i = 0, { length } = messages; i < length; ++i) {
    messages[i].key = messageKey(messages[i])
  }
}

<commit_msg>createKeyMessageMap<commit_after>/* @flow */

import arrayUnique from 'lodash/uniq'
import { Disposable, Range, Point } from 'atom'
import type { TextEditor } from 'atom'
import type { Linter, Message } from './types'

export const $version = '__$sb_linter_version'
export const $activated = '__$sb_linter_activated'
export const $requestLatest = '__$sb_linter_request_latest'
export const $requestLastReceived = '__$sb_linter_request_last_received'

export function shouldTriggerLinter(linter: Linter, wasTriggeredOnChange: boolean, scopes: Array<string>): boolean {
  if (wasTriggeredOnChange && !linter.lintsOnChange) {
    return false
  }
  return scopes.some(function(scope) {
    return linter.grammarScopes.includes(scope)
  })
}

export function getEditorCursorScopes(textEditor: TextEditor): Array<string> {
  return arrayUnique(
    textEditor.getCursors().reduce((scopes, cursor) => scopes.concat(cursor.getScopeDescriptor().getScopesArray()), ['*']),
  )
}

let minimatch
export function isPathIgnored(filePath: ?string, ignoredGlob: string, ignoredVCS: boolean): boolean {
  if (!filePath) {
    return true
  }

  if (ignoredVCS) {
    let repository = null
    const projectPaths = atom.project.getPaths()
    for (let i = 0, { length } = projectPaths; i < length; ++i) {
      const projectPath = projectPaths[i]
      if (filePath.indexOf(projectPath) === 0) {
        repository = atom.project.getRepositories()[i]
        break
      }
    }
    if (repository && repository.isPathIgnored(filePath)) {
      return true
    }
  }
  const normalizedFilePath = process.platform === 'win32' ? filePath.replace(/\\/g, '/') : filePath
  if (!minimatch) {
    minimatch = require('minimatch')
  }
  return minimatch(normalizedFilePath, ignoredGlob)
}

export function subscriptiveObserve(object: Object, eventName: string, callback: Function): Disposable {
  let subscription = null
  const eventSubscription = object.observe(eventName, function(props) {
    if (subscription) {
      subscription.dispose()
    }
    subscription = callback.call(this, props)
  })

  return new Disposable(function() {
    eventSubscription.dispose()
    if (subscription) {
      subscription.dispose()
    }
  })
}

export function messageKey(message: Message) {
  const { reference } = message
  return [
    `$LINTER:${message.linterName}`,
    `$LOCATION:${message.location.file}$${message.location.position.start.row}$${message.location.position.start.column}$${
      message.location.position.end.row
    }$${message.location.position.end.column}`,
    reference
      ? `$REFERENCE:${reference.file}$${reference.position ? `${reference.position.row}$${reference.position.column}` : ''}`
      : '$REFERENCE:null',
    `$EXCERPT:${message.excerpt}`,
    `$SEVERITY:${message.severity}`,
    message.icon ? `$ICON:${message.icon}` : '$ICON:null',
    message.url ? `$URL:${message.url}` : '$URL:null',
    typeof message.description === 'string' ? `$DESCRIPTION:${message.description}` : '$DESCRIPTION:null',
  ].join('')
}

export function normalizeMessages(linterName: string, messages: Array<Message>) {
  for (let i = 0, { length } = messages; i < length; ++i) {
    const message = messages[i]
    const { reference } = message
    if (Array.isArray(message.location.position)) {
      message.location.position = Range.fromObject(message.location.position)
    }
    if (reference && Array.isArray(reference.position)) {
      reference.position = Point.fromObject(reference.position)
    }
    if (message.solutions && message.solutions.length) {
      for (let j = 0, _length = message.solutions.length, solution; j < _length; j++) {
        solution = message.solutions[j]
        if (Array.isArray(solution.position)) {
          solution.position = Range.fromObject(solution.position)
        }
      }
    }
    message.version = 2
    if (!message.linterName) {
      message.linterName = linterName
    }
    message.key = messageKey(message)
  }
}

// update the key of the given messages
export function updateKeys(messages: Array<Message>) {
  for (let i = 0, { length } = messages; i < length; ++i) {
    messages[i].key = messageKey(messages[i])
  }
}

// create a map from keys to messages
export function createKeyMessageMap(messages: Array<Message>): Map<string, Message> {
  const keyMessageMap = new Map()
  for (let i = 0, { length } = messages; i < length; ++i) {
    const message = messages[i]
    keyMessageMap.set(message.key, message)
  }
  return keyMessageMap
}

<|endoftext|>


<commit_before>//
//  helpers.js
//

var helpers = exports;

var docs = require("./docs"),
    fs = require('fs'),
    fs2 = require('./fs2'),
    findit = require('findit'),
    path = require('path'),
    traverse = require('traverse');

helpers.unresolve = function (base, abs) {
  return abs.replace(base, ".");
}

helpers.buildToc = function (src) {

  var src = "./pages";

  // get list of directories.
  var _articles = fs2.readDirSync(src, true, function (a) {
    return path.extname(a).length === 0;
  });

  Object.keys(_articles).forEach(function (i) {
    if (_articles[i].isDirectory) {
      _articles[i] = null;
    }
  });

  // build up the tree.
  var toc = fs2.dirToTree(_articles);

  // sort the tree.
  toc = helpers.tocSort(toc)[0];

  // digs until there is a layer with >1 item in it.
  while (toc.length === 1) {
    var row = toc[0];
    var key = Object.keys(row)[0];

    toc = toc[0][key];
  }

  return helpers.treeToHTML(toc);
}

// xs.indexOf(e) returns -1 if no element, the element's index otherwise.
// -~x is truthy if x is non-negative.
var isElement = helpers.isElement = function(xs, e) {
    return -~xs.indexOf(e);
}

//
// Function to use with sorting the ToC.
// ie. tocSort(toc);
//
helpers.tocSort = function(toc) {
  return toc.map(function sortToc (row, paths) {
    var paths = paths || [];
    var key = Object.keys(row)[0];
    var subtoc = row[key];

    var paths = paths.concat([[key]]);

    //Pretty sweet directory view XD
    //console.log(Array(paths.length+1).join(Array(3).join(" ")) + "-"+paths[paths.length-1]);

    // TODO: fs.fileExists instead
    try {
      var order = JSON.parse(fs.readFileSync(paths.join("/")+"/../metadata.json").toString()).order;

      // try to sort the table of contents
      subtoc = subtoc.sort(function (a, b) {
        var aKey = Object.keys(a)[0];
        var bKey = Object.keys(b)[0];

        var aIndex = order[aKey] || 0;
        var bIndex = order[bKey] || 0;

        // would be cleaner with a sgn() function
        if (aIndex < 0) {
          aIndex = subtoc.length + aIndex;
        } else if (aIndex > 0) {
          aIndex = aIndex - subtoc.length;
        }

        if (bIndex < 0) {
          bIndex = subtoc.length + bIndex;
        } else if (bIndex > 0) {
          bIndex = bIndex - subtoc.length;
        }

        return aIndex-bIndex;
      });

    } catch (e) {
      //this just means there's nothing to sort.
      if (e.code !== "EBADF") {
        throw e;
      }
    }

    if (typeof subtoc === "object" && subtoc !== null) {
      return subtoc.map(function (row) {
        var newRow = {};
        var key = Object.keys(row)[0];

        newRow[key] = sortToc(row, paths);
        return newRow;
      });
    } else {
      return subtoc;
    }
  });
};

// TODO: Use weld.
helpers.treeToHTML = function(values, parent) {
  var str = '
';

  if (typeof values === "string") {
    //todo: Make source of value be the article name.

    //var title = values.split("/");
    //title = title[title.length-1];

    return "";

  }

  values.forEach( function(val, i) {
    if (val) {
      var key = Object.keys(val)[0];
    }
    if (typeof values[i]=='object' && values[i] != null){
      var newParent = parent || '';
      newParent = newParent + '/' + key;
      var link = '/articles' + newParent;
      str+='
'+key.replace(/-/g, ' ')+'' + helpers.treeToHTML(values[i][key], newParent)+'
';
    }
  });

   str+='
';

   if(str === "

"){
     return '';
   }
   return str;
};

helpers.articlesToObject = function (src, files) {
  var articles = {};

  Object.keys(files).forEach(function (f) {
    var pathName = path.dirname(f) + "/article.md";
    if (path.basename(f) === "metadata.json") {
      if (!articles[pathName]) {
        articles[pathName] = {};
      }

      try {
        articles[pathName].metadata = JSON.parse(files[f]);
      } catch (e) {
        throw new Error("Failed to parse \""+files[f]+"\"");
      }
      articles[pathName].metadata.link = pathName;
      articles[pathName].metadata.breadcrumb = pathName.replace(path.dirname(src), "").split("/");

      articles[pathName].metadata.breadcrumb = articles[pathName]
        .metadata
        .breadcrumb
        .slice(2, articles[pathName].metadata.breadcrumb.length-1);

    }
    else if (path.basename(f) === "article.md") {
      if (!articles[pathName]) {
        articles[pathName] = {};
      }

      articles[pathName].content = files[f].toString();

    }

  });

  return articles;
}

// Takes a directory, does some slicing/dicing to consolidate information and handle defaults
helpers.dirToContent = function (src, files, resolve) {
  var content = {};
  if (typeof resolve === "undefined") {
    resolve = true;
  }

  Object.keys(files).forEach(function (f) {

    // we want the paths to represent path-based resources,
    // not individual files as before
    var p = path.dirname(f);
    if (!content[p]) {
      content[p] = {};
    }

    // if it's a metadata.json, load the metadata.
    if (path.basename(f) === "metadata.json") {
      try {
        content[p].metadata = JSON.parse(files[f]);
      } catch (e) {
        content[p].metadata = {};
      }

      // what is "link" used for?
      content[p].metadata.link = p;

      // build up a "breadcrumb"
      content[p].metadata.breadcrumb = p.replace(path.dirname(src), "").split("/");
      content[p].metadata.breadcrumb = content[p].metadata.breadcrumb.slice(2, content[p].metadata.breadcrumb.length);

    } // grab content---assumes content is in "article.md" for now
    else if (path.basename(f) === "article.md") {
      if (!content[p]) {
        content[p] = {};
      }

      if (resolve) {
        content[p].content = files[f].toString();
      } else {
        content[p].content = "";
      }

    } else if (fs.statSync(f).isDirectory()) {
      // Directory stuffs
      if (!content[p]) {
        content[p] = {};
      }

      content[p].ls = fs.readdirSync(p).map(function(file) {
        return helpers.unresolve(docs.src, p+"/"+file).replace(/^\./, '');
      });

      // build up a "breadcrumb"
      if (!content[p].metadata) {
        content[p].metadata = {};
      }

      content[p].metadata.breadcrumb = p.replace(path.dirname(src), "").split("/");
      content[p].metadata.breadcrumb = content[p].metadata.breadcrumb.slice(2, content[p].metadata.breadcrumb.length);

    } else if (fs.statSync(f).isFile()) {
      // these are "other" files.
      if (!content[p]) {
        content[p] = {};
      }

      if (!content[p].files) {
        content[p].files = {};
      }

      content[p].files[path.basename(f)] = Buffer.isBuffer(files[f]) ? files[f].toString() : files[f];
      try {
        content[p].files[path.basename(f)] = JSON.parse(content[f].files[path.basename(f)]);
      } catch (e) {
        //don't care
      }
    }

  });

  return content;
}
<commit_msg>[fix] Sorting now implemented *properly.*<commit_after>//
//  helpers.js
//

var helpers = exports;

var docs = require("./docs"),
    fs = require('fs'),
    fs2 = require('./fs2'),
    findit = require('findit'),
    path = require('path'),
    Hash = require('hashish'),
    traverse = require('traverse');

helpers.unresolve = function (base, abs) {
  return abs.replace(base, ".");
}

helpers.buildToc = function (src) {

  var src = "./pages";

  // get list of directories.
  var _articles = fs2.readDirSync(src, true, function (a) {
    return path.extname(a).length === 0;
  });

  Object.keys(_articles).forEach(function (i) {
    if (_articles[i].isDirectory) {
      _articles[i] = null;
    }
  });

  // build up the tree.
  var toc = fs2.dirToTree(_articles);

  // sort the tree.
  toc = helpers.tocSort(toc)[0];

  // digs until there is a layer with >1 item in it.
  while (toc.length === 1) {
    var row = toc[0];
    var key = Object.keys(row)[0];

    toc = toc[0][key];
  }

  return helpers.treeToHTML(toc);
}

// xs.indexOf(e) returns -1 if no element, the element's index otherwise.
// -~x is truthy if x is non-negative.
var isElement = helpers.isElement = function(xs, e) {
    return -~xs.indexOf(e);
}

//
// Function to use with sorting the ToC.
// ie. tocSort(toc);
//
helpers.tocSort = function(toc) {
  return toc.map(function sortToc (row, paths) {
    var paths = paths || [];
    var key = Object.keys(row)[0];
    var subtoc = row[key];

    var paths = paths.concat([[key]]);

    //Pretty sweet directory view XD
    //console.log(Array(paths.length+1).join(Array(3).join(" ")) + "-"+paths[paths.length-1]);

    // Fails if there's no metadata.json
    try {
      var order = JSON.parse(fs.readFileSync(paths.join("/")+"/../metadata.json").toString()).order;

      order = Hash(order).map(function (n) {
        if (n < 0) {
          return Object.keys(subtoc).length + n;
        } else {
          return n;
        }
      }).items;

      // sorts the table of contents based on "order" property
      subtoc = (function () {
        var oldToc = subtoc;
        var newToc = Array(subtoc.length);

        // just the keys.
        var elements = oldToc.map(function (t) {
          return Object.keys(t)[0];
        });

        // place the elements that are explicitly ordered
        Object.keys(order).forEach(function (label) {
          var n = order[label];
          var m = elements.indexOf(label);
          if (m !== -1) {
            newToc[n] = subtoc[m];
            // oldToc holds toc elements not in newToc, but we pull newTocs from
            // subtoc so that the indices match.

            var i = oldToc.map(function (t) {
              return Object.keys(t)[0];
            }).indexOf(label);
            oldToc = oldToc.slice(0, i).concat(oldToc.slice(i+1));
          }
        });

        // get the rest
        // use a for loop because map ignores null values
        for (var i = 0; i < newToc.length; i++) {
          newToc[i] = newToc[i] || oldToc.pop();

        }

        return newToc;

      })();

    } catch (e) {
      //this just means there's nothing to sort.
      if (e.code !== "EBADF") {
        throw e;
      }
    }

    if (typeof subtoc === "object" && subtoc !== null) {
      return subtoc.map(function (row) {
        var newRow = {};
        var key = Object.keys(row)[0];

        newRow[key] = sortToc(row, paths);
        return newRow;
      });
    } else {
      return subtoc;
    }
  });
};

// TODO: Use weld.
helpers.treeToHTML = function(values, parent) {
  var str = '
';

  if (typeof values === "string") {
    //todo: Make source of value be the article name.

    //var title = values.split("/");
    //title = title[title.length-1];

    return "";

  }

  values.forEach( function(val, i) {
    if (val) {
      var key = Object.keys(val)[0];
    }
    if (typeof values[i]=='object' && values[i] != null){
      var newParent = parent || '';
      newParent = newParent + '/' + key;
      var link = '/articles' + newParent;
      str+='
'+key.replace(/-/g, ' ')+'' + helpers.treeToHTML(values[i][key], newParent)+'
';
    }
  });

   str+='
';

   if(str === "

"){
     return '';
   }
   return str;
};

helpers.articlesToObject = function (src, files) {
  var articles = {};

  Object.keys(files).forEach(function (f) {
    var pathName = path.dirname(f) + "/article.md";
    if (path.basename(f) === "metadata.json") {
      if (!articles[pathName]) {
        articles[pathName] = {};
      }

      try {
        articles[pathName].metadata = JSON.parse(files[f]);
      } catch (e) {
        throw new Error("Failed to parse \""+files[f]+"\"");
      }
      articles[pathName].metadata.link = pathName;
      articles[pathName].metadata.breadcrumb = pathName.replace(path.dirname(src), "").split("/");

      articles[pathName].metadata.breadcrumb = articles[pathName]
        .metadata
        .breadcrumb
        .slice(2, articles[pathName].metadata.breadcrumb.length-1);

    }
    else if (path.basename(f) === "article.md") {
      if (!articles[pathName]) {
        articles[pathName] = {};
      }

      articles[pathName].content = files[f].toString();

    }

  });

  return articles;
}

// Takes a directory, does some slicing/dicing to consolidate information and handle defaults
helpers.dirToContent = function (src, files, resolve) {
  var content = {};
  if (typeof resolve === "undefined") {
    resolve = true;
  }

  Object.keys(files).forEach(function (f) {

    // we want the paths to represent path-based resources,
    // not individual files as before
    var p = path.dirname(f);
    if (!content[p]) {
      content[p] = {};
    }

    // if it's a metadata.json, load the metadata.
    if (path.basename(f) === "metadata.json") {
      try {
        content[p].metadata = JSON.parse(files[f]);
      } catch (e) {
        content[p].metadata = {};
      }

      // what is "link" used for?
      content[p].metadata.link = p;

      // build up a "breadcrumb"
      content[p].metadata.breadcrumb = p.replace(path.dirname(src), "").split("/");
      content[p].metadata.breadcrumb = content[p].metadata.breadcrumb.slice(2, content[p].metadata.breadcrumb.length);

    } // grab content---assumes content is in "article.md" for now
    else if (path.basename(f) === "article.md") {
      if (!content[p]) {
        content[p] = {};
      }

      if (resolve) {
        content[p].content = files[f].toString();
      } else {
        content[p].content = "";
      }

    } else if (fs.statSync(f).isDirectory()) {
      // Directory stuffs
      if (!content[p]) {
        content[p] = {};
      }

      content[p].ls = fs.readdirSync(p).map(function(file) {
        return helpers.unresolve(docs.src, p+"/"+file).replace(/^\./, '');
      });

      // build up a "breadcrumb"
      if (!content[p].metadata) {
        content[p].metadata = {};
      }

      content[p].metadata.breadcrumb = p.replace(path.dirname(src), "").split("/");
      content[p].metadata.breadcrumb = content[p].metadata.breadcrumb.slice(2, content[p].metadata.breadcrumb.length);

    } else if (fs.statSync(f).isFile()) {
      // these are "other" files.
      if (!content[p]) {
        content[p] = {};
      }

      if (!content[p].files) {
        content[p].files = {};
      }

      content[p].files[path.basename(f)] = Buffer.isBuffer(files[f]) ? files[f].toString() : files[f];
      try {
        content[p].files[path.basename(f)] = JSON.parse(content[f].files[path.basename(f)]);
      } catch (e) {
        //don't care
      }
    }

  });

  return content;
}
<|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var sget = require('sget');

var helpers = {
  cliTable: require('cli-table'),
  sget: sget,
  getWe: function getWe() {
    try {
      var projectFolder = process.cwd();
      var We = require( path.resolve( projectFolder, 'node_modules/we-core' ));
      return new We();
    } catch(e) {
      if (e.code == 'MODULE_NOT_FOUND') {
        console.error('we-core not found, we.js cli only works in project folder');
        process.exit();
      } else {
        throw e;
      }
    }
  },
  checkIfAreInProject: function checkIfAreInProject() {
    var weCoreFolder = path.resolve( process.cwd(), 'node_modules/we-core' );
    try {
      return fs.statSync(weCoreFolder);
    } catch(e) {
      return false;
    }
  },
  notInProjectError: function notInProjectError() {
    console.error(
      'we-core not found, possible problems: \n\n'+
      '1- run "npm install" for install we-core and others dependencies in your project\n'+
      '2- "we run" we.js cli command only works in project folder\n'
    );
  },

  loadCLICommands: function loadCLICommands() {
    var dir = path.join(__dirname, 'commands');
    return this.loadCommands(dir);
  },

  loadProjectCommands: function loadProjectCommands() {
    var dir = path.join(process.cwd(), 'commands');
    return this.loadCommands(dir);
  },
  loadProjectPluginsCommands: function loadProjectPluginsCommands() {
    var pluginList = this.getPluginsList();

    var plugins = {};

    if (pluginList) {
      for (var i = 0; i < pluginList.length; i++) {
        plugins[pluginList] = this.loadCommands(pluginList[i]);
      }
    }

    return plugins;
  },

  loadCommands: function loadCommands(dir) {
    var commands = [];

    try {
      fs.readdirSync(dir)
      .forEach(function(fileName) {
        if (fileName.endsWith('.js')) {
          commands.push(require(path.join(dir, fileName)));
        }
      });
    } catch(e) {
      if (e.code !== 'ENOENT') throw e;
    }

    return commands;
  },

  runCommandFNs: function runCommandFNs(commands, program) {
    var i;
    // cli
    commands.cli.forEach(function(pf) {
      pf(program, helpers);
    });
    // project
    commands.project.forEach(function(pf) {
      pf(program, helpers);
    });
    // plugins
    for(var pluginName in commands.plugins) {
      for (i = 0; i < commands.plugins[pluginName].length; i++) {
        commands.plugins[pluginName][i](program, helpers);
      }
    }
  },

  getPluginsList: function getPluginsList() {
    var nodeModulesPath = path.join(process.cwd(),'node_modules');

    try {
      var folders = fs.readdirSync(nodeModulesPath);

      return folders
        .filter(function (f) {
          if (
            f.substring(0, 3) === 'we-' &&
            isPlugin(path.join(nodeModulesPath, f))
          ) return true;
          return false;
        })
        .map(function (r) {
          return path.join(nodeModulesPath, r, 'commands');
        })
    } catch(e) {

    }
  }
};

function isPlugin(nodeModulePath) {
  // then check if the npm module is one plugin
  try {
    if (fs.statSync( path.resolve( nodeModulePath, 'plugin.js' ) )) {
      return true;
    } else {
    return false;
    }
  } catch(e) {
    return false;
  }
}

module.exports =helpers;<commit_msg>fix plugin command loaders<commit_after>var path = require('path');
var fs = require('fs');
var sget = require('sget');

var helpers = {
  cliTable: require('cli-table'),
  sget: sget,
  getWe: function getWe() {
    try {
      var projectFolder = process.cwd();
      var We = require( path.resolve( projectFolder, 'node_modules/we-core' ));
      return new We();
    } catch(e) {
      if (e.code == 'MODULE_NOT_FOUND') {
        console.error('we-core not found, we.js cli only works in project folder');
        process.exit();
      } else {
        throw e;
      }
    }
  },
  checkIfAreInProject: function checkIfAreInProject() {
    var weCoreFolder = path.resolve( process.cwd(), 'node_modules/we-core' );
    try {
      return fs.statSync(weCoreFolder);
    } catch(e) {
      return false;
    }
  },
  notInProjectError: function notInProjectError() {
    console.error(
      'we-core not found, possible problems: \n\n'+
      '1- run "npm install" for install we-core and others dependencies in your project\n'+
      '2- "we run" we.js cli command only works in project folder\n'
    );
  },

  loadCLICommands: function loadCLICommands() {
    var dir = path.join(__dirname, 'commands');
    return this.loadCommands(dir);
  },

  loadProjectCommands: function loadProjectCommands() {
    var dir = path.join(process.cwd(), 'commands');
    return this.loadCommands(dir);
  },
  loadProjectPluginsCommands: function loadProjectPluginsCommands() {
    var pluginList = this.getPluginsList();

    var plugins = {};

    if (pluginList) {
      for (var i = 0; i < pluginList.length; i++) {
        plugins[pluginList[i]] = this.loadCommands(pluginList[i]);
      }
    }

    return plugins;
  },

  loadCommands: function loadCommands(dir) {
    var commands = [];

    try {
      fs.readdirSync(dir)
      .forEach(function(fileName) {
        if (fileName.endsWith('.js')) {
          commands.push(require(path.join(dir, fileName)));
        }
      });
    } catch(e) {
      if (e.code !== 'ENOENT') throw e;
    }

    return commands;
  },

  runCommandFNs: function runCommandFNs(commands, program) {
    var i;
    // cli
    commands.cli.forEach(function(pf) {
      pf(program, helpers);
    });
    // project
    commands.project.forEach(function(pf) {
      pf(program, helpers);
    });
    // plugins
    for(var pluginName in commands.plugins) {
      for (i = 0; i < commands.plugins[pluginName].length; i++) {
        commands.plugins[pluginName][i](program, helpers);
      }
    }
  },

  getPluginsList: function getPluginsList() {
    var nodeModulesPath = path.join(process.cwd(),'node_modules');

    try {
      var folders = fs.readdirSync(nodeModulesPath);

      return folders
        .filter(function (f) {
          if (
            f.substring(0, 3) === 'we-' &&
            isPlugin(path.join(nodeModulesPath, f))
          ) return true;
          return false;
        })
        .map(function (r) {
          return path.join(nodeModulesPath, r, 'commands');
        })
    } catch(e) {

    }
  }
};

function isPlugin(nodeModulePath) {
  // then check if the npm module is one plugin
  try {
    if (fs.statSync( path.resolve( nodeModulePath, 'plugin.js' ) )) {
      return true;
    } else {
    return false;
    }
  } catch(e) {
    return false;
  }
}

module.exports =helpers;<|endoftext|>


<commit_before>
module.exports = exports = install

exports.usage = 'Install node development files for the specified node version.'

/**
 * Module dependencies.
 */

var fs = require('graceful-fs')
  , osenv = require('osenv')
  , tar = require('tar')
  , rm = require('rimraf')
  , path = require('path')
  , crypto = require('crypto')
  , zlib = require('zlib')
  , log = require('npmlog')
  , semver = require('semver')
  , fstream = require('fstream')
  , request = require('request')
  , minimatch = require('minimatch')
  , mkdir = require('mkdirp')
  , win = process.platform == 'win32'

function install (gyp, argv, callback) {

  // ensure no double-callbacks happen
  function cb (err) {
    if (cb.done) return
    cb.done = true
    if (err) {
      log.warn('install', 'got an error, rolling back install')
      // roll-back the install if anything went wrong
      gyp.commands.remove([ version ], function (err2) {
        callback(err)
      })
    } else {
      callback(null, version)
    }
  }

  var distUrl = gyp.opts['dist-url'] || gyp.opts.disturl || 'http://nodejs.org/dist'

  // Determine which node dev files version we are installing
  var versionStr = argv[0] || gyp.opts.target || process.version
  log.verbose('install', 'input version string %j', versionStr)

  // parse the version to normalize and ensure it's valid
  var version = semver.parse(versionStr)
  if (!version) {
    return callback(new Error('Invalid version number: ' + versionStr))
  }

  if (semver.lt(versionStr, '0.8.0')) {
    return callback(new Error('Minimum target version is `0.8.0` or greater. Got: ' + versionStr))
  }

  // 0.x.y-pre versions are not published yet and cannot be installed. Bail.
  if (version.prerelease[0] === 'pre') {
    log.verbose('detected "pre" node version', versionStr)
    if (gyp.opts.nodedir) {
      log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir)
      callback()
    } else {
      callback(new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead'))
    }
    return
  }

  // flatten version into String
  version = version.version
  log.verbose('install', 'installing version: %s', version)

  // distributions starting with 0.10.0 contain sha256 checksums
  var checksumAlgo = semver.gte(version, '0.10.0') ? 'sha256' : 'sha1'

  // the directory where the dev files will be installed
  var devDir = path.resolve(gyp.devDir, version)

  // If '--ensure' was passed, then don't *always* install the version;
  // check if it is already installed, and only install when needed
  if (gyp.opts.ensure) {
    log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed')
    fs.stat(devDir, function (err, stat) {
      if (err) {
        if (err.code == 'ENOENT') {
          log.verbose('install', 'version not already installed, continuing with install', version)
          go()
        } else if (err.code == 'EACCES') {
          eaccesFallback()
        } else {
          cb(err)
        }
        return
      }
      log.verbose('install', 'version is already installed, need to check "installVersion"')
      var installVersionFile = path.resolve(devDir, 'installVersion')
      fs.readFile(installVersionFile, 'ascii', function (err, ver) {
        if (err && err.code != 'ENOENT') {
          return cb(err)
        }
        var installVersion = parseInt(ver, 10) || 0
        log.verbose('got "installVersion"', installVersion)
        log.verbose('needs "installVersion"', gyp.package.installVersion)
        if (installVersion < gyp.package.installVersion) {
          log.verbose('install', 'version is no good; reinstalling')
          go()
        } else {
          log.verbose('install', 'version is good')
          cb()
        }
      })
    })
  } else {
    go()
  }

  function download (url) {
    log.http('GET', url)

    var req = null
    var requestOpts = {
        uri: url
      , headers: {
          'User-Agent': 'node-gyp v' + gyp.version + ' (node ' + process.version + ')'
        }
    }

    // basic support for a proxy server
    var proxyUrl = gyp.opts.proxy
                || process.env.http_proxy
                || process.env.HTTP_PROXY
                || process.env.npm_config_proxy
    if (proxyUrl) {
      if (/^https?:\/\//i.test(proxyUrl)) {
        log.verbose('download', 'using proxy url: "%s"', proxyUrl)
        requestOpts.proxy = proxyUrl
      } else {
        log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
      }
    }
    try {
      // The "request" constructor can throw sometimes apparently :(
      // See: https://github.com/TooTallNate/node-gyp/issues/114
      req = request(requestOpts)
    } catch (e) {
      cb(e)
    }
    if (req) {
      req.on('response', function (res) {
        log.http(res.statusCode, url)
      })
    }
    return req
  }

  function getContentSha(res, callback) {
    var shasum = crypto.createHash(checksumAlgo)
    res.on('data', function (chunk) {
      shasum.update(chunk)
    }).on('end', function () {
      callback(null, shasum.digest('hex'))
    })
  }

  function go () {

    log.verbose('ensuring nodedir is created', devDir)

    // first create the dir for the node dev files
    mkdir(devDir, function (err, created) {
      if (err) {
        if (err.code == 'EACCES') {
          eaccesFallback()
        } else {
          cb(err)
        }
        return
      }

      if (created) {
        log.verbose('created nodedir', created)
      }

      // now download the node tarball
      var tarPath = gyp.opts['tarball']
      var tarballUrl = tarPath ? tarPath : distUrl + '/v' + version + '/node-v' + version + '.tar.gz'
        , badDownload = false
        , extractCount = 0
        , gunzip = zlib.createGunzip()
        , extracter = tar.Extract({ path: devDir, strip: 1, filter: isValid })

      var contentShasums = {}
      var expectShasums = {}

      // checks if a file to be extracted from the tarball is valid.
      // only .h header files and the gyp files get extracted
      function isValid () {
        var name = this.path.substring(devDir.length + 1)
        var isValid = valid(name)
        if (name === '' && this.type === 'Directory') {
          // the first directory entry is ok
          return true
        }
        if (isValid) {
          log.verbose('extracted file from tarball', name)
          extractCount++
        } else {
          // invalid
          log.silly('ignoring from tarball', name)
        }
        return isValid
      }

      gunzip.on('error', cb)
      extracter.on('error', cb)
      extracter.on('end', afterTarball)

      // download the tarball, gunzip and extract!

      if (tarPath) {
        var input = fs.createReadStream(tarballUrl)
        input.pipe(gunzip).pipe(extracter)
        return
      }

      var req = download(tarballUrl)
      if (!req) return

      // something went wrong downloading the tarball?
      req.on('error', function (err) {
        badDownload = true
        cb(err)
      })

      req.on('close', function () {
        if (extractCount === 0) {
          cb(new Error('Connection closed while downloading tarball file'))
        }
      })

      req.on('response', function (res) {
        if (res.statusCode !== 200) {
          badDownload = true
          cb(new Error(res.statusCode + ' status code downloading tarball'))
          return
        }
        // content checksum
        getContentSha(res, function (_, checksum) {
          var filename = path.basename(tarballUrl).trim()
          contentShasums[filename] = checksum
          log.verbose('content checksum', filename, checksum)
        })

        // start unzipping and untaring
        req.pipe(gunzip).pipe(extracter)
      })

      // invoked after the tarball has finished being extracted
      function afterTarball () {
        if (badDownload) return
        if (extractCount === 0) {
          return cb(new Error('There was a fatal problem while downloading/extracting the tarball'))
        }
        log.verbose('tarball', 'done parsing tarball')
        var async = 0

        if (win) {
          // need to download node.lib
          async++
          downloadNodeLib(deref)
        }

        // write the "installVersion" file
        async++
        var installVersionPath = path.resolve(devDir, 'installVersion')
        fs.writeFile(installVersionPath, gyp.package.installVersion + '\n', deref)

        // download SHASUMS.txt
        async++
        downloadShasums(deref)

        if (async === 0) {
          // no async tasks required
          cb()
        }

        function deref (err) {
          if (err) return cb(err)

          async--
          if (!async) {
            log.verbose('download contents checksum', JSON.stringify(contentShasums))
            // check content shasums
            for (var k in contentShasums) {
              log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k])
              if (contentShasums[k] !== expectShasums[k]) {
                cb(new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k]))
                return
              }
            }
            cb()
          }
        }
      }

      function downloadShasums(done) {
        var shasumsFile = (checksumAlgo === 'sha256') ? 'SHASUMS256.txt' : 'SHASUMS.txt'
        log.verbose('check download content checksum, need to download `' + shasumsFile + '`...')
        var shasumsPath = path.resolve(devDir, shasumsFile)
          , shasumsUrl = distUrl + '/v' + version + '/' + shasumsFile

        log.verbose('checksum url', shasumsUrl)
        var req = download(shasumsUrl)
        if (!req) return
        req.on('error', done)
        req.on('response', function (res) {
          if (res.statusCode !== 200) {
            done(new Error(res.statusCode + ' status code downloading checksum'))
            return
          }

          var chunks = []
          res.on('data', function (chunk) {
            chunks.push(chunk)
          })
          res.on('end', function () {
            var lines = Buffer.concat(chunks).toString().trim().split('\n')
            lines.forEach(function (line) {
              var items = line.trim().split(/\s+/)
              if (items.length !== 2) return

              // 0035d18e2dcf9aad669b1c7c07319e17abfe3762  ./node-v0.11.4.tar.gz
              var name = items[1].replace(/^\.\//, '')
              expectShasums[name] = items[0]
            })

            log.verbose('checksum data', JSON.stringify(expectShasums))
            done()
          })
        })
      }

      function downloadNodeLib (done) {
        log.verbose('on Windows; need to download `node.lib`...')
        var dir32 = path.resolve(devDir, 'ia32')
          , dir64 = path.resolve(devDir, 'x64')
          , nodeLibPath32 = path.resolve(dir32, 'node.lib')
          , nodeLibPath64 = path.resolve(dir64, 'node.lib')
          , nodeLibUrl32 = distUrl + '/v' + version + '/node.lib'
          , nodeLibUrl64 = distUrl + '/v' + version + '/x64/node.lib'

        log.verbose('32-bit node.lib dir', dir32)
        log.verbose('64-bit node.lib dir', dir64)
        log.verbose('`node.lib` 32-bit url', nodeLibUrl32)
        log.verbose('`node.lib` 64-bit url', nodeLibUrl64)

        var async = 2
        mkdir(dir32, function (err) {
          if (err) return done(err)
          log.verbose('streaming 32-bit node.lib to:', nodeLibPath32)

          var req = download(nodeLibUrl32)
          if (!req) return
          req.on('error', done)
          req.on('response', function (res) {
            if (res.statusCode !== 200) {
              done(new Error(res.statusCode + ' status code downloading 32-bit node.lib'))
              return
            }

            getContentSha(res, function (_, checksum) {
              contentShasums['node.lib'] = checksum
              log.verbose('content checksum', 'node.lib', checksum)
            })

            var ws = fs.createWriteStream(nodeLibPath32)
            ws.on('error', cb)
            req.pipe(ws)
          })
          req.on('end', function () {
            --async || done()
          })
        })
        mkdir(dir64, function (err) {
          if (err) return done(err)
          log.verbose('streaming 64-bit node.lib to:', nodeLibPath64)

          var req = download(nodeLibUrl64)
          if (!req) return
          req.on('error', done)
          req.on('response', function (res) {
            if (res.statusCode !== 200) {
              done(new Error(res.statusCode + ' status code downloading 64-bit node.lib'))
              return
            }

            getContentSha(res, function (_, checksum) {
              contentShasums['x64/node.lib'] = checksum
              log.verbose('content checksum', 'x64/node.lib', checksum)
            })

            var ws = fs.createWriteStream(nodeLibPath64)
            ws.on('error', cb)
            req.pipe(ws)
          })
          req.on('end', function () {
            --async || done()
          })
        })
      } // downloadNodeLib()

    }) // mkdir()

  } // go()

  /**
   * Checks if a given filename is "valid" for this installation.
   */

  function valid (file) {
    // header files
    return minimatch(file, '*.h', { matchBase: true }) ||
           minimatch(file, '*.gypi', { matchBase: true })
  }

  /**
   * The EACCES fallback is a workaround for npm's `sudo` behavior, where
   * it drops the permissions before invoking any child processes (like
   * node-gyp). So what happens is the "nobody" user doesn't have
   * permission to create the dev dir. As a fallback, make the tmpdir() be
   * the dev dir for this installation. This is not ideal, but at least
   * the compilation will succeed...
   */

  function eaccesFallback () {
    var tmpdir = osenv.tmpdir()
    gyp.devDir = path.resolve(tmpdir, '.node-gyp')
    log.warn('EACCES', 'user "%s" does not have permission to access the dev dir "%s"', osenv.user(), devDir)
    log.warn('EACCES', 'attempting to reinstall using temporary dev dir "%s"', gyp.devDir)
    if (process.cwd() == tmpdir) {
      log.verbose('tmpdir == cwd', 'automatically will remove dev files after to save disk space')
      gyp.todo.push({ name: 'remove', args: argv })
    }
    gyp.commands.install(argv, cb)
  }

}
<commit_msg>Show URL when a download fails<commit_after>
module.exports = exports = install

exports.usage = 'Install node development files for the specified node version.'

/**
 * Module dependencies.
 */

var fs = require('graceful-fs')
  , osenv = require('osenv')
  , tar = require('tar')
  , rm = require('rimraf')
  , path = require('path')
  , crypto = require('crypto')
  , zlib = require('zlib')
  , log = require('npmlog')
  , semver = require('semver')
  , fstream = require('fstream')
  , request = require('request')
  , minimatch = require('minimatch')
  , mkdir = require('mkdirp')
  , win = process.platform == 'win32'

function install (gyp, argv, callback) {

  // ensure no double-callbacks happen
  function cb (err) {
    if (cb.done) return
    cb.done = true
    if (err) {
      log.warn('install', 'got an error, rolling back install')
      // roll-back the install if anything went wrong
      gyp.commands.remove([ version ], function (err2) {
        callback(err)
      })
    } else {
      callback(null, version)
    }
  }

  var distUrl = gyp.opts['dist-url'] || gyp.opts.disturl || 'http://nodejs.org/dist'

  // Determine which node dev files version we are installing
  var versionStr = argv[0] || gyp.opts.target || process.version
  log.verbose('install', 'input version string %j', versionStr)

  // parse the version to normalize and ensure it's valid
  var version = semver.parse(versionStr)
  if (!version) {
    return callback(new Error('Invalid version number: ' + versionStr))
  }

  if (semver.lt(versionStr, '0.8.0')) {
    return callback(new Error('Minimum target version is `0.8.0` or greater. Got: ' + versionStr))
  }

  // 0.x.y-pre versions are not published yet and cannot be installed. Bail.
  if (version.prerelease[0] === 'pre') {
    log.verbose('detected "pre" node version', versionStr)
    if (gyp.opts.nodedir) {
      log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir)
      callback()
    } else {
      callback(new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead'))
    }
    return
  }

  // flatten version into String
  version = version.version
  log.verbose('install', 'installing version: %s', version)

  // distributions starting with 0.10.0 contain sha256 checksums
  var checksumAlgo = semver.gte(version, '0.10.0') ? 'sha256' : 'sha1'

  // the directory where the dev files will be installed
  var devDir = path.resolve(gyp.devDir, version)

  // If '--ensure' was passed, then don't *always* install the version;
  // check if it is already installed, and only install when needed
  if (gyp.opts.ensure) {
    log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed')
    fs.stat(devDir, function (err, stat) {
      if (err) {
        if (err.code == 'ENOENT') {
          log.verbose('install', 'version not already installed, continuing with install', version)
          go()
        } else if (err.code == 'EACCES') {
          eaccesFallback()
        } else {
          cb(err)
        }
        return
      }
      log.verbose('install', 'version is already installed, need to check "installVersion"')
      var installVersionFile = path.resolve(devDir, 'installVersion')
      fs.readFile(installVersionFile, 'ascii', function (err, ver) {
        if (err && err.code != 'ENOENT') {
          return cb(err)
        }
        var installVersion = parseInt(ver, 10) || 0
        log.verbose('got "installVersion"', installVersion)
        log.verbose('needs "installVersion"', gyp.package.installVersion)
        if (installVersion < gyp.package.installVersion) {
          log.verbose('install', 'version is no good; reinstalling')
          go()
        } else {
          log.verbose('install', 'version is good')
          cb()
        }
      })
    })
  } else {
    go()
  }

  function download (url) {
    log.http('GET', url)

    var req = null
    var requestOpts = {
        uri: url
      , headers: {
          'User-Agent': 'node-gyp v' + gyp.version + ' (node ' + process.version + ')'
        }
    }

    // basic support for a proxy server
    var proxyUrl = gyp.opts.proxy
                || process.env.http_proxy
                || process.env.HTTP_PROXY
                || process.env.npm_config_proxy
    if (proxyUrl) {
      if (/^https?:\/\//i.test(proxyUrl)) {
        log.verbose('download', 'using proxy url: "%s"', proxyUrl)
        requestOpts.proxy = proxyUrl
      } else {
        log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
      }
    }
    try {
      // The "request" constructor can throw sometimes apparently :(
      // See: https://github.com/TooTallNate/node-gyp/issues/114
      req = request(requestOpts)
    } catch (e) {
      cb(e)
    }
    if (req) {
      req.on('response', function (res) {
        log.http(res.statusCode, url)
      })
    }
    return req
  }

  function getContentSha(res, callback) {
    var shasum = crypto.createHash(checksumAlgo)
    res.on('data', function (chunk) {
      shasum.update(chunk)
    }).on('end', function () {
      callback(null, shasum.digest('hex'))
    })
  }

  function go () {

    log.verbose('ensuring nodedir is created', devDir)

    // first create the dir for the node dev files
    mkdir(devDir, function (err, created) {
      if (err) {
        if (err.code == 'EACCES') {
          eaccesFallback()
        } else {
          cb(err)
        }
        return
      }

      if (created) {
        log.verbose('created nodedir', created)
      }

      // now download the node tarball
      var tarPath = gyp.opts['tarball']
      var tarballUrl = tarPath ? tarPath : distUrl + '/v' + version + '/node-v' + version + '.tar.gz'
        , badDownload = false
        , extractCount = 0
        , gunzip = zlib.createGunzip()
        , extracter = tar.Extract({ path: devDir, strip: 1, filter: isValid })

      var contentShasums = {}
      var expectShasums = {}

      // checks if a file to be extracted from the tarball is valid.
      // only .h header files and the gyp files get extracted
      function isValid () {
        var name = this.path.substring(devDir.length + 1)
        var isValid = valid(name)
        if (name === '' && this.type === 'Directory') {
          // the first directory entry is ok
          return true
        }
        if (isValid) {
          log.verbose('extracted file from tarball', name)
          extractCount++
        } else {
          // invalid
          log.silly('ignoring from tarball', name)
        }
        return isValid
      }

      gunzip.on('error', cb)
      extracter.on('error', cb)
      extracter.on('end', afterTarball)

      // download the tarball, gunzip and extract!

      if (tarPath) {
        var input = fs.createReadStream(tarballUrl)
        input.pipe(gunzip).pipe(extracter)
        return
      }

      var req = download(tarballUrl)
      if (!req) return

      // something went wrong downloading the tarball?
      req.on('error', function (err) {
        badDownload = true
        cb(err)
      })

      req.on('close', function () {
        if (extractCount === 0) {
          cb(new Error('Connection closed while downloading tarball file'))
        }
      })

      req.on('response', function (res) {
        if (res.statusCode !== 200) {
          badDownload = true
          cb(new Error(res.statusCode + ' response dowloading ' + tarballUrl))
          return
        }
        // content checksum
        getContentSha(res, function (_, checksum) {
          var filename = path.basename(tarballUrl).trim()
          contentShasums[filename] = checksum
          log.verbose('content checksum', filename, checksum)
        })

        // start unzipping and untaring
        req.pipe(gunzip).pipe(extracter)
      })

      // invoked after the tarball has finished being extracted
      function afterTarball () {
        if (badDownload) return
        if (extractCount === 0) {
          return cb(new Error('There was a fatal problem while downloading/extracting the tarball'))
        }
        log.verbose('tarball', 'done parsing tarball')
        var async = 0

        if (win) {
          // need to download node.lib
          async++
          downloadNodeLib(deref)
        }

        // write the "installVersion" file
        async++
        var installVersionPath = path.resolve(devDir, 'installVersion')
        fs.writeFile(installVersionPath, gyp.package.installVersion + '\n', deref)

        // download SHASUMS.txt
        async++
        downloadShasums(deref)

        if (async === 0) {
          // no async tasks required
          cb()
        }

        function deref (err) {
          if (err) return cb(err)

          async--
          if (!async) {
            log.verbose('download contents checksum', JSON.stringify(contentShasums))
            // check content shasums
            for (var k in contentShasums) {
              log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k])
              if (contentShasums[k] !== expectShasums[k]) {
                cb(new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k]))
                return
              }
            }
            cb()
          }
        }
      }

      function downloadShasums(done) {
        var shasumsFile = (checksumAlgo === 'sha256') ? 'SHASUMS256.txt' : 'SHASUMS.txt'
        log.verbose('check download content checksum, need to download `' + shasumsFile + '`...')
        var shasumsPath = path.resolve(devDir, shasumsFile)
          , shasumsUrl = distUrl + '/v' + version + '/' + shasumsFile

        log.verbose('checksum url', shasumsUrl)
        var req = download(shasumsUrl)
        if (!req) return
        req.on('error', done)
        req.on('response', function (res) {
          if (res.statusCode !== 200) {
            done(new Error(res.statusCode + ' status code downloading checksum'))
            return
          }

          var chunks = []
          res.on('data', function (chunk) {
            chunks.push(chunk)
          })
          res.on('end', function () {
            var lines = Buffer.concat(chunks).toString().trim().split('\n')
            lines.forEach(function (line) {
              var items = line.trim().split(/\s+/)
              if (items.length !== 2) return

              // 0035d18e2dcf9aad669b1c7c07319e17abfe3762  ./node-v0.11.4.tar.gz
              var name = items[1].replace(/^\.\//, '')
              expectShasums[name] = items[0]
            })

            log.verbose('checksum data', JSON.stringify(expectShasums))
            done()
          })
        })
      }

      function downloadNodeLib (done) {
        log.verbose('on Windows; need to download `node.lib`...')
        var dir32 = path.resolve(devDir, 'ia32')
          , dir64 = path.resolve(devDir, 'x64')
          , nodeLibPath32 = path.resolve(dir32, 'node.lib')
          , nodeLibPath64 = path.resolve(dir64, 'node.lib')
          , nodeLibUrl32 = distUrl + '/v' + version + '/node.lib'
          , nodeLibUrl64 = distUrl + '/v' + version + '/x64/node.lib'

        log.verbose('32-bit node.lib dir', dir32)
        log.verbose('64-bit node.lib dir', dir64)
        log.verbose('`node.lib` 32-bit url', nodeLibUrl32)
        log.verbose('`node.lib` 64-bit url', nodeLibUrl64)

        var async = 2
        mkdir(dir32, function (err) {
          if (err) return done(err)
          log.verbose('streaming 32-bit node.lib to:', nodeLibPath32)

          var req = download(nodeLibUrl32)
          if (!req) return
          req.on('error', done)
          req.on('response', function (res) {
            if (res.statusCode !== 200) {
              done(new Error(res.statusCode + ' status code downloading 32-bit node.lib'))
              return
            }

            getContentSha(res, function (_, checksum) {
              contentShasums['node.lib'] = checksum
              log.verbose('content checksum', 'node.lib', checksum)
            })

            var ws = fs.createWriteStream(nodeLibPath32)
            ws.on('error', cb)
            req.pipe(ws)
          })
          req.on('end', function () {
            --async || done()
          })
        })
        mkdir(dir64, function (err) {
          if (err) return done(err)
          log.verbose('streaming 64-bit node.lib to:', nodeLibPath64)

          var req = download(nodeLibUrl64)
          if (!req) return
          req.on('error', done)
          req.on('response', function (res) {
            if (res.statusCode !== 200) {
              done(new Error(res.statusCode + ' status code downloading 64-bit node.lib'))
              return
            }

            getContentSha(res, function (_, checksum) {
              contentShasums['x64/node.lib'] = checksum
              log.verbose('content checksum', 'x64/node.lib', checksum)
            })

            var ws = fs.createWriteStream(nodeLibPath64)
            ws.on('error', cb)
            req.pipe(ws)
          })
          req.on('end', function () {
            --async || done()
          })
        })
      } // downloadNodeLib()

    }) // mkdir()

  } // go()

  /**
   * Checks if a given filename is "valid" for this installation.
   */

  function valid (file) {
    // header files
    return minimatch(file, '*.h', { matchBase: true }) ||
           minimatch(file, '*.gypi', { matchBase: true })
  }

  /**
   * The EACCES fallback is a workaround for npm's `sudo` behavior, where
   * it drops the permissions before invoking any child processes (like
   * node-gyp). So what happens is the "nobody" user doesn't have
   * permission to create the dev dir. As a fallback, make the tmpdir() be
   * the dev dir for this installation. This is not ideal, but at least
   * the compilation will succeed...
   */

  function eaccesFallback () {
    var tmpdir = osenv.tmpdir()
    gyp.devDir = path.resolve(tmpdir, '.node-gyp')
    log.warn('EACCES', 'user "%s" does not have permission to access the dev dir "%s"', osenv.user(), devDir)
    log.warn('EACCES', 'attempting to reinstall using temporary dev dir "%s"', gyp.devDir)
    if (process.cwd() == tmpdir) {
      log.verbose('tmpdir == cwd', 'automatically will remove dev files after to save disk space')
      gyp.todo.push({ name: 'remove', args: argv })
    }
    gyp.commands.install(argv, cb)
  }

}
<|endoftext|>


<commit_before>
module.exports = exports = install

exports.usage = 'Install node development files for the specified node version'

/**
 * Module dependencies.
 */

var fs = require('fs')
  , tar = require('tar')
  , rm = require('rimraf')
  , path = require('path')
  , zlib = require('zlib')
  , mkdir = require('mkdirp')
  , request = require('request')
  , minimatch = require('minimatch')
  , nodeVersion = require('./util/node_version')
  , distUrl = 'http://nodejs.org/dist'
  , win = process.platform == 'win32'
  // a map for legacy releases:
  // 0.6.10 is the first 0.6 release to have node.lib
  // 0.7.2 is the first 0.7 release to have node.lib
  , nodeLibMap = {
        '0.6': 10
      , '0.7': 1
      // otherwise use the .0 patch release
    }

function install (gyp, argv, callback) {

  // ensure no double-callbacks happen
  function cb (err) {
    if (cb.done) return
    cb.done = true
    if (err) {
      gyp.verbose('got an error, rolling back install')
      // roll-back the install if anything went wrong
      gyp.commands.remove([ version ], function (err2) {
        callback(err)
      })
    } else {
      callback.apply(null, arguments)
    }
  }

  var version = nodeVersion.parse(argv[0] || gyp.opts.target)

  if (!version) {
    return callback(new Error('You must specify a version to install (like "0.7")'))
  }
  if (nodeVersion.lessThan(version, 0, 6)) {
    return callback(new Error('Minimum target version is `0.6` or greater. Got: ' + version))
  }

  // TODO: Make ~/.node-gyp configurable
  var devDir = path.join(process.env.HOME, '.node-gyp', version)

  // If '--ensure' was passed, then don't *always* install the version,
  // check if it is already installed, and only install when needed
  if (gyp.opts.ensure) {
    gyp.verbose('--ensure was passed, so won\'t reinstall if already installed')
    fs.stat(devDir, function (err, stat) {
      if (err) {
        if (err.code == 'ENOENT') {
          gyp.verbose('version not already installed, continuing with install', version)
          go()
        } else {
          callback(err)
        }
        return
      }
      gyp.verbose('version is already installed, not re-installing', version)
      callback()
    })
  } else {
    go()
  }

  function go () {

  // first create the dir for the node dev files
  mkdir(devDir, function (err) {
    if (err) return cb(err)

    // TODO: Detect if it was actually created or if it already existed
    gyp.verbose('created:', devDir)

    // now download the node tarball
    // TODO: download the newest version instead of the .0 release
    var tarballUrl = distUrl + '/v' + version + '.0/node-v' + version + '.0.tar.gz'
      , badDownload = false
      , parser = tar.Parse()

    gyp.info('downloading:', tarballUrl)

    request(tarballUrl, downloadError)
      .pipe(zlib.createGunzip())
      .pipe(parser)
    parser.on('entry', onEntry)
    parser.on('end', afterTarball)

    // something went wrong downloading the tarball?
    function downloadError (err, res) {
      if (err || res.statusCode != 200) {
        badDownload = true
        cb(err || new Error(res.statusCode + ' status code downloading tarball'))
      }
    }

    // handle a file from the tarball
    function onEntry (entry) {
      var filename = entry.props.path
        , trimmed = install.trim(filename)

      if (!install.valid(trimmed)) {
        // skip
        return
      }

      var dir = path.dirname(trimmed)
        , devFileDir = path.join(devDir, dir)
        , devFile = path.join(devDir, trimmed)

      if (dir !== '.') {
        // TODO: async
        // TODO: keep track of the dirs that have been created/checked so far
        //console.error(devFileDir)
        mkdir.sync(devFileDir)
      }
      // TODO: better "File" detection or use `fstream`
      if (entry.props.type !== '0') {
        return
      }
      //console.error(trimmed, entry.props)

      // Finally save the file to the filesystem
      // TODO: Figure out why pipe() hangs here or use `fstream`
      var ws = fs.createWriteStream(devFile, {
          mode: entry.props.mode
      })
      entry.on('data', function (b) {
        ws.write(b)
      })
      entry.on('end', function () {
        ws.end()
        gyp.verbose('saved file', devFile)
      })

    }

    function afterTarball () {
      if (badDownload) return
      gyp.verbose('done parsing tarball')
      var async = 0

      if (nodeVersion.lessThan(version, 0, 7)) {
        // copy over gyp_addon, addon.gypi and common.gypi
        async++
        copyLegacy(deref)
      }

      if (win) {
        // need to download node.lib
        async++
        downloadNodeLib(deref)
      }

      if (win && nodeVersion.lessThan(version, 0, 8)) {
        // before node 0.8 we need to manually link to node.lib
        async++
        copy2685(deref)
      }
      if (!win && nodeVersion.lessThan(version, 0, 8)) {
        async++
        copy2722(deref)
      }

      if (async === 0) {
        // no async tasks required
        cb()
      }

      function deref (err) {
        if (err) return cb(err)
        --async || cb()
      }
    }

    function copyLegacy (done) {
      // node 0.6.x doesn't come with the needed addon.gypi or gyp_addon
      // files, so we must copy them over manually
      gyp.verbose('copying "legacy" development files for version', version)
      var legacyDir = path.join(__dirname, '..', 'legacy')
        , toolsDir = path.join(devDir, 'tools')
      gyp.verbose('using "legacy" dir', legacyDir)
      gyp.verbose('installing to "tools" dir', toolsDir)

      // get a listing of the files to copy
      fs.readdir(legacyDir, function (err, files) {
        if (err) return done(err)
        var count = files.length

        // copy each one over in parallel
        files.forEach(function (file) {
          // common.gypi is a special-case that goes in the root dir instead of
          // the "tools" dir
          var copyFrom = path.join(legacyDir, file)
            , copyTo = path.join(file == 'common.gypi' ? devDir : toolsDir, path.basename(file))
          gyp.verbose('copying from, to', copyFrom, copyTo)
          copy(copyFrom, copyTo, function (err) {
            // TODO: guard against multi-callbacks
            if (err) return done(err)
            --count || done()
          })
        })
      })
    }

    function downloadNodeLib (done) {
      gyp.verbose('on windows; need to download `node.lib`')
      var releaseDir = path.join(devDir, 'Release')
        , debugDir = path.join(devDir, 'Debug')
        , patchVersion = nodeLibMap[version] || '0'
        , nodeLibUrl = distUrl + '/v' + version.toFixed(1) + '.' + patchVersion + '/node.lib'
      gyp.verbose('Release dir', releaseDir)
      gyp.verbose('Debug dir', debugDir)
      gyp.verbose('`node.lib` url', nodeLibUrl)
      // TODO: parallelize mkdirs
      mkdir(releaseDir, function (err) {
        if (err) return done(err)
        mkdir(debugDir, function (err) {
          if (err) return done(err)
          gyp.info('downloading `node.lib`', nodeLibUrl)
          // TODO: clean this mess up, written in a hastemode-9000
          var badDownload = false
          var res = request(nodeLibUrl, function (err, res) {
            if (err || res.statusCode != 200) {
              badDownload = true
              done(err || new Error(res.statusCode + ' status code downloading node.lib'))
            }
          })
          var releaseDirNodeLib = path.join(releaseDir, 'node.lib')
            , debugDirNodeLib = path.join(debugDir, 'node.lib')
            , rws = fs.createWriteStream(releaseDirNodeLib)
            , dws = fs.createWriteStream(debugDirNodeLib)
          gyp.verbose('streaming to', releaseDirNodeLib)
          gyp.verbose('streaming to', debugDirNodeLib)
          res.pipe(rws)
          res.pipe(dws)
          res.on('end', function () {
            if (badDownload) return
            done()
          })
        })
      })
    }

    function copy2685 (done) {
      gyp.verbose('need to install the patch gypi file for #2685 for version', version)
      var patchPath = path.join(__dirname, '..', '2685', 'patch.gypi')
        , copyTo = path.join(devDir, 'tools', 'patch.gypi')
      gyp.verbose('patch.gypi', patchPath)
      gyp.verbose('copy to', copyTo)
      copy(patchPath, copyTo, done)
    }

    function copy2722 (done) {
      gyp.verbose('need to install the patch gypi file for #2722 for version', version)
      var patchPath = path.join(__dirname, '..', '2722', 'patch.gypi')
        , copyTo = path.join(devDir, 'tools', 'patch2722.gypi')
      gyp.verbose('patch.gypi', patchPath)
      gyp.verbose('copy to', copyTo)
      copy(patchPath, copyTo, done)
    }

  })

  }
}

function copy (from, to, cb) {
  var ws = fs.createWriteStream(to)
    , rs = fs.createReadStream(from)
  rs.on('error', cb)
  ws.on('error', cb)
  rs.pipe(ws)
  rs.on('end', function () {
    cb()
  })
}

install.valid = function valid (file) {
  return minimatch(file, '*.gypi')
    || minimatch(file, 'tools/*.gypi')
    || minimatch(file, 'tools/gyp_addon')
    || (minimatch(file, 'tools/gyp/**')
       && !minimatch(file, 'tools/gyp/test/**'))
    // header files
    || minimatch(file, 'src/*.h')
    || minimatch(file, 'deps/v8/include/**/*.h')
    || minimatch(file, 'deps/uv/include/**/*.h')
}

install.trim = function trim (file) {
  var firstSlash = file.indexOf('/')
  return file.substring(firstSlash + 1)
}
<commit_msg>Fix uncaught exception "no method toFixed()".<commit_after>
module.exports = exports = install

exports.usage = 'Install node development files for the specified node version'

/**
 * Module dependencies.
 */

var fs = require('fs')
  , tar = require('tar')
  , rm = require('rimraf')
  , path = require('path')
  , zlib = require('zlib')
  , mkdir = require('mkdirp')
  , request = require('request')
  , minimatch = require('minimatch')
  , nodeVersion = require('./util/node_version')
  , distUrl = 'http://nodejs.org/dist'
  , win = process.platform == 'win32'
  // a map for legacy releases:
  // 0.6.10 is the first 0.6 release to have node.lib
  // 0.7.2 is the first 0.7 release to have node.lib
  , nodeLibMap = {
        '0.6': 10
      , '0.7': 1
      // otherwise use the .0 patch release
    }

function install (gyp, argv, callback) {

  // ensure no double-callbacks happen
  function cb (err) {
    if (cb.done) return
    cb.done = true
    if (err) {
      gyp.verbose('got an error, rolling back install')
      // roll-back the install if anything went wrong
      gyp.commands.remove([ version ], function (err2) {
        callback(err)
      })
    } else {
      callback.apply(null, arguments)
    }
  }

  var version = nodeVersion.parse(argv[0] || gyp.opts.target)

  if (!version) {
    return callback(new Error('You must specify a version to install (like "0.7")'))
  }
  if (nodeVersion.lessThan(version, 0, 6)) {
    return callback(new Error('Minimum target version is `0.6` or greater. Got: ' + version))
  }

  // TODO: Make ~/.node-gyp configurable
  var devDir = path.join(process.env.HOME, '.node-gyp', version)

  // If '--ensure' was passed, then don't *always* install the version,
  // check if it is already installed, and only install when needed
  if (gyp.opts.ensure) {
    gyp.verbose('--ensure was passed, so won\'t reinstall if already installed')
    fs.stat(devDir, function (err, stat) {
      if (err) {
        if (err.code == 'ENOENT') {
          gyp.verbose('version not already installed, continuing with install', version)
          go()
        } else {
          callback(err)
        }
        return
      }
      gyp.verbose('version is already installed, not re-installing', version)
      callback()
    })
  } else {
    go()
  }

  function go () {

  // first create the dir for the node dev files
  mkdir(devDir, function (err) {
    if (err) return cb(err)

    // TODO: Detect if it was actually created or if it already existed
    gyp.verbose('created:', devDir)

    // now download the node tarball
    // TODO: download the newest version instead of the .0 release
    var tarballUrl = distUrl + '/v' + version + '.0/node-v' + version + '.0.tar.gz'
      , badDownload = false
      , parser = tar.Parse()

    gyp.info('downloading:', tarballUrl)

    request(tarballUrl, downloadError)
      .pipe(zlib.createGunzip())
      .pipe(parser)
    parser.on('entry', onEntry)
    parser.on('end', afterTarball)

    // something went wrong downloading the tarball?
    function downloadError (err, res) {
      if (err || res.statusCode != 200) {
        badDownload = true
        cb(err || new Error(res.statusCode + ' status code downloading tarball'))
      }
    }

    // handle a file from the tarball
    function onEntry (entry) {
      var filename = entry.props.path
        , trimmed = install.trim(filename)

      if (!install.valid(trimmed)) {
        // skip
        return
      }

      var dir = path.dirname(trimmed)
        , devFileDir = path.join(devDir, dir)
        , devFile = path.join(devDir, trimmed)

      if (dir !== '.') {
        // TODO: async
        // TODO: keep track of the dirs that have been created/checked so far
        //console.error(devFileDir)
        mkdir.sync(devFileDir)
      }
      // TODO: better "File" detection or use `fstream`
      if (entry.props.type !== '0') {
        return
      }
      //console.error(trimmed, entry.props)

      // Finally save the file to the filesystem
      // TODO: Figure out why pipe() hangs here or use `fstream`
      var ws = fs.createWriteStream(devFile, {
          mode: entry.props.mode
      })
      entry.on('data', function (b) {
        ws.write(b)
      })
      entry.on('end', function () {
        ws.end()
        gyp.verbose('saved file', devFile)
      })

    }

    function afterTarball () {
      if (badDownload) return
      gyp.verbose('done parsing tarball')
      var async = 0

      if (nodeVersion.lessThan(version, 0, 7)) {
        // copy over gyp_addon, addon.gypi and common.gypi
        async++
        copyLegacy(deref)
      }

      if (win) {
        // need to download node.lib
        async++
        downloadNodeLib(deref)
      }

      if (win && nodeVersion.lessThan(version, 0, 8)) {
        // before node 0.8 we need to manually link to node.lib
        async++
        copy2685(deref)
      }
      if (!win && nodeVersion.lessThan(version, 0, 8)) {
        async++
        copy2722(deref)
      }

      if (async === 0) {
        // no async tasks required
        cb()
      }

      function deref (err) {
        if (err) return cb(err)
        --async || cb()
      }
    }

    function copyLegacy (done) {
      // node 0.6.x doesn't come with the needed addon.gypi or gyp_addon
      // files, so we must copy them over manually
      gyp.verbose('copying "legacy" development files for version', version)
      var legacyDir = path.join(__dirname, '..', 'legacy')
        , toolsDir = path.join(devDir, 'tools')
      gyp.verbose('using "legacy" dir', legacyDir)
      gyp.verbose('installing to "tools" dir', toolsDir)

      // get a listing of the files to copy
      fs.readdir(legacyDir, function (err, files) {
        if (err) return done(err)
        var count = files.length

        // copy each one over in parallel
        files.forEach(function (file) {
          // common.gypi is a special-case that goes in the root dir instead of
          // the "tools" dir
          var copyFrom = path.join(legacyDir, file)
            , copyTo = path.join(file == 'common.gypi' ? devDir : toolsDir, path.basename(file))
          gyp.verbose('copying from, to', copyFrom, copyTo)
          copy(copyFrom, copyTo, function (err) {
            // TODO: guard against multi-callbacks
            if (err) return done(err)
            --count || done()
          })
        })
      })
    }

    function downloadNodeLib (done) {
      gyp.verbose('on windows; need to download `node.lib`')
      var releaseDir = path.join(devDir, 'Release')
        , debugDir = path.join(devDir, 'Debug')
        , patchVersion = nodeLibMap[version] || '0'
        , nodeLibUrl = distUrl + '/v' + version + '.' + patchVersion + '/node.lib'
      gyp.verbose('Release dir', releaseDir)
      gyp.verbose('Debug dir', debugDir)
      gyp.verbose('`node.lib` url', nodeLibUrl)
      // TODO: parallelize mkdirs
      mkdir(releaseDir, function (err) {
        if (err) return done(err)
        mkdir(debugDir, function (err) {
          if (err) return done(err)
          gyp.info('downloading `node.lib`', nodeLibUrl)
          // TODO: clean this mess up, written in a hastemode-9000
          var badDownload = false
          var res = request(nodeLibUrl, function (err, res) {
            if (err || res.statusCode != 200) {
              badDownload = true
              done(err || new Error(res.statusCode + ' status code downloading node.lib'))
            }
          })
          var releaseDirNodeLib = path.join(releaseDir, 'node.lib')
            , debugDirNodeLib = path.join(debugDir, 'node.lib')
            , rws = fs.createWriteStream(releaseDirNodeLib)
            , dws = fs.createWriteStream(debugDirNodeLib)
          gyp.verbose('streaming to', releaseDirNodeLib)
          gyp.verbose('streaming to', debugDirNodeLib)
          res.pipe(rws)
          res.pipe(dws)
          res.on('end', function () {
            if (badDownload) return
            done()
          })
        })
      })
    }

    function copy2685 (done) {
      gyp.verbose('need to install the patch gypi file for #2685 for version', version)
      var patchPath = path.join(__dirname, '..', '2685', 'patch.gypi')
        , copyTo = path.join(devDir, 'tools', 'patch.gypi')
      gyp.verbose('patch.gypi', patchPath)
      gyp.verbose('copy to', copyTo)
      copy(patchPath, copyTo, done)
    }

    function copy2722 (done) {
      gyp.verbose('need to install the patch gypi file for #2722 for version', version)
      var patchPath = path.join(__dirname, '..', '2722', 'patch.gypi')
        , copyTo = path.join(devDir, 'tools', 'patch2722.gypi')
      gyp.verbose('patch.gypi', patchPath)
      gyp.verbose('copy to', copyTo)
      copy(patchPath, copyTo, done)
    }

  })

  }
}

function copy (from, to, cb) {
  var ws = fs.createWriteStream(to)
    , rs = fs.createReadStream(from)
  rs.on('error', cb)
  ws.on('error', cb)
  rs.pipe(ws)
  rs.on('end', function () {
    cb()
  })
}

install.valid = function valid (file) {
  return minimatch(file, '*.gypi')
    || minimatch(file, 'tools/*.gypi')
    || minimatch(file, 'tools/gyp_addon')
    || (minimatch(file, 'tools/gyp/**')
       && !minimatch(file, 'tools/gyp/test/**'))
    // header files
    || minimatch(file, 'src/*.h')
    || minimatch(file, 'deps/v8/include/**/*.h')
    || minimatch(file, 'deps/uv/include/**/*.h')
}

install.trim = function trim (file) {
  var firstSlash = file.indexOf('/')
  return file.substring(firstSlash + 1)
}
<|endoftext|>


<commit_before>/* global dependenciesTree */
const path = require('path')
const resolver = require('./install/resolver')
const installer = require('./install/installer')
const pkgJSON = require(path.join(process.env.PWD, 'package.json'))
const dependencies = pkgJSON.dependencies || {}
const devDependencies = pkgJSON.devDependencies || {}
const optionalDependencies = pkgJSON.optionalDependencies || {}
const allDependencies = Object.assign(
  optionalDependencies,
  devDependencies,
  dependencies
)
const lock = {
  name: pkgJSON.name,
  version: pkgJSON.version
}
global.dependenciesTree = {}
global.time = process.hrtime()

function install (argv) {
  argv._handled = true
  const deps = argv.dev ? devDependencies : allDependencies
  const list = resolver(deps)
  Promise.all(list).then(() => {
    const keys = Object.keys(dependenciesTree)
    if (!keys.length) return
    lock.dependencies = dependenciesTree
    const tasks = installer(keys, dependenciesTree)
    Promise.all(tasks).then(() => {
      const duration = process.hrtime(global.time)
      const s = duration[0] + duration[1] / 1e9
      process.stdout.write(
        `added ${Object.keys(dependenciesTree).length} packages in ${s}s\n`
      )
    })
  })
}

module.exports = {
  command: 'install [dev]',
  describe: '',
  handler: install,
  aliases: ['i']
}
<commit_msg>Math.round the number<commit_after>/* global dependenciesTree */
const path = require('path')
const resolver = require('./install/resolver')
const installer = require('./install/installer')
const pkgJSON = require(path.join(process.env.PWD, 'package.json'))
const dependencies = pkgJSON.dependencies || {}
const devDependencies = pkgJSON.devDependencies || {}
const optionalDependencies = pkgJSON.optionalDependencies || {}
const allDependencies = Object.assign(
  optionalDependencies,
  devDependencies,
  dependencies
)
const lock = {
  name: pkgJSON.name,
  version: pkgJSON.version
}
global.dependenciesTree = {}
global.time = process.hrtime()

function install (argv) {
  argv._handled = true
  const deps = argv.dev ? devDependencies : allDependencies
  const list = resolver(deps)
  Promise.all(list).then(() => {
    const keys = Object.keys(dependenciesTree)
    if (!keys.length) return
    lock.dependencies = dependenciesTree
    const tasks = installer(keys, dependenciesTree)
    Promise.all(tasks).then(() => {
      const duration = process.hrtime(global.time)
      const time = duration[0] + duration[1] / 1e9
      const s = Math.round(time * 1000) / 1000
      process.stdout.write(
        `added ${Object.keys(dependenciesTree).length} packages in ${s}s\n`
      )
    })
  })
}

module.exports = {
  command: 'install [dev]',
  describe: '',
  handler: install,
  aliases: ['i']
}
<|endoftext|>


<commit_before>var treeIterator = require('./tree-iterator');

/**
 * File representation for JSCS.
 *
 * @name JsFile
 */
var JsFile = function(filename, source, tree) {
    this._filename = filename;
    this._source = source;
    this._tree = tree;
    this._lines = source.split('\n');
    this._tokenIndex = null;
    var index = this._index = {};
    this.iterate(function(node, parentNode, parentCollection) {
        if (node) {
            var type = node.type;
            if (type) {
                node.parentNode = parentNode;
                node.parentCollection = parentCollection;
                (index[type] || (index[type] = [])).push(node);
            }
        }
    });
};

JsFile.prototype = {
    /**
     * Builds token index by starting pos for futher navigation.
     */
    _buildTokenIndex: function() {
        var tokens = this._tree.tokens;
        var tokenIndex = {};
        for (var i = 0, l = tokens.length; i < l; i++) {
            tokenIndex[tokens[i].range[0]] = i;
        }
        this._tokenIndex = tokenIndex;
    },
    /**
     * Returns token position using range start from the index.
     *
     * @returns {Object}
     */
    getTokenPosByRangeStart: function(start) {
        if (!this._tokenIndex) {
            this._buildTokenIndex();
        }
        return this._tokenIndex[start];
    },
    /**
     * Iterates through the token tree using tree iterator.
     * Calls passed function for every token.
     *
     * @param {Function} cb
     */
    iterate: function(cb) {
        return treeIterator.iterate(this._tree, cb);
    },
    /**
     * Returns tokens by type(s) from earlier built index.
     *
     * @param {String|String[]) type
     * @returns {Object[]}
     */
    getNodesByType: function(type) {
        if (typeof type === 'string') {
            return this._index[type] || [];
        } else {
            var result = [];
            for (var i = 0, l = type.length; i < l; i++) {
                var nodes = this._index[type[i]];
                if (nodes) {
                    result = result.concat(nodes);
                }
            }
            return result;
        }
    },
    /**
     * Iterates tokens by type(s) from earlier built index.
     * Calls passed function for every matched token.
     *
     * @param {String|String[]) type
     * @param {Function} cb
     */
    iterateNodesByType: function(type, cb) {
        return this.getNodesByType(type).forEach(cb);
    },
    /**
     * Returns string representing contents of the file.
     *
     * @returns {String}
     */
    getSource: function() {
        return this._source;
    },
    /**
     * Returns token tree, built using esprima.
     *
     * @returns {Object}
     */
    getTree: function() {
        return this._tree;
    },
    /**
     * Returns token list, built using esprima.
     *
     * @returns {Object[]}
     */
    getTokens: function() {
        return this._tree.tokens;
    },
    /**
     * Returns comment token list, built using esprima.
     */
    getComments: function() {
        return this._tree.comments;
    },
    /**
     * Returns source filename for this object representation.
     *
     * @returns {String}
     */
    getFilename: function() {
        return this._filename;
    },
    /**
     * Returns array of source lines for the file.
     *
     * @returns {String[]}
     */
    getLines: function() {
        return this._lines;
    }
};

module.exports = JsFile;
<commit_msg>JSDoc fix<commit_after>var treeIterator = require('./tree-iterator');

/**
 * File representation for JSCS.
 *
 * @name JsFile
 */
var JsFile = function(filename, source, tree) {
    this._filename = filename;
    this._source = source;
    this._tree = tree;
    this._lines = source.split('\n');
    this._tokenIndex = null;
    var index = this._index = {};
    this.iterate(function(node, parentNode, parentCollection) {
        if (node) {
            var type = node.type;
            if (type) {
                node.parentNode = parentNode;
                node.parentCollection = parentCollection;
                (index[type] || (index[type] = [])).push(node);
            }
        }
    });
};

JsFile.prototype = {
    /**
     * Builds token index by starting pos for futher navigation.
     */
    _buildTokenIndex: function() {
        var tokens = this._tree.tokens;
        var tokenIndex = {};
        for (var i = 0, l = tokens.length; i < l; i++) {
            tokenIndex[tokens[i].range[0]] = i;
        }
        this._tokenIndex = tokenIndex;
    },
    /**
     * Returns token position using range start from the index.
     *
     * @returns {Object}
     */
    getTokenPosByRangeStart: function(start) {
        if (!this._tokenIndex) {
            this._buildTokenIndex();
        }
        return this._tokenIndex[start];
    },
    /**
     * Iterates through the token tree using tree iterator.
     * Calls passed function for every token.
     *
     * @param {Function} cb
     */
    iterate: function(cb) {
        return treeIterator.iterate(this._tree, cb);
    },
    /**
     * Returns tokens by type(s) from earlier built index.
     *
     * @param {String|String[]} type
     * @returns {Object[]}
     */
    getNodesByType: function(type) {
        if (typeof type === 'string') {
            return this._index[type] || [];
        } else {
            var result = [];
            for (var i = 0, l = type.length; i < l; i++) {
                var nodes = this._index[type[i]];
                if (nodes) {
                    result = result.concat(nodes);
                }
            }
            return result;
        }
    },
    /**
     * Iterates tokens by type(s) from earlier built index.
     * Calls passed function for every matched token.
     *
     * @param {String|String[]} type
     * @param {Function} cb
     */
    iterateNodesByType: function(type, cb) {
        return this.getNodesByType(type).forEach(cb);
    },
    /**
     * Returns string representing contents of the file.
     *
     * @returns {String}
     */
    getSource: function() {
        return this._source;
    },
    /**
     * Returns token tree, built using esprima.
     *
     * @returns {Object}
     */
    getTree: function() {
        return this._tree;
    },
    /**
     * Returns token list, built using esprima.
     *
     * @returns {Object[]}
     */
    getTokens: function() {
        return this._tree.tokens;
    },
    /**
     * Returns comment token list, built using esprima.
     */
    getComments: function() {
        return this._tree.comments;
    },
    /**
     * Returns source filename for this object representation.
     *
     * @returns {String}
     */
    getFilename: function() {
        return this._filename;
    },
    /**
     * Returns array of source lines for the file.
     *
     * @returns {String[]}
     */
    getLines: function() {
        return this._lines;
    }
};

module.exports = JsFile;
<|endoftext|>


<commit_before>var Q = require('q');
var request = require("request");
var moment = require('moment');

module.exports = {
  search: function(query, cat, page, kickass_url) {
    var count = 1;
    var deferred = Q.defer();
    var data_content = {};
    var torrent_content = [];
    var torrent_verified;

    var search_url = kickass_url + '/json.php?q=' + encodeURIComponent(query) + '&field=seeders&order=desc&page=' + page;

    request(search_url, function(err, response, body){

      if(!err && response.statusCode === 200){

        data = JSON.parse(body);

        if(data.list.length){
          for(var torrent in data.list){

            var title = data.list[torrent].title;
            var category = data.list[torrent].category;
            var torrent_link = data.list[torrent].torrentLink;
            var seeds = data.list[torrent].seeds;
            var leechs = data.list[torrent].leechs;
            var size = bytesToSize(data.list[torrent].size);
            if(data.list[torrent].verified === 1){
              torrent_verified = " 👑  ";
            } else {
              torrent_verified = " ";
            }

            var date_added = moment(Date.parse(data.list[torrent].pubDate)).fromNow();

            data_content = {
              torrent_num: count,
              title: title,
              category: category,
              seeds: seeds,
              leechs: leechs,
              size: size,
              torrent_link: torrent_link,
              torrent_verified:torrent_verified,
              date_added: date_added
            };

            torrent_content.push(data_content);

            deferred.resolve(torrent_content);
            count++;
          }
        } else {
          deferred.reject("No torrents found");
        }
      } else {
        deferred.reject("There was a problem loading KickassTorrents");
      }

    });

    return deferred.promise;

  }
};

function bytesToSize(bytes) {
  var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  if (bytes === 0) return '0 Byte';
  var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  return Math.round(bytes / Math.pow(1024, i), 2) + '' + sizes[i];
}
<commit_msg>Make kickass use magnet instead of .torrent<commit_after>var Q = require('q');
var request = require("request");
var moment = require('moment');

module.exports = {
  search: function(query, cat, page, kickass_url) {
    var count = 1;
    var deferred = Q.defer();
    var data_content = {};
    var torrent_content = [];
    var torrent_verified;

    var search_url = kickass_url + '/json.php?q=' + encodeURIComponent(query) + '&field=seeders&order=desc&page=' + page;

    request(search_url, function(err, response, body){

      if(!err && response.statusCode === 200){

        data = JSON.parse(body);
        console.log(data);
        if(data.list.length){
          for(var torrent in data.list){

            var title = data.list[torrent].title;
            var category = data.list[torrent].category;
            var torrent_link = data.list[torrent].torrentLink;
            var seeds = data.list[torrent].seeds;
            var leechs = data.list[torrent].leechs;
            var size = bytesToSize(data.list[torrent].size);
            if(data.list[torrent].verified === 1){
              torrent_verified = " 👑  ";
            } else {
              torrent_verified = " ";
            }

            var date_added = moment(Date.parse(data.list[torrent].pubDate)).fromNow();

            var magnet_link = "magnet:?xt=urn:btih:" + data.list[torrent].hash + "&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce";

            data_content = {
              torrent_num: count,
              title: title,
              category: category,
              seeds: seeds,
              leechs: leechs,
              size: size,
              torrent_link: magnet_link,
              torrent_verified:torrent_verified,
              date_added: date_added
            };

            torrent_content.push(data_content);

            deferred.resolve(torrent_content);
            count++;
          }
        } else {
          deferred.reject("No torrents found");
        }
      } else {
        deferred.reject("There was a problem loading KickassTorrents");
      }

    });

    return deferred.promise;

  }
};

function bytesToSize(bytes) {
  var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  if (bytes === 0) return '0 Byte';
  var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  return Math.round(bytes / Math.pow(1024, i), 2) + '' + sizes[i];
}
<|endoftext|>