"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/npm/lib/cache.js" (8 Mar 2017, 10411 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // XXX lib/utils/tar.js and this file need to be rewritten.
    2 
    3 // URL-to-cache folder mapping:
    4 // : -> !
    5 // @ -> _
    6 // http://registry.npmjs.org/foo/version -> cache/http!/...
    7 //
    8 
    9 /*
   10 fetching a URL:
   11 1. Check for URL in inflight URLs.  If present, add cb, and return.
   12 2. Acquire lock at {cache}/{sha(url)}.lock
   13    retries = {cache-lock-retries, def=10}
   14    stale = {cache-lock-stale, def=60000}
   15    wait = {cache-lock-wait, def=10000}
   16 3. if lock can't be acquired, then fail
   17 4. fetch url, clear lock, call cbs
   18 
   19 cache folders:
   20 1. urls: http!/server.com/path/to/thing
   21 2. c:\path\to\thing: file!/c!/path/to/thing
   22 3. /path/to/thing: file!/path/to/thing
   23 4. git@ private: git_github.com!npm/npm
   24 5. git://public: git!/github.com/npm/npm
   25 6. git+blah:// git-blah!/server.com/foo/bar
   26 
   27 adding a folder:
   28 1. tar into tmp/random/package.tgz
   29 2. untar into tmp/random/contents/package, stripping one dir piece
   30 3. tar tmp/random/contents/package to cache/n/v/package.tgz
   31 4. untar cache/n/v/package.tgz into cache/n/v/package
   32 5. rm tmp/random
   33 
   34 Adding a url:
   35 1. fetch to tmp/random/package.tgz
   36 2. goto folder(2)
   37 
   38 adding a name@version:
   39 1. registry.get(name/version)
   40 2. if response isn't 304, add url(dist.tarball)
   41 
   42 adding a name@range:
   43 1. registry.get(name)
   44 2. Find a version that satisfies
   45 3. add name@version
   46 
   47 adding a local tarball:
   48 1. untar to tmp/random/{blah}
   49 2. goto folder(2)
   50 
   51 adding a namespaced package:
   52 1. lookup registry for @namespace
   53 2. namespace_registry.get('name')
   54 3. add url(namespace/latest.tarball)
   55 */
   56 
   57 exports = module.exports = cache
   58 
   59 cache.unpack = unpack
   60 cache.clean = clean
   61 cache.read = read
   62 
   63 var npm = require('./npm.js')
   64 var fs = require('graceful-fs')
   65 var writeFileAtomic = require('write-file-atomic')
   66 var assert = require('assert')
   67 var rm = require('./utils/gently-rm.js')
   68 var readJson = require('read-package-json')
   69 var log = require('npmlog')
   70 var path = require('path')
   71 var asyncMap = require('slide').asyncMap
   72 var tar = require('./utils/tar.js')
   73 var fileCompletion = require('./utils/completion/file-completion.js')
   74 var deprCheck = require('./utils/depr-check.js')
   75 var addNamed = require('./cache/add-named.js')
   76 var addLocal = require('./cache/add-local.js')
   77 var addRemoteTarball = require('./cache/add-remote-tarball.js')
   78 var addRemoteGit = require('./cache/add-remote-git.js')
   79 var inflight = require('inflight')
   80 var realizePackageSpecifier = require('realize-package-specifier')
   81 var npa = require('npm-package-arg')
   82 var getStat = require('./cache/get-stat.js')
   83 var cachedPackageRoot = require('./cache/cached-package-root.js')
   84 var mapToRegistry = require('./utils/map-to-registry.js')
   85 var output = require('./utils/output.js')
   86 
   87 cache.usage = 'npm cache add <tarball file>' +
   88               '\nnpm cache add <folder>' +
   89               '\nnpm cache add <tarball url>' +
   90               '\nnpm cache add <git url>' +
   91               '\nnpm cache add <name>@<version>' +
   92               '\nnpm cache ls [<path>]' +
   93               '\nnpm cache clean [<pkg>[@<version>]]'
   94 
   95 cache.completion = function (opts, cb) {
   96   var argv = opts.conf.argv.remain
   97   if (argv.length === 2) {
   98     return cb(null, ['add', 'ls', 'clean'])
   99   }
  100 
  101   switch (argv[2]) {
  102     case 'clean':
  103     case 'ls':
  104       // cache and ls are easy, because the completion is
  105       // what ls_ returns anyway.
  106       // just get the partial words, minus the last path part
  107       var p = path.dirname(opts.partialWords.slice(3).join('/'))
  108       if (p === '.') p = ''
  109       return ls_(p, 2, cb)
  110     case 'add':
  111       // Same semantics as install and publish.
  112       return npm.commands.install.completion(opts, cb)
  113   }
  114 }
  115 
  116 function cache (args, cb) {
  117   var cmd = args.shift()
  118   switch (cmd) {
  119     case 'rm': case 'clear': case 'clean': return clean(args, cb)
  120     case 'list': case 'sl': case 'ls': return ls(args, cb)
  121     case 'add': return add(args, npm.prefix, cb)
  122     default: return cb('Usage: ' + cache.usage)
  123   }
  124 }
  125 
  126 // if the pkg and ver are in the cache, then
  127 // just do a readJson and return.
  128 // if they're not, then fetch them from the registry.
  129 function read (name, ver, forceBypass, cb) {
  130   assert(typeof name === 'string', 'must include name of module to install')
  131   assert(typeof cb === 'function', 'must include callback')
  132 
  133   if (forceBypass === undefined || forceBypass === null) forceBypass = true
  134 
  135   var root = cachedPackageRoot({name: name, version: ver})
  136   function c (er, data) {
  137     if (er) log.verbose('cache', 'addNamed error for', name + '@' + ver, er)
  138     if (data) deprCheck(data)
  139 
  140     return cb(er, data)
  141   }
  142 
  143   if (forceBypass && npm.config.get('force')) {
  144     log.verbose('using force', 'skipping cache')
  145     return addNamed(name, ver, null, c)
  146   }
  147 
  148   readJson(path.join(root, 'package', 'package.json'), function (er, data) {
  149     if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
  150 
  151     if (data) {
  152       if (!data.name) return cb(new Error('No name provided'))
  153       if (!data.version) return cb(new Error('No version provided'))
  154     }
  155 
  156     if (er) return addNamed(name, ver, null, c)
  157     else c(er, data)
  158   })
  159 }
  160 
  161 function normalize (args) {
  162   var normalized = ''
  163   if (args.length > 0) {
  164     var a = npa(args[0])
  165     if (a.name) normalized = a.name
  166     if (a.rawSpec) normalized = [normalized, a.rawSpec].join('/')
  167     if (args.length > 1) normalized = [normalized].concat(args.slice(1)).join('/')
  168   }
  169 
  170   if (normalized.substr(-1) === '/') {
  171     normalized = normalized.substr(0, normalized.length - 1)
  172   }
  173   normalized = path.normalize(normalized)
  174   log.silly('ls', 'normalized', normalized)
  175 
  176   return normalized
  177 }
  178 
  179 // npm cache ls [<path>]
  180 function ls (args, cb) {
  181   var prefix = npm.config.get('cache')
  182   if (prefix.indexOf(process.env.HOME) === 0) {
  183     prefix = '~' + prefix.substr(process.env.HOME.length)
  184   }
  185   ls_(normalize(args), npm.config.get('depth'), function (er, files) {
  186     output(files.map(function (f) {
  187       return path.join(prefix, f)
  188     }).join('\n').trim())
  189     cb(er, files)
  190   })
  191 }
  192 
  193 // Calls cb with list of cached pkgs matching show.
  194 function ls_ (req, depth, cb) {
  195   return fileCompletion(npm.cache, req, depth, cb)
  196 }
  197 
  198 // npm cache clean [<path>]
  199 function clean (args, cb) {
  200   assert(typeof cb === 'function', 'must include callback')
  201 
  202   if (!args) args = []
  203 
  204   var f = path.join(npm.cache, normalize(args))
  205   if (f === npm.cache) {
  206     fs.readdir(npm.cache, function (er, files) {
  207       if (er) return cb()
  208       asyncMap(
  209         files.filter(function (f) {
  210           return npm.config.get('force') || f !== '-'
  211         }).map(function (f) {
  212           return path.join(npm.cache, f)
  213         }),
  214         rm,
  215         cb
  216       )
  217     })
  218   } else {
  219     rm(f, cb)
  220   }
  221 }
  222 
  223 // npm cache add <tarball-url>
  224 // npm cache add <pkg> <ver>
  225 // npm cache add <tarball>
  226 // npm cache add <folder>
  227 cache.add = function (pkg, ver, where, scrub, cb) {
  228   assert(typeof pkg === 'string', 'must include name of package to install')
  229   assert(typeof cb === 'function', 'must include callback')
  230 
  231   if (scrub) {
  232     return clean([], function (er) {
  233       if (er) return cb(er)
  234       add([pkg, ver], where, cb)
  235     })
  236   }
  237   return add([pkg, ver], where, cb)
  238 }
  239 
  240 var adding = 0
  241 function add (args, where, cb) {
  242   // this is hot code.  almost everything passes through here.
  243   // the args can be any of:
  244   // ['url']
  245   // ['pkg', 'version']
  246   // ['pkg@version']
  247   // ['pkg', 'url']
  248   // This is tricky, because urls can contain @
  249   // Also, in some cases we get [name, null] rather
  250   // that just a single argument.
  251 
  252   var usage = 'Usage:\n' +
  253               '    npm cache add <tarball-url>\n' +
  254               '    npm cache add <pkg>@<ver>\n' +
  255               '    npm cache add <tarball>\n' +
  256               '    npm cache add <folder>\n'
  257   var spec
  258 
  259   log.silly('cache add', 'args', args)
  260 
  261   if (args[1] === undefined) args[1] = null
  262 
  263   // at this point the args length must ==2
  264   if (args[1] !== null) {
  265     spec = args[0] + '@' + args[1]
  266   } else if (args.length === 2) {
  267     spec = args[0]
  268   }
  269 
  270   log.verbose('cache add', 'spec', spec)
  271 
  272   if (!spec) return cb(usage)
  273 
  274   adding++
  275   cb = afterAdd(cb)
  276 
  277   realizePackageSpecifier(spec, where, function (err, p) {
  278     if (err) return cb(err)
  279 
  280     log.silly('cache add', 'parsed spec', p)
  281 
  282     switch (p.type) {
  283       case 'local':
  284       case 'directory':
  285         addLocal(p, null, cb)
  286         break
  287       case 'remote':
  288         // get auth, if possible
  289         mapToRegistry(p.raw, npm.config, function (err, uri, auth) {
  290           if (err) return cb(err)
  291 
  292           addRemoteTarball(p.spec, { name: p.name }, null, auth, cb)
  293         })
  294         break
  295       case 'git':
  296       case 'hosted':
  297         addRemoteGit(p.rawSpec, cb)
  298         break
  299       default:
  300         if (p.name) return addNamed(p.name, p.spec, null, cb)
  301 
  302         cb(new Error("couldn't figure out how to install " + spec))
  303     }
  304   })
  305 }
  306 
  307 function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb) {
  308   if (typeof cb !== 'function') {
  309     cb = gid
  310     gid = null
  311   }
  312   if (typeof cb !== 'function') {
  313     cb = uid
  314     uid = null
  315   }
  316   if (typeof cb !== 'function') {
  317     cb = fMode
  318     fMode = null
  319   }
  320   if (typeof cb !== 'function') {
  321     cb = dMode
  322     dMode = null
  323   }
  324 
  325   read(pkg, ver, false, function (er) {
  326     if (er) {
  327       log.error('unpack', 'Could not read data for %s', pkg + '@' + ver)
  328       return cb(er)
  329     }
  330     npm.commands.unbuild([unpackTarget], true, function (er) {
  331       if (er) return cb(er)
  332       tar.unpack(
  333         path.join(cachedPackageRoot({ name: pkg, version: ver }), 'package.tgz'),
  334         unpackTarget,
  335         dMode, fMode,
  336         uid, gid,
  337         cb
  338       )
  339     })
  340   })
  341 }
  342 
  343 function afterAdd (cb) {
  344   return function (er, data) {
  345     adding--
  346 
  347     if (er || !data || !data.name || !data.version) return cb(er, data)
  348     log.silly('cache', 'afterAdd', data.name + '@' + data.version)
  349 
  350     // Save the resolved, shasum, etc. into the data so that the next
  351     // time we load from this cached data, we have all the same info.
  352     // Ignore if it fails.
  353     var pj = path.join(cachedPackageRoot(data), 'package', 'package.json')
  354 
  355     var done = inflight(pj, cb)
  356     if (!done) return log.verbose('afterAdd', pj, 'already in flight; not writing')
  357     log.verbose('afterAdd', pj, 'not in flight; writing')
  358 
  359     getStat(function (er, cs) {
  360       if (er) return done(er)
  361       writeFileAtomic(pj, JSON.stringify(data), { chown: cs }, function (er) {
  362         if (!er) log.verbose('afterAdd', pj, 'written')
  363         return done(null, data)
  364       })
  365     })
  366   }
  367 }