"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/npm/lib/cache/add-remote-tarball.js" (11 Apr 2017, 4467 Bytes) of package /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 var mkdir = require('mkdirp')
    2 var assert = require('assert')
    3 var log = require('npmlog')
    4 var path = require('path')
    5 var sha = require('sha')
    6 var retry = require('retry')
    7 var writeStreamAtomic = require('fs-write-stream-atomic')
    8 var PassThrough = require('readable-stream').PassThrough
    9 var npm = require('../npm.js')
   10 var inflight = require('inflight')
   11 var addLocalTarball = require('./add-local-tarball.js')
   12 var cacheFile = require('npm-cache-filename')
   13 var rimraf = require('rimraf')
   14 var pulseTillDone = require('../utils/pulse-till-done.js')
   15 
   16 module.exports = addRemoteTarball
   17 
   18 function addRemoteTarball (u, pkgData, shasum, auth, cb_) {
   19   assert(typeof u === 'string', 'must have module URL')
   20   assert(typeof cb_ === 'function', 'must have callback')
   21 
   22   function cb (er, data) {
   23     if (data) {
   24       data._from = u
   25       data._resolved = u
   26       data._shasum = data._shasum || shasum
   27     }
   28     cb_(er, data)
   29   }
   30 
   31   cb_ = inflight(u, cb_)
   32   if (!cb_) return log.verbose('addRemoteTarball', u, 'already in flight; waiting')
   33   log.verbose('addRemoteTarball', u, 'not in flight; adding')
   34 
   35   // XXX Fetch direct to cache location, store tarballs under
   36   // ${cache}/registry.npmjs.org/pkg/-/pkg-1.2.3.tgz
   37   var tmp = cacheFile(npm.tmp, u)
   38 
   39   function next (er, resp, shasum) {
   40     if (er) return cb(er)
   41     addLocalTarball(tmp, pkgData, shasum, cleanup)
   42   }
   43   function cleanup (er, data) {
   44     if (er) return cb(er)
   45     rimraf(tmp, function () {
   46       cb(er, data)
   47     })
   48   }
   49 
   50   log.verbose('addRemoteTarball', [u, shasum])
   51   mkdir(path.dirname(tmp), function (er) {
   52     if (er) return cb(er)
   53     addRemoteTarball_(u, tmp, shasum, auth, next)
   54   })
   55 }
   56 
   57 function addRemoteTarball_ (u, tmp, shasum, auth, cb) {
   58   // Tuned to spread 3 attempts over about a minute.
   59   // See formula at <https://github.com/tim-kos/node-retry>.
   60   var operation = retry.operation({
   61     retries: npm.config.get('fetch-retries'),
   62     factor: npm.config.get('fetch-retry-factor'),
   63     minTimeout: npm.config.get('fetch-retry-mintimeout'),
   64     maxTimeout: npm.config.get('fetch-retry-maxtimeout')
   65   })
   66 
   67   operation.attempt(function (currentAttempt) {
   68     log.info(
   69       'retry',
   70       'fetch attempt', currentAttempt,
   71       'at', (new Date()).toLocaleTimeString()
   72     )
   73     fetchAndShaCheck(u, tmp, shasum, auth, function (er, response, shasum) {
   74       // Only retry on 408, 5xx or no `response`.
   75       var sc = response && response.statusCode
   76       var statusRetry = !sc || (sc === 408 || sc >= 500)
   77       if (er && statusRetry && operation.retry(er)) {
   78         log.warn('retry', 'will retry, error on last attempt: ' + er)
   79         return
   80       }
   81       cb(er, response, shasum)
   82     })
   83   })
   84 }
   85 
   86 function fetchAndShaCheck (u, tmp, shasum, auth, cb) {
   87   cb = pulseTillDone('fetchTarball', cb)
   88   npm.registry.fetch(u, { auth: auth }, function (er, response) {
   89     if (er) {
   90       log.error('fetch failed', u)
   91       return cb(er, response)
   92     }
   93 
   94     var tarball = writeStreamAtomic(tmp, { mode: npm.modes.file })
   95     tarball.on('error', function (er) {
   96       cb(er)
   97       tarball.destroy()
   98     })
   99 
  100     tarball.on('finish', function () {
  101       if (!shasum) {
  102         // Well, we weren't given a shasum, so at least sha what we have
  103         // in case we want to compare it to something else later
  104         return sha.get(tmp, function (er, shasum) {
  105           log.silly('fetchAndShaCheck', 'shasum', shasum)
  106           cb(er, response, shasum)
  107         })
  108       }
  109 
  110       // validate that the url we just downloaded matches the expected shasum.
  111       log.silly('fetchAndShaCheck', 'shasum', shasum)
  112       sha.check(tmp, shasum, function (er) {
  113         if (er && er.message) {
  114           // add original filename for better debuggability
  115           er.message = er.message + '\n' + 'From:     ' + u
  116         }
  117         return cb(er, response, shasum)
  118       })
  119     })
  120 
  121     // 0.8 http streams have a bug, where if they're paused with data in
  122     // their buffers when the socket closes, they call `end` before emptying
  123     // those buffers, which results in the entire pipeline ending and thus
  124     // the point that applied backpressure never being able to trigger a
  125     // `resume`.
  126     // We work around this by piping into a pass through stream that has
  127     // unlimited buffering. The pass through stream is from readable-stream
  128     // and is thus a current streams3 implementation that is free of these
  129     // bugs even on 0.8.
  130     response.pipe(PassThrough({highWaterMark: Infinity})).pipe(tarball)
  131   })
  132 }