Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib/cache.js')
-rw-r--r--deps/npm/lib/cache.js128
1 files changed, 107 insertions, 21 deletions
diff --git a/deps/npm/lib/cache.js b/deps/npm/lib/cache.js
index 55fb3e86363..aed2cce31e6 100644
--- a/deps/npm/lib/cache.js
+++ b/deps/npm/lib/cache.js
@@ -4,7 +4,59 @@ const log = require('npmlog')
const pacote = require('pacote')
const path = require('path')
const rimraf = promisify(require('rimraf'))
+const semver = require('semver')
const BaseCommand = require('./base-command.js')
+const npa = require('npm-package-arg')
+const jsonParse = require('json-parse-even-better-errors')
+
+const searchCachePackage = async (path, spec, cacheKeys) => {
+ const parsed = npa(spec)
+ if (parsed.rawSpec !== '' && parsed.type === 'tag')
+ throw new Error(`Cannot list cache keys for a tagged package.`)
+ const searchMFH = new RegExp(`^make-fetch-happen:request-cache:.*(?<!/[@a-zA-Z]+)/${parsed.name}/-/(${parsed.name}[^/]+.tgz)$`)
+ const searchPack = new RegExp(`^make-fetch-happen:request-cache:.*/${parsed.escapedName}$`)
+ const results = new Set()
+ cacheKeys = new Set(cacheKeys)
+ for (const key of cacheKeys) {
+ // match on the public key registry url format
+ if (searchMFH.test(key)) {
+ // extract the version from the filename
+ const filename = key.match(searchMFH)[1]
+ const noExt = filename.slice(0, -4)
+ const noScope = `${parsed.name.split('/').pop()}-`
+ const ver = noExt.slice(noScope.length)
+ if (semver.satisfies(ver, parsed.rawSpec))
+ results.add(key)
+ continue
+ }
+ // is this key a packument?
+ if (!searchPack.test(key))
+ continue
+
+ results.add(key)
+ let packument, details
+ try {
+ details = await cacache.get(path, key)
+ packument = jsonParse(details.data)
+ } catch (_) {
+ // if we couldn't parse the packument, abort
+ continue
+ }
+ if (!packument.versions || typeof packument.versions !== 'object')
+ continue
+ // assuming this is a packument
+ for (const ver of Object.keys(packument.versions)) {
+ if (semver.satisfies(ver, parsed.rawSpec)) {
+ if (packument.versions[ver].dist
+ && typeof packument.versions[ver].dist === 'object'
+ && packument.versions[ver].dist.tarball !== undefined
+ && cacheKeys.has(`make-fetch-happen:request-cache:${packument.versions[ver].dist.tarball}`))
+ results.add(`make-fetch-happen:request-cache:${packument.versions[ver].dist.tarball}`)
+ }
+ }
+ }
+ return results
+}
class Cache extends BaseCommand {
static get description () {
@@ -29,7 +81,8 @@ class Cache extends BaseCommand {
'add <tarball url>',
'add <git url>',
'add <name>@<version>',
- 'clean',
+ 'clean [<key>]',
+ 'ls [<name>@<version>]',
'verify',
]
}
@@ -37,13 +90,15 @@ class Cache extends BaseCommand {
async completion (opts) {
const argv = opts.conf.argv.remain
if (argv.length === 2)
- return ['add', 'clean', 'verify']
+ return ['add', 'clean', 'verify', 'ls', 'delete']
// TODO - eventually...
switch (argv[2]) {
case 'verify':
case 'clean':
case 'add':
+ case 'ls':
+ case 'delete':
return []
}
}
@@ -61,6 +116,8 @@ class Cache extends BaseCommand {
return await this.add(args)
case 'verify': case 'check':
return await this.verify()
+ case 'ls':
+ return await this.ls(args)
default:
throw Object.assign(new Error(this.usage), { code: 'EUSAGE' })
}
@@ -68,27 +125,38 @@ class Cache extends BaseCommand {
// npm cache clean [pkg]*
async clean (args) {
- if (args.length)
- throw new Error('npm cache clear does not accept arguments')
-
const cachePath = path.join(this.npm.cache, '_cacache')
- if (!this.npm.config.get('force')) {
- throw new Error(`As of npm@5, the npm cache self-heals from corruption issues
-by treating integrity mismatches as cache misses. As a result,
-data extracted from the cache is guaranteed to be valid. If you
-want to make sure everything is consistent, use \`npm cache verify\`
-instead. Deleting the cache can only make npm go slower, and is
-not likely to correct any problems you may be encountering!
-
-On the other hand, if you're debugging an issue with the installer,
-or race conditions that depend on the timing of writing to an empty
-cache, you can use \`npm install --cache /tmp/empty-cache\` to use a
-temporary cache instead of nuking the actual one.
-
-If you're sure you want to delete the entire cache, rerun this command
-with --force.`)
+ if (args.length === 0) {
+ if (!this.npm.config.get('force')) {
+ throw new Error(`As of npm@5, the npm cache self-heals from corruption issues
+ by treating integrity mismatches as cache misses. As a result,
+ data extracted from the cache is guaranteed to be valid. If you
+ want to make sure everything is consistent, use \`npm cache verify\`
+ instead. Deleting the cache can only make npm go slower, and is
+ not likely to correct any problems you may be encountering!
+
+ On the other hand, if you're debugging an issue with the installer,
+ or race conditions that depend on the timing of writing to an empty
+ cache, you can use \`npm install --cache /tmp/empty-cache\` to use a
+ temporary cache instead of nuking the actual one.
+
+ If you're sure you want to delete the entire cache, rerun this command
+ with --force.`)
+ }
+ return rimraf(cachePath)
+ }
+ for (const key of args) {
+ let entry
+ try {
+ entry = await cacache.get(cachePath, key)
+ } catch (err) {
+ this.npm.log.warn(`Not Found: ${key}`)
+ break
+ }
+ this.npm.output(`Deleted: ${key}`)
+ await cacache.rm.entry(cachePath, key)
+ await cacache.rm.content(cachePath, entry.integrity)
}
- return rimraf(cachePath)
}
// npm cache add <tarball-url>...
@@ -131,6 +199,24 @@ with --force.`)
this.npm.output(`Index entries: ${stats.totalEntries}`)
this.npm.output(`Finished in ${stats.runTime.total / 1000}s`)
}
+
+ // npm cache ls [--package <spec> ...]
+ async ls (specs) {
+ const cachePath = path.join(this.npm.cache, '_cacache')
+ const cacheKeys = Object.keys(await cacache.ls(cachePath))
+ if (specs.length > 0) {
+ // get results for each package spec specified
+ const results = new Set()
+ for (const spec of specs) {
+ const keySet = await searchCachePackage(cachePath, spec, cacheKeys)
+ for (const key of keySet)
+ results.add(key)
+ }
+ [...results].sort((a, b) => a.localeCompare(b, 'en')).forEach(key => this.npm.output(key))
+ return
+ }
+ cacheKeys.sort((a, b) => a.localeCompare(b, 'en')).forEach(key => this.npm.output(key))
+ }
}
module.exports = Cache