cacache 15.0.5 → 15.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -1
- package/get.js +121 -139
- package/index.js +5 -0
- package/lib/content/read.js +27 -33
- package/lib/content/rm.js +2 -3
- package/lib/content/write.js +19 -14
- package/lib/entry-index.js +127 -38
- package/lib/memoization.js +5 -6
- package/lib/util/disposer.js +2 -2
- package/lib/util/fix-owner.js +9 -12
- package/lib/util/move-file.js +3 -5
- package/lib/util/tmp.js +9 -9
- package/lib/verify.js +17 -17
- package/package.json +14 -29
- package/put.js +9 -10
- package/rm.js +2 -2
- package/CHANGELOG.md +0 -794
package/lib/entry-index.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const util = require('util')
|
|
4
|
-
|
|
5
4
|
const crypto = require('crypto')
|
|
6
5
|
const fs = require('fs')
|
|
7
6
|
const Minipass = require('minipass')
|
|
8
7
|
const path = require('path')
|
|
9
8
|
const ssri = require('ssri')
|
|
9
|
+
const uniqueFilename = require('unique-filename')
|
|
10
|
+
|
|
11
|
+
const { disposer } = require('./util/disposer')
|
|
10
12
|
const contentPath = require('./content/path')
|
|
11
13
|
const fixOwner = require('./util/fix-owner')
|
|
12
14
|
const hashToSegments = require('./util/hash-to-segments')
|
|
13
15
|
const indexV = require('../package.json')['cache-version'].index
|
|
16
|
+
const moveFile = require('@npmcli/move-file')
|
|
17
|
+
const _rimraf = require('rimraf')
|
|
18
|
+
const rimraf = util.promisify(_rimraf)
|
|
19
|
+
rimraf.sync = _rimraf.sync
|
|
14
20
|
|
|
15
21
|
const appendFile = util.promisify(fs.appendFile)
|
|
16
22
|
const readFile = util.promisify(fs.readFile)
|
|
17
23
|
const readdir = util.promisify(fs.readdir)
|
|
24
|
+
const writeFile = util.promisify(fs.writeFile)
|
|
18
25
|
|
|
19
26
|
module.exports.NotFoundError = class NotFoundError extends Error {
|
|
20
27
|
constructor (cache, key) {
|
|
@@ -25,6 +32,82 @@ module.exports.NotFoundError = class NotFoundError extends Error {
|
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
|
|
35
|
+
module.exports.compact = compact
|
|
36
|
+
|
|
37
|
+
async function compact (cache, key, matchFn, opts = {}) {
|
|
38
|
+
const bucket = bucketPath(cache, key)
|
|
39
|
+
const entries = await bucketEntries(bucket)
|
|
40
|
+
const newEntries = []
|
|
41
|
+
// we loop backwards because the bottom-most result is the newest
|
|
42
|
+
// since we add new entries with appendFile
|
|
43
|
+
for (let i = entries.length - 1; i >= 0; --i) {
|
|
44
|
+
const entry = entries[i]
|
|
45
|
+
// a null integrity could mean either a delete was appended
|
|
46
|
+
// or the user has simply stored an index that does not map
|
|
47
|
+
// to any content. we determine if the user wants to keep the
|
|
48
|
+
// null integrity based on the validateEntry function passed in options.
|
|
49
|
+
// if the integrity is null and no validateEntry is provided, we break
|
|
50
|
+
// as we consider the null integrity to be a deletion of everything
|
|
51
|
+
// that came before it.
|
|
52
|
+
if (entry.integrity === null && !opts.validateEntry)
|
|
53
|
+
break
|
|
54
|
+
|
|
55
|
+
// if this entry is valid, and it is either the first entry or
|
|
56
|
+
// the newEntries array doesn't already include an entry that
|
|
57
|
+
// matches this one based on the provided matchFn, then we add
|
|
58
|
+
// it to the beginning of our list
|
|
59
|
+
if ((!opts.validateEntry || opts.validateEntry(entry) === true) &&
|
|
60
|
+
(newEntries.length === 0 ||
|
|
61
|
+
!newEntries.find((oldEntry) => matchFn(oldEntry, entry))))
|
|
62
|
+
newEntries.unshift(entry)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const newIndex = '\n' + newEntries.map((entry) => {
|
|
66
|
+
const stringified = JSON.stringify(entry)
|
|
67
|
+
const hash = hashEntry(stringified)
|
|
68
|
+
return `${hash}\t${stringified}`
|
|
69
|
+
}).join('\n')
|
|
70
|
+
|
|
71
|
+
const setup = async () => {
|
|
72
|
+
const target = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix)
|
|
73
|
+
await fixOwner.mkdirfix(cache, path.dirname(target))
|
|
74
|
+
return {
|
|
75
|
+
target,
|
|
76
|
+
moved: false,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const teardown = async (tmp) => {
|
|
81
|
+
if (!tmp.moved)
|
|
82
|
+
return rimraf(tmp.target)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const write = async (tmp) => {
|
|
86
|
+
await writeFile(tmp.target, newIndex, { flag: 'wx' })
|
|
87
|
+
await fixOwner.mkdirfix(cache, path.dirname(bucket))
|
|
88
|
+
// we use @npmcli/move-file directly here because we
|
|
89
|
+
// want to overwrite the existing file
|
|
90
|
+
await moveFile(tmp.target, bucket)
|
|
91
|
+
tmp.moved = true
|
|
92
|
+
try {
|
|
93
|
+
await fixOwner.chownr(cache, bucket)
|
|
94
|
+
} catch (err) {
|
|
95
|
+
if (err.code !== 'ENOENT')
|
|
96
|
+
throw err
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// write the file atomically
|
|
101
|
+
await disposer(setup(), teardown, write)
|
|
102
|
+
|
|
103
|
+
// we reverse the list we generated such that the newest
|
|
104
|
+
// entries come first in order to make looping through them easier
|
|
105
|
+
// the true passed to formatEntry tells it to keep null
|
|
106
|
+
// integrity values, if they made it this far it's because
|
|
107
|
+
// validateEntry returned true, and as such we should return it
|
|
108
|
+
return newEntries.reverse().map((entry) => formatEntry(cache, entry, true))
|
|
109
|
+
}
|
|
110
|
+
|
|
28
111
|
module.exports.insert = insert
|
|
29
112
|
|
|
30
113
|
function insert (cache, key, integrity, opts = {}) {
|
|
@@ -35,7 +118,7 @@ function insert (cache, key, integrity, opts = {}) {
|
|
|
35
118
|
integrity: integrity && ssri.stringify(integrity),
|
|
36
119
|
time: Date.now(),
|
|
37
120
|
size,
|
|
38
|
-
metadata
|
|
121
|
+
metadata,
|
|
39
122
|
}
|
|
40
123
|
return fixOwner
|
|
41
124
|
.mkdirfix(cache, path.dirname(bucket))
|
|
@@ -47,14 +130,15 @@ function insert (cache, key, integrity, opts = {}) {
|
|
|
47
130
|
// another while still preserving the string length of the JSON in
|
|
48
131
|
// question. So, we just slap the length in there and verify it on read.
|
|
49
132
|
//
|
|
50
|
-
// Thanks to @isaacs for the whiteboarding session that ended up with
|
|
133
|
+
// Thanks to @isaacs for the whiteboarding session that ended up with
|
|
134
|
+
// this.
|
|
51
135
|
return appendFile(bucket, `\n${hashEntry(stringified)}\t${stringified}`)
|
|
52
136
|
})
|
|
53
137
|
.then(() => fixOwner.chownr(cache, bucket))
|
|
54
138
|
.catch((err) => {
|
|
55
|
-
if (err.code === 'ENOENT')
|
|
139
|
+
if (err.code === 'ENOENT')
|
|
56
140
|
return undefined
|
|
57
|
-
|
|
141
|
+
|
|
58
142
|
throw err
|
|
59
143
|
// There's a class of race conditions that happen when things get deleted
|
|
60
144
|
// during fixOwner, or between the two mkdirfix/chownr calls.
|
|
@@ -77,7 +161,7 @@ function insertSync (cache, key, integrity, opts = {}) {
|
|
|
77
161
|
integrity: integrity && ssri.stringify(integrity),
|
|
78
162
|
time: Date.now(),
|
|
79
163
|
size,
|
|
80
|
-
metadata
|
|
164
|
+
metadata,
|
|
81
165
|
}
|
|
82
166
|
fixOwner.mkdirfix.sync(cache, path.dirname(bucket))
|
|
83
167
|
const stringified = JSON.stringify(entry)
|
|
@@ -85,9 +169,8 @@ function insertSync (cache, key, integrity, opts = {}) {
|
|
|
85
169
|
try {
|
|
86
170
|
fixOwner.chownr.sync(cache, bucket)
|
|
87
171
|
} catch (err) {
|
|
88
|
-
if (err.code !== 'ENOENT')
|
|
172
|
+
if (err.code !== 'ENOENT')
|
|
89
173
|
throw err
|
|
90
|
-
}
|
|
91
174
|
}
|
|
92
175
|
return formatEntry(cache, entry)
|
|
93
176
|
}
|
|
@@ -99,19 +182,17 @@ function find (cache, key) {
|
|
|
99
182
|
return bucketEntries(bucket)
|
|
100
183
|
.then((entries) => {
|
|
101
184
|
return entries.reduce((latest, next) => {
|
|
102
|
-
if (next && next.key === key)
|
|
185
|
+
if (next && next.key === key)
|
|
103
186
|
return formatEntry(cache, next)
|
|
104
|
-
|
|
187
|
+
else
|
|
105
188
|
return latest
|
|
106
|
-
}
|
|
107
189
|
}, null)
|
|
108
190
|
})
|
|
109
191
|
.catch((err) => {
|
|
110
|
-
if (err.code === 'ENOENT')
|
|
192
|
+
if (err.code === 'ENOENT')
|
|
111
193
|
return null
|
|
112
|
-
|
|
194
|
+
else
|
|
113
195
|
throw err
|
|
114
|
-
}
|
|
115
196
|
})
|
|
116
197
|
}
|
|
117
198
|
|
|
@@ -121,31 +202,37 @@ function findSync (cache, key) {
|
|
|
121
202
|
const bucket = bucketPath(cache, key)
|
|
122
203
|
try {
|
|
123
204
|
return bucketEntriesSync(bucket).reduce((latest, next) => {
|
|
124
|
-
if (next && next.key === key)
|
|
205
|
+
if (next && next.key === key)
|
|
125
206
|
return formatEntry(cache, next)
|
|
126
|
-
|
|
207
|
+
else
|
|
127
208
|
return latest
|
|
128
|
-
}
|
|
129
209
|
}, null)
|
|
130
210
|
} catch (err) {
|
|
131
|
-
if (err.code === 'ENOENT')
|
|
211
|
+
if (err.code === 'ENOENT')
|
|
132
212
|
return null
|
|
133
|
-
|
|
213
|
+
else
|
|
134
214
|
throw err
|
|
135
|
-
}
|
|
136
215
|
}
|
|
137
216
|
}
|
|
138
217
|
|
|
139
218
|
module.exports.delete = del
|
|
140
219
|
|
|
141
|
-
function del (cache, key, opts) {
|
|
142
|
-
|
|
220
|
+
function del (cache, key, opts = {}) {
|
|
221
|
+
if (!opts.removeFully)
|
|
222
|
+
return insert(cache, key, null, opts)
|
|
223
|
+
|
|
224
|
+
const bucket = bucketPath(cache, key)
|
|
225
|
+
return rimraf(bucket)
|
|
143
226
|
}
|
|
144
227
|
|
|
145
228
|
module.exports.delete.sync = delSync
|
|
146
229
|
|
|
147
|
-
function delSync (cache, key, opts) {
|
|
148
|
-
|
|
230
|
+
function delSync (cache, key, opts = {}) {
|
|
231
|
+
if (!opts.removeFully)
|
|
232
|
+
return insertSync(cache, key, null, opts)
|
|
233
|
+
|
|
234
|
+
const bucket = bucketPath(cache, key)
|
|
235
|
+
return rimraf.sync(bucket)
|
|
149
236
|
}
|
|
150
237
|
|
|
151
238
|
module.exports.lsStream = lsStream
|
|
@@ -176,12 +263,12 @@ function lsStream (cache) {
|
|
|
176
263
|
// reduced is a map of key => entry
|
|
177
264
|
for (const entry of reduced.values()) {
|
|
178
265
|
const formatted = formatEntry(cache, entry)
|
|
179
|
-
if (formatted)
|
|
266
|
+
if (formatted)
|
|
180
267
|
stream.write(formatted)
|
|
181
|
-
}
|
|
182
268
|
}
|
|
183
269
|
}).catch(err => {
|
|
184
|
-
if (err.code === 'ENOENT')
|
|
270
|
+
if (err.code === 'ENOENT')
|
|
271
|
+
return undefined
|
|
185
272
|
throw err
|
|
186
273
|
})
|
|
187
274
|
})
|
|
@@ -209,10 +296,14 @@ function ls (cache) {
|
|
|
209
296
|
)
|
|
210
297
|
}
|
|
211
298
|
|
|
299
|
+
module.exports.bucketEntries = bucketEntries
|
|
300
|
+
|
|
212
301
|
function bucketEntries (bucket, filter) {
|
|
213
302
|
return readFile(bucket, 'utf8').then((data) => _bucketEntries(data, filter))
|
|
214
303
|
}
|
|
215
304
|
|
|
305
|
+
module.exports.bucketEntries.sync = bucketEntriesSync
|
|
306
|
+
|
|
216
307
|
function bucketEntriesSync (bucket, filter) {
|
|
217
308
|
const data = fs.readFileSync(bucket, 'utf8')
|
|
218
309
|
return _bucketEntries(data, filter)
|
|
@@ -221,9 +312,9 @@ function bucketEntriesSync (bucket, filter) {
|
|
|
221
312
|
function _bucketEntries (data, filter) {
|
|
222
313
|
const entries = []
|
|
223
314
|
data.split('\n').forEach((entry) => {
|
|
224
|
-
if (!entry)
|
|
315
|
+
if (!entry)
|
|
225
316
|
return
|
|
226
|
-
|
|
317
|
+
|
|
227
318
|
const pieces = entry.split('\t')
|
|
228
319
|
if (!pieces[1] || hashEntry(pieces[1]) !== pieces[0]) {
|
|
229
320
|
// Hash is no good! Corruption or malice? Doesn't matter!
|
|
@@ -237,9 +328,8 @@ function _bucketEntries (data, filter) {
|
|
|
237
328
|
// Entry is corrupted!
|
|
238
329
|
return
|
|
239
330
|
}
|
|
240
|
-
if (obj)
|
|
331
|
+
if (obj)
|
|
241
332
|
entries.push(obj)
|
|
242
|
-
}
|
|
243
333
|
})
|
|
244
334
|
return entries
|
|
245
335
|
}
|
|
@@ -279,26 +369,25 @@ function hash (str, digest) {
|
|
|
279
369
|
.digest('hex')
|
|
280
370
|
}
|
|
281
371
|
|
|
282
|
-
function formatEntry (cache, entry) {
|
|
372
|
+
function formatEntry (cache, entry, keepAll) {
|
|
283
373
|
// Treat null digests as deletions. They'll shadow any previous entries.
|
|
284
|
-
if (!entry.integrity)
|
|
374
|
+
if (!entry.integrity && !keepAll)
|
|
285
375
|
return null
|
|
286
|
-
|
|
376
|
+
|
|
287
377
|
return {
|
|
288
378
|
key: entry.key,
|
|
289
379
|
integrity: entry.integrity,
|
|
290
|
-
path: contentPath(cache, entry.integrity),
|
|
380
|
+
path: entry.integrity ? contentPath(cache, entry.integrity) : undefined,
|
|
291
381
|
size: entry.size,
|
|
292
382
|
time: entry.time,
|
|
293
|
-
metadata: entry.metadata
|
|
383
|
+
metadata: entry.metadata,
|
|
294
384
|
}
|
|
295
385
|
}
|
|
296
386
|
|
|
297
387
|
function readdirOrEmpty (dir) {
|
|
298
388
|
return readdir(dir).catch((err) => {
|
|
299
|
-
if (err.code === 'ENOENT' || err.code === 'ENOTDIR')
|
|
389
|
+
if (err.code === 'ENOENT' || err.code === 'ENOTDIR')
|
|
300
390
|
return []
|
|
301
|
-
}
|
|
302
391
|
|
|
303
392
|
throw err
|
|
304
393
|
})
|
package/lib/memoization.js
CHANGED
|
@@ -8,7 +8,7 @@ const MAX_AGE = 3 * 60 * 1000
|
|
|
8
8
|
const MEMOIZED = new LRU({
|
|
9
9
|
max: MAX_SIZE,
|
|
10
10
|
maxAge: MAX_AGE,
|
|
11
|
-
length: (entry, key) => key.startsWith('key:') ? entry.data.length : entry.length
|
|
11
|
+
length: (entry, key) => key.startsWith('key:') ? entry.data.length : entry.length,
|
|
12
12
|
})
|
|
13
13
|
|
|
14
14
|
module.exports.clearMemoized = clearMemoized
|
|
@@ -62,13 +62,12 @@ class ObjProxy {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
function pickMem (opts) {
|
|
65
|
-
if (!opts || !opts.memoize)
|
|
65
|
+
if (!opts || !opts.memoize)
|
|
66
66
|
return MEMOIZED
|
|
67
|
-
|
|
67
|
+
else if (opts.memoize.get && opts.memoize.set)
|
|
68
68
|
return opts.memoize
|
|
69
|
-
|
|
69
|
+
else if (typeof opts.memoize === 'object')
|
|
70
70
|
return new ObjProxy(opts.memoize)
|
|
71
|
-
|
|
71
|
+
else
|
|
72
72
|
return MEMOIZED
|
|
73
|
-
}
|
|
74
73
|
}
|
package/lib/util/disposer.js
CHANGED
|
@@ -8,9 +8,9 @@ function disposer (creatorFn, disposerFn, fn) {
|
|
|
8
8
|
.then(
|
|
9
9
|
// disposer resolved, do something with original fn's promise
|
|
10
10
|
() => {
|
|
11
|
-
if (shouldThrow)
|
|
11
|
+
if (shouldThrow)
|
|
12
12
|
throw result
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
return result
|
|
15
15
|
},
|
|
16
16
|
// Disposer fn failed, crash process
|
package/lib/util/fix-owner.js
CHANGED
|
@@ -49,9 +49,8 @@ function fixOwner (cache, filepath) {
|
|
|
49
49
|
const { uid, gid } = owner
|
|
50
50
|
|
|
51
51
|
// No need to override if it's already what we used.
|
|
52
|
-
if (self.uid === uid && self.gid === gid)
|
|
52
|
+
if (self.uid === uid && self.gid === gid)
|
|
53
53
|
return
|
|
54
|
-
}
|
|
55
54
|
|
|
56
55
|
return inflight('fixOwner: fixing ownership on ' + filepath, () =>
|
|
57
56
|
chownr(
|
|
@@ -59,9 +58,9 @@ function fixOwner (cache, filepath) {
|
|
|
59
58
|
typeof uid === 'number' ? uid : self.uid,
|
|
60
59
|
typeof gid === 'number' ? gid : self.gid
|
|
61
60
|
).catch((err) => {
|
|
62
|
-
if (err.code === 'ENOENT')
|
|
61
|
+
if (err.code === 'ENOENT')
|
|
63
62
|
return null
|
|
64
|
-
|
|
63
|
+
|
|
65
64
|
throw err
|
|
66
65
|
})
|
|
67
66
|
)
|
|
@@ -94,9 +93,9 @@ function fixOwnerSync (cache, filepath) {
|
|
|
94
93
|
)
|
|
95
94
|
} catch (err) {
|
|
96
95
|
// only catch ENOENT, any other error is a problem.
|
|
97
|
-
if (err.code === 'ENOENT')
|
|
96
|
+
if (err.code === 'ENOENT')
|
|
98
97
|
return null
|
|
99
|
-
|
|
98
|
+
|
|
100
99
|
throw err
|
|
101
100
|
}
|
|
102
101
|
}
|
|
@@ -111,14 +110,13 @@ function mkdirfix (cache, p, cb) {
|
|
|
111
110
|
return Promise.resolve(inferOwner(cache)).then(() => {
|
|
112
111
|
return mkdirp(p)
|
|
113
112
|
.then((made) => {
|
|
114
|
-
if (made)
|
|
113
|
+
if (made)
|
|
115
114
|
return fixOwner(cache, made).then(() => made)
|
|
116
|
-
}
|
|
117
115
|
})
|
|
118
116
|
.catch((err) => {
|
|
119
|
-
if (err.code === 'EEXIST')
|
|
117
|
+
if (err.code === 'EEXIST')
|
|
120
118
|
return fixOwner(cache, p).then(() => null)
|
|
121
|
-
|
|
119
|
+
|
|
122
120
|
throw err
|
|
123
121
|
})
|
|
124
122
|
})
|
|
@@ -138,8 +136,7 @@ function mkdirfixSync (cache, p) {
|
|
|
138
136
|
if (err.code === 'EEXIST') {
|
|
139
137
|
fixOwnerSync(cache, p)
|
|
140
138
|
return null
|
|
141
|
-
} else
|
|
139
|
+
} else
|
|
142
140
|
throw err
|
|
143
|
-
}
|
|
144
141
|
}
|
|
145
142
|
}
|
package/lib/util/move-file.js
CHANGED
|
@@ -38,19 +38,17 @@ function moveFile (src, dest) {
|
|
|
38
38
|
} else if (err.code === 'EEXIST' || err.code === 'EBUSY') {
|
|
39
39
|
// file already exists, so whatever
|
|
40
40
|
return resolve()
|
|
41
|
-
} else
|
|
41
|
+
} else
|
|
42
42
|
return reject(err)
|
|
43
|
-
|
|
44
|
-
} else {
|
|
43
|
+
} else
|
|
45
44
|
return resolve()
|
|
46
|
-
}
|
|
47
45
|
})
|
|
48
46
|
})
|
|
49
47
|
.then(() => {
|
|
50
48
|
// content should never change for any reason, so make it read-only
|
|
51
49
|
return Promise.all([
|
|
52
50
|
unlink(src),
|
|
53
|
-
!isWindows && chmod(dest, '0444')
|
|
51
|
+
!isWindows && chmod(dest, '0444'),
|
|
54
52
|
])
|
|
55
53
|
})
|
|
56
54
|
.catch(() => {
|
package/lib/util/tmp.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const fs = require('@npmcli/fs')
|
|
4
4
|
|
|
5
5
|
const fixOwner = require('./fix-owner')
|
|
6
6
|
const path = require('path')
|
|
7
|
-
const rimraf = util.promisify(require('rimraf'))
|
|
8
|
-
const uniqueFilename = require('unique-filename')
|
|
9
|
-
const { disposer } = require('./disposer')
|
|
10
7
|
|
|
11
8
|
module.exports.mkdir = mktmpdir
|
|
12
9
|
|
|
13
10
|
function mktmpdir (cache, opts = {}) {
|
|
14
11
|
const { tmpPrefix } = opts
|
|
15
|
-
const
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const tmpDir = path.join(cache, 'tmp')
|
|
13
|
+
return fs.mkdir(tmpDir, { recursive: true, owner: 'inherit' })
|
|
14
|
+
.then(() => {
|
|
15
|
+
// do not use path.join(), it drops the trailing / if tmpPrefix is unset
|
|
16
|
+
const target = `${tmpDir}${path.sep}${tmpPrefix || ''}`
|
|
17
|
+
return fs.mkdtemp(target, { owner: 'inherit' })
|
|
18
|
+
})
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
module.exports.withTmp = withTmp
|
|
@@ -25,7 +25,7 @@ function withTmp (cache, opts, cb) {
|
|
|
25
25
|
cb = opts
|
|
26
26
|
opts = {}
|
|
27
27
|
}
|
|
28
|
-
return
|
|
28
|
+
return fs.withTempDir(path.join(cache, 'tmp'), cb, opts)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
module.exports.fix = fixtmpdir
|
package/lib/verify.js
CHANGED
|
@@ -24,7 +24,7 @@ const readFile = util.promisify(fs.readFile)
|
|
|
24
24
|
const verifyOpts = (opts) => ({
|
|
25
25
|
concurrency: 20,
|
|
26
26
|
log: { silly () {} },
|
|
27
|
-
...opts
|
|
27
|
+
...opts,
|
|
28
28
|
})
|
|
29
29
|
|
|
30
30
|
module.exports = verify
|
|
@@ -40,7 +40,7 @@ function verify (cache, opts) {
|
|
|
40
40
|
rebuildIndex,
|
|
41
41
|
cleanTmp,
|
|
42
42
|
writeVerifile,
|
|
43
|
-
markEndTime
|
|
43
|
+
markEndTime,
|
|
44
44
|
]
|
|
45
45
|
|
|
46
46
|
return steps
|
|
@@ -54,9 +54,9 @@ function verify (cache, opts) {
|
|
|
54
54
|
stats[k] = s[k]
|
|
55
55
|
})
|
|
56
56
|
const end = new Date()
|
|
57
|
-
if (!stats.runTime)
|
|
57
|
+
if (!stats.runTime)
|
|
58
58
|
stats.runTime = {}
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
stats.runTime[label] = end - start
|
|
61
61
|
return Promise.resolve(stats)
|
|
62
62
|
})
|
|
@@ -108,9 +108,9 @@ function garbageCollect (cache, opts) {
|
|
|
108
108
|
const indexStream = index.lsStream(cache)
|
|
109
109
|
const liveContent = new Set()
|
|
110
110
|
indexStream.on('data', (entry) => {
|
|
111
|
-
if (opts.filter && !opts.filter(entry))
|
|
111
|
+
if (opts.filter && !opts.filter(entry))
|
|
112
112
|
return
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
liveContent.add(entry.integrity.toString())
|
|
115
115
|
})
|
|
116
116
|
return new Promise((resolve, reject) => {
|
|
@@ -120,14 +120,14 @@ function garbageCollect (cache, opts) {
|
|
|
120
120
|
return glob(path.join(contentDir, '**'), {
|
|
121
121
|
follow: false,
|
|
122
122
|
nodir: true,
|
|
123
|
-
nosort: true
|
|
123
|
+
nosort: true,
|
|
124
124
|
}).then((files) => {
|
|
125
125
|
return Promise.resolve({
|
|
126
126
|
verifiedContent: 0,
|
|
127
127
|
reclaimedCount: 0,
|
|
128
128
|
reclaimedSize: 0,
|
|
129
129
|
badContentCount: 0,
|
|
130
|
-
keptSize: 0
|
|
130
|
+
keptSize: 0,
|
|
131
131
|
}).then((stats) =>
|
|
132
132
|
pMap(
|
|
133
133
|
files,
|
|
@@ -171,14 +171,14 @@ function verifyContent (filepath, sri) {
|
|
|
171
171
|
.then((s) => {
|
|
172
172
|
const contentInfo = {
|
|
173
173
|
size: s.size,
|
|
174
|
-
valid: true
|
|
174
|
+
valid: true,
|
|
175
175
|
}
|
|
176
176
|
return ssri
|
|
177
177
|
.checkStream(new fsm.ReadStream(filepath), sri)
|
|
178
178
|
.catch((err) => {
|
|
179
|
-
if (err.code !== 'EINTEGRITY')
|
|
179
|
+
if (err.code !== 'EINTEGRITY')
|
|
180
180
|
throw err
|
|
181
|
-
|
|
181
|
+
|
|
182
182
|
return rimraf(filepath).then(() => {
|
|
183
183
|
contentInfo.valid = false
|
|
184
184
|
})
|
|
@@ -186,9 +186,9 @@ function verifyContent (filepath, sri) {
|
|
|
186
186
|
.then(() => contentInfo)
|
|
187
187
|
})
|
|
188
188
|
.catch((err) => {
|
|
189
|
-
if (err.code === 'ENOENT')
|
|
189
|
+
if (err.code === 'ENOENT')
|
|
190
190
|
return { size: 0, valid: false }
|
|
191
|
-
|
|
191
|
+
|
|
192
192
|
throw err
|
|
193
193
|
})
|
|
194
194
|
}
|
|
@@ -199,7 +199,7 @@ function rebuildIndex (cache, opts) {
|
|
|
199
199
|
const stats = {
|
|
200
200
|
missingContent: 0,
|
|
201
201
|
rejectedEntries: 0,
|
|
202
|
-
totalEntries: 0
|
|
202
|
+
totalEntries: 0,
|
|
203
203
|
}
|
|
204
204
|
const buckets = {}
|
|
205
205
|
for (const k in entries) {
|
|
@@ -209,9 +209,9 @@ function rebuildIndex (cache, opts) {
|
|
|
209
209
|
const entry = entries[k]
|
|
210
210
|
const excluded = opts.filter && !opts.filter(entry)
|
|
211
211
|
excluded && stats.rejectedEntries++
|
|
212
|
-
if (buckets[hashed] && !excluded)
|
|
212
|
+
if (buckets[hashed] && !excluded)
|
|
213
213
|
buckets[hashed].push(entry)
|
|
214
|
-
|
|
214
|
+
else if (buckets[hashed] && excluded) {
|
|
215
215
|
// skip
|
|
216
216
|
} else if (excluded) {
|
|
217
217
|
buckets[hashed] = []
|
|
@@ -244,7 +244,7 @@ function rebuildBucket (cache, bucket, stats, opts) {
|
|
|
244
244
|
return index
|
|
245
245
|
.insert(cache, entry.key, entry.integrity, {
|
|
246
246
|
metadata: entry.metadata,
|
|
247
|
-
size: entry.size
|
|
247
|
+
size: entry.size,
|
|
248
248
|
})
|
|
249
249
|
.then(() => {
|
|
250
250
|
stats.totalEntries++
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cacache",
|
|
3
|
-
"version": "15.0
|
|
3
|
+
"version": "15.3.0",
|
|
4
4
|
"cache-version": {
|
|
5
5
|
"content": "2",
|
|
6
6
|
"index": "5"
|
|
@@ -13,15 +13,17 @@
|
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
15
|
"benchmarks": "node test/benchmarks",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"prepublishOnly": "git push --follow-tags",
|
|
20
|
-
"prerelease": "npm t",
|
|
21
|
-
"release": "standard-version -s",
|
|
16
|
+
"preversion": "npm test",
|
|
17
|
+
"postversion": "npm publish",
|
|
18
|
+
"prepublishOnly": "git push origin --follow-tags",
|
|
22
19
|
"test": "tap",
|
|
20
|
+
"snap": "tap",
|
|
23
21
|
"coverage": "tap",
|
|
24
|
-
"test-docker": "docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test"
|
|
22
|
+
"test-docker": "docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test",
|
|
23
|
+
"lint": "npm run npmclilint -- \"*.*js\" \"lib/**/*.*js\" \"test/**/*.*js\"",
|
|
24
|
+
"npmclilint": "npmcli-lint",
|
|
25
|
+
"lintfix": "npm run lint -- --fix",
|
|
26
|
+
"postsnap": "npm run lintfix --"
|
|
25
27
|
},
|
|
26
28
|
"repository": "https://github.com/npm/cacache",
|
|
27
29
|
"keywords": [
|
|
@@ -39,25 +41,9 @@
|
|
|
39
41
|
"disk cache",
|
|
40
42
|
"disk storage"
|
|
41
43
|
],
|
|
42
|
-
"author": {
|
|
43
|
-
"name": "Kat Marchán",
|
|
44
|
-
"email": "kzm@sykosomatic.org",
|
|
45
|
-
"twitter": "maybekatz"
|
|
46
|
-
},
|
|
47
|
-
"contributors": [
|
|
48
|
-
{
|
|
49
|
-
"name": "Charlotte Spencer",
|
|
50
|
-
"email": "charlottelaspencer@gmail.com",
|
|
51
|
-
"twitter": "charlotteis"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"name": "Rebecca Turner",
|
|
55
|
-
"email": "me@re-becca.org",
|
|
56
|
-
"twitter": "ReBeccaOrg"
|
|
57
|
-
}
|
|
58
|
-
],
|
|
59
44
|
"license": "ISC",
|
|
60
45
|
"dependencies": {
|
|
46
|
+
"@npmcli/fs": "^1.0.0",
|
|
61
47
|
"@npmcli/move-file": "^1.0.1",
|
|
62
48
|
"chownr": "^2.0.0",
|
|
63
49
|
"fs-minipass": "^2.0.0",
|
|
@@ -72,18 +58,17 @@
|
|
|
72
58
|
"p-map": "^4.0.0",
|
|
73
59
|
"promise-inflight": "^1.0.1",
|
|
74
60
|
"rimraf": "^3.0.2",
|
|
75
|
-
"ssri": "^8.0.
|
|
61
|
+
"ssri": "^8.0.1",
|
|
76
62
|
"tar": "^6.0.2",
|
|
77
63
|
"unique-filename": "^1.1.1"
|
|
78
64
|
},
|
|
79
65
|
"devDependencies": {
|
|
66
|
+
"@npmcli/lint": "^1.0.1",
|
|
80
67
|
"benchmark": "^2.1.4",
|
|
81
68
|
"chalk": "^4.0.0",
|
|
82
69
|
"require-inject": "^1.4.4",
|
|
83
|
-
"standard": "^14.3.1",
|
|
84
|
-
"standard-version": "^7.1.0",
|
|
85
70
|
"tacks": "^1.3.0",
|
|
86
|
-
"tap": "^
|
|
71
|
+
"tap": "^15.0.9"
|
|
87
72
|
},
|
|
88
73
|
"tap": {
|
|
89
74
|
"100": true,
|