UNPKG

4.45 kBJavaScriptView Raw
1'use strict'
2
3const BB = require('bluebird')
4
5const assert = require('assert')
6const cacache = require('cacache')
7const log = require('npmlog')
8const npa = require('npm-package-arg')
9const npm = require('./npm.js')
10const output = require('./utils/output.js')
11const pacote = require('pacote')
12const pacoteOpts = require('./config/pacote')
13const path = require('path')
14const rm = BB.promisify(require('./utils/gently-rm.js'))
15const unbuild = BB.promisify(npm.commands.unbuild)
16
17cache.usage = 'npm cache add <tarball file>' +
18 '\nnpm cache add <folder>' +
19 '\nnpm cache add <tarball url>' +
20 '\nnpm cache add <git url>' +
21 '\nnpm cache add <name>@<version>' +
22 '\nnpm cache clean' +
23 '\nnpm cache verify'
24
25cache.completion = function (opts, cb) {
26 var argv = opts.conf.argv.remain
27 if (argv.length === 2) {
28 return cb(null, ['add', 'clean'])
29 }
30
31 // TODO - eventually...
32 switch (argv[2]) {
33 case 'clean':
34 case 'add':
35 return cb(null, [])
36 }
37}
38
39exports = module.exports = cache
40function cache (args, cb) {
41 const cmd = args.shift()
42 let result
43 switch (cmd) {
44 case 'rm': case 'clear': case 'clean':
45 result = clean(args)
46 break
47 case 'add':
48 result = add(args, npm.prefix)
49 break
50 case 'verify': case 'check':
51 result = verify()
52 break
53 default: return cb('Usage: ' + cache.usage)
54 }
55 if (!result || !result.then) {
56 throw new Error(`npm cache ${cmd} handler did not return a Promise`)
57 }
58 result.then(() => cb(), cb)
59}
60
61// npm cache clean [pkg]*
62cache.clean = clean
63function clean (args) {
64 if (!args) args = []
65 if (args.length) {
66 return BB.reject(new Error('npm cache clear does not accept arguments'))
67 }
68 const cachePath = path.join(npm.cache, '_cacache')
69 if (!npm.config.get('force')) {
70 return BB.reject(new Error("As of npm@5, the npm cache self-heals from corruption issues and data extracted from the cache is guaranteed to be valid. If you want to make sure everything is consistent, use 'npm cache verify' instead.\n\nIf you're sure you want to delete the entire cache, rerun this command with --force."))
71 }
72 // TODO - remove specific packages or package versions
73 return rm(cachePath)
74}
75
76// npm cache add <tarball-url>
77// npm cache add <pkg> <ver>
78// npm cache add <tarball>
79// npm cache add <folder>
80cache.add = function (pkg, ver, where, scrub) {
81 assert(typeof pkg === 'string', 'must include name of package to install')
82 if (scrub) {
83 return clean([]).then(() => {
84 return add([pkg, ver], where)
85 })
86 }
87 return add([pkg, ver], where)
88}
89
90function add (args, where) {
91 var usage = 'Usage:\n' +
92 ' npm cache add <tarball-url>\n' +
93 ' npm cache add <pkg>@<ver>\n' +
94 ' npm cache add <tarball>\n' +
95 ' npm cache add <folder>\n'
96 var spec
97 log.silly('cache add', 'args', args)
98 if (args[1] === undefined) args[1] = null
99 // at this point the args length must ==2
100 if (args[1] !== null) {
101 spec = args[0] + '@' + args[1]
102 } else if (args.length === 2) {
103 spec = args[0]
104 }
105 log.verbose('cache add', 'spec', spec)
106 if (!spec) return BB.reject(new Error(usage))
107 log.silly('cache add', 'parsed spec', spec)
108 return pacote.prefetch(spec, pacoteOpts({where}))
109}
110
111cache.verify = verify
112function verify () {
113 const cache = path.join(npm.config.get('cache'), '_cacache')
114 let prefix = cache
115 if (prefix.indexOf(process.env.HOME) === 0) {
116 prefix = '~' + prefix.substr(process.env.HOME.length)
117 }
118 return cacache.verify(cache).then((stats) => {
119 output(`Cache verified and compressed (${prefix}):`)
120 output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`)
121 stats.badContentCount && output(`Corrupted content removed: ${stats.badContentCount}`)
122 stats.reclaimedCount && output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`)
123 stats.missingContent && output(`Missing content: ${stats.missingContent}`)
124 output(`Index entries: ${stats.totalEntries}`)
125 output(`Finished in ${stats.runTime.total / 1000}s`)
126 })
127}
128
129cache.unpack = unpack
130function unpack (pkg, ver, unpackTarget, dmode, fmode, uid, gid) {
131 return unbuild([unpackTarget], true).then(() => {
132 const opts = pacoteOpts({dmode, fmode, uid, gid, offline: true})
133 return pacote.extract(npa.resolve(pkg, ver), unpackTarget, opts)
134 })
135}