cacache 12.0.2 → 13.0.1
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/CHANGELOG.md +100 -1
- package/README.md +3 -27
- package/get.js +158 -139
- package/index.js +39 -1
- package/lib/content/path.js +7 -5
- package/lib/content/read.js +120 -54
- package/lib/content/rm.js +5 -4
- package/lib/content/write.js +120 -97
- package/lib/entry-index.js +135 -112
- package/lib/memoization.js +15 -10
- package/lib/util/disposer.js +30 -0
- package/lib/util/fix-owner.js +42 -19
- package/lib/util/hash-to-segments.js +1 -5
- package/lib/util/move-file.js +29 -24
- package/lib/util/tmp.js +8 -3
- package/lib/verify.js +161 -97
- package/ls.js +1 -1
- package/package.json +20 -22
- package/put.js +56 -48
- package/rm.js +5 -2
- package/README.es.md +0 -628
- package/en.js +0 -3
- package/es.js +0 -3
- package/lib/util/y.js +0 -25
- package/locales/en.js +0 -47
- package/locales/en.json +0 -7
- package/locales/es.js +0 -49
- package/locales/es.json +0 -6
package/lib/content/read.js
CHANGED
|
@@ -1,86 +1,109 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const util = require('util')
|
|
4
4
|
|
|
5
|
-
const contentPath = require('./path')
|
|
6
5
|
const figgyPudding = require('figgy-pudding')
|
|
7
6
|
const fs = require('graceful-fs')
|
|
8
|
-
const
|
|
9
|
-
const pipe = BB.promisify(require('mississippi').pipe)
|
|
7
|
+
const fsm = require('fs-minipass')
|
|
10
8
|
const ssri = require('ssri')
|
|
11
|
-
const
|
|
9
|
+
const contentPath = require('./path')
|
|
10
|
+
const Pipeline = require('minipass-pipeline')
|
|
12
11
|
|
|
13
|
-
const
|
|
14
|
-
const
|
|
12
|
+
const lstat = util.promisify(fs.lstat)
|
|
13
|
+
const readFile = util.promisify(fs.readFile)
|
|
15
14
|
|
|
16
15
|
const ReadOpts = figgyPudding({
|
|
17
16
|
size: {}
|
|
18
17
|
})
|
|
19
18
|
|
|
20
19
|
module.exports = read
|
|
20
|
+
|
|
21
|
+
const MAX_SINGLE_READ_SIZE = 64 * 1024 * 1024
|
|
21
22
|
function read (cache, integrity, opts) {
|
|
22
23
|
opts = ReadOpts(opts)
|
|
23
24
|
return withContentSri(cache, integrity, (cpath, sri) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
// get size
|
|
26
|
+
return lstat(cpath).then(stat => ({ stat, cpath, sri }))
|
|
27
|
+
}).then(({ stat, cpath, sri }) => {
|
|
28
|
+
if (typeof opts.size === 'number' && stat.size !== opts.size) {
|
|
29
|
+
throw sizeError(opts.size, stat.size)
|
|
30
|
+
}
|
|
31
|
+
if (stat.size > MAX_SINGLE_READ_SIZE) {
|
|
32
|
+
return readPipeline(cpath, stat.size, sri, new Pipeline()).concat()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return readFile(cpath, null).then((data) => {
|
|
36
|
+
if (!ssri.checkData(data, sri)) {
|
|
30
37
|
throw integrityError(sri, cpath)
|
|
31
38
|
}
|
|
39
|
+
return data
|
|
32
40
|
})
|
|
33
41
|
})
|
|
34
42
|
}
|
|
35
43
|
|
|
44
|
+
const readPipeline = (cpath, size, sri, stream) => {
|
|
45
|
+
stream.push(
|
|
46
|
+
new fsm.ReadStream(cpath, {
|
|
47
|
+
size,
|
|
48
|
+
readSize: MAX_SINGLE_READ_SIZE
|
|
49
|
+
}),
|
|
50
|
+
ssri.integrityStream({
|
|
51
|
+
integrity: sri,
|
|
52
|
+
size
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
return stream
|
|
56
|
+
}
|
|
57
|
+
|
|
36
58
|
module.exports.sync = readSync
|
|
59
|
+
|
|
37
60
|
function readSync (cache, integrity, opts) {
|
|
38
61
|
opts = ReadOpts(opts)
|
|
39
62
|
return withContentSriSync(cache, integrity, (cpath, sri) => {
|
|
40
63
|
const data = fs.readFileSync(cpath)
|
|
41
64
|
if (typeof opts.size === 'number' && opts.size !== data.length) {
|
|
42
65
|
throw sizeError(opts.size, data.length)
|
|
43
|
-
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (ssri.checkData(data, sri)) {
|
|
44
69
|
return data
|
|
45
|
-
} else {
|
|
46
|
-
throw integrityError(sri, cpath)
|
|
47
70
|
}
|
|
71
|
+
|
|
72
|
+
throw integrityError(sri, cpath)
|
|
48
73
|
})
|
|
49
74
|
}
|
|
50
75
|
|
|
51
76
|
module.exports.stream = readStream
|
|
52
77
|
module.exports.readStream = readStream
|
|
78
|
+
|
|
53
79
|
function readStream (cache, integrity, opts) {
|
|
54
80
|
opts = ReadOpts(opts)
|
|
55
|
-
|
|
81
|
+
|
|
82
|
+
const stream = new Pipeline()
|
|
56
83
|
withContentSri(cache, integrity, (cpath, sri) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
)
|
|
67
|
-
}).catch(err => {
|
|
68
|
-
stream.emit('error', err)
|
|
69
|
-
})
|
|
84
|
+
// just lstat to ensure it exists
|
|
85
|
+
return lstat(cpath).then((stat) => ({ stat, cpath, sri }))
|
|
86
|
+
}).then(({ stat, cpath, sri }) => {
|
|
87
|
+
if (typeof opts.size === 'number' && opts.size !== stat.size) {
|
|
88
|
+
return stream.emit('error', sizeError(opts.size, stat.size))
|
|
89
|
+
}
|
|
90
|
+
readPipeline(cpath, stat.size, sri, stream)
|
|
91
|
+
}, er => stream.emit('error', er))
|
|
92
|
+
|
|
70
93
|
return stream
|
|
71
94
|
}
|
|
72
95
|
|
|
73
|
-
let
|
|
96
|
+
let copyFile
|
|
74
97
|
if (fs.copyFile) {
|
|
75
98
|
module.exports.copy = copy
|
|
76
99
|
module.exports.copy.sync = copySync
|
|
77
|
-
|
|
100
|
+
copyFile = util.promisify(fs.copyFile)
|
|
78
101
|
}
|
|
79
102
|
|
|
80
103
|
function copy (cache, integrity, dest, opts) {
|
|
81
104
|
opts = ReadOpts(opts)
|
|
82
105
|
return withContentSri(cache, integrity, (cpath, sri) => {
|
|
83
|
-
return
|
|
106
|
+
return copyFile(cpath, dest)
|
|
84
107
|
})
|
|
85
108
|
}
|
|
86
109
|
|
|
@@ -92,12 +115,17 @@ function copySync (cache, integrity, dest, opts) {
|
|
|
92
115
|
}
|
|
93
116
|
|
|
94
117
|
module.exports.hasContent = hasContent
|
|
118
|
+
|
|
95
119
|
function hasContent (cache, integrity) {
|
|
96
|
-
if (!integrity) {
|
|
120
|
+
if (!integrity) {
|
|
121
|
+
return Promise.resolve(false)
|
|
122
|
+
}
|
|
97
123
|
return withContentSri(cache, integrity, (cpath, sri) => {
|
|
98
|
-
return
|
|
99
|
-
}).catch(err => {
|
|
100
|
-
if (err.code === 'ENOENT') {
|
|
124
|
+
return lstat(cpath).then((stat) => ({ size: stat.size, sri, stat }))
|
|
125
|
+
}).catch((err) => {
|
|
126
|
+
if (err.code === 'ENOENT') {
|
|
127
|
+
return false
|
|
128
|
+
}
|
|
101
129
|
if (err.code === 'EPERM') {
|
|
102
130
|
if (process.platform !== 'win32') {
|
|
103
131
|
throw err
|
|
@@ -109,14 +137,19 @@ function hasContent (cache, integrity) {
|
|
|
109
137
|
}
|
|
110
138
|
|
|
111
139
|
module.exports.hasContent.sync = hasContentSync
|
|
140
|
+
|
|
112
141
|
function hasContentSync (cache, integrity) {
|
|
113
|
-
if (!integrity) {
|
|
142
|
+
if (!integrity) {
|
|
143
|
+
return false
|
|
144
|
+
}
|
|
114
145
|
return withContentSriSync(cache, integrity, (cpath, sri) => {
|
|
115
146
|
try {
|
|
116
147
|
const stat = fs.lstatSync(cpath)
|
|
117
148
|
return { size: stat.size, sri, stat }
|
|
118
149
|
} catch (err) {
|
|
119
|
-
if (err.code === 'ENOENT') {
|
|
150
|
+
if (err.code === 'ENOENT') {
|
|
151
|
+
return false
|
|
152
|
+
}
|
|
120
153
|
if (err.code === 'EPERM') {
|
|
121
154
|
if (process.platform !== 'win32') {
|
|
122
155
|
throw err
|
|
@@ -129,30 +162,61 @@ function hasContentSync (cache, integrity) {
|
|
|
129
162
|
}
|
|
130
163
|
|
|
131
164
|
function withContentSri (cache, integrity, fn) {
|
|
132
|
-
|
|
165
|
+
const tryFn = () => {
|
|
133
166
|
const sri = ssri.parse(integrity)
|
|
134
167
|
// If `integrity` has multiple entries, pick the first digest
|
|
135
168
|
// with available local data.
|
|
136
169
|
const algo = sri.pickAlgorithm()
|
|
137
170
|
const digests = sri[algo]
|
|
171
|
+
|
|
138
172
|
if (digests.length <= 1) {
|
|
139
173
|
const cpath = contentPath(cache, digests[0])
|
|
140
174
|
return fn(cpath, digests[0])
|
|
141
175
|
} else {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
176
|
+
// Can't use race here because a generic error can happen before a ENOENT error, and can happen before a valid result
|
|
177
|
+
return Promise
|
|
178
|
+
.all(sri[sri.pickAlgorithm()].map((meta) => {
|
|
179
|
+
return withContentSri(cache, meta, fn)
|
|
180
|
+
.catch((err) => {
|
|
181
|
+
if (err.code === 'ENOENT') {
|
|
182
|
+
return Object.assign(
|
|
183
|
+
new Error('No matching content found for ' + sri.toString()),
|
|
184
|
+
{ code: 'ENOENT' }
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
return err
|
|
188
|
+
})
|
|
189
|
+
}))
|
|
190
|
+
.then((results) => {
|
|
191
|
+
// Return the first non error if it is found
|
|
192
|
+
const result = results.find((r) => !(r instanceof Error))
|
|
193
|
+
if (result) {
|
|
194
|
+
return result
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Throw the No matching content found error
|
|
198
|
+
const enoentError = results.find((r) => r.code === 'ENOENT')
|
|
199
|
+
if (enoentError) {
|
|
200
|
+
throw enoentError
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Throw generic error
|
|
204
|
+
const genericError = results.find((r) => r instanceof Error)
|
|
205
|
+
if (genericError) {
|
|
206
|
+
throw genericError
|
|
153
207
|
}
|
|
154
208
|
})
|
|
155
209
|
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return new Promise((resolve, reject) => {
|
|
213
|
+
try {
|
|
214
|
+
tryFn()
|
|
215
|
+
.then(resolve)
|
|
216
|
+
.catch(reject)
|
|
217
|
+
} catch (err) {
|
|
218
|
+
reject(err)
|
|
219
|
+
}
|
|
156
220
|
})
|
|
157
221
|
}
|
|
158
222
|
|
|
@@ -174,12 +238,14 @@ function withContentSriSync (cache, integrity, fn) {
|
|
|
174
238
|
lastErr = err
|
|
175
239
|
}
|
|
176
240
|
}
|
|
177
|
-
if (lastErr) {
|
|
241
|
+
if (lastErr) {
|
|
242
|
+
throw lastErr
|
|
243
|
+
}
|
|
178
244
|
}
|
|
179
245
|
}
|
|
180
246
|
|
|
181
247
|
function sizeError (expected, found) {
|
|
182
|
-
|
|
248
|
+
const err = new Error(`Bad data size: expected inserted data to be ${expected} bytes, but got ${found} instead`)
|
|
183
249
|
err.expected = expected
|
|
184
250
|
err.found = found
|
|
185
251
|
err.code = 'EBADSIZE'
|
|
@@ -187,7 +253,7 @@ function sizeError (expected, found) {
|
|
|
187
253
|
}
|
|
188
254
|
|
|
189
255
|
function integrityError (sri, path) {
|
|
190
|
-
|
|
256
|
+
const err = new Error(`Integrity verification failed for ${sri} (${path})`)
|
|
191
257
|
err.code = 'EINTEGRITY'
|
|
192
258
|
err.sri = sri
|
|
193
259
|
err.path = path
|
package/lib/content/rm.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const util = require('util')
|
|
4
4
|
|
|
5
5
|
const contentPath = require('./path')
|
|
6
|
-
const hasContent = require('./read')
|
|
7
|
-
const rimraf =
|
|
6
|
+
const { hasContent } = require('./read')
|
|
7
|
+
const rimraf = util.promisify(require('rimraf'))
|
|
8
8
|
|
|
9
9
|
module.exports = rm
|
|
10
|
+
|
|
10
11
|
function rm (cache, integrity) {
|
|
11
|
-
return hasContent(cache, integrity).then(content => {
|
|
12
|
+
return hasContent(cache, integrity).then((content) => {
|
|
12
13
|
if (content) {
|
|
13
14
|
const sri = content.sri
|
|
14
15
|
if (sri) {
|
package/lib/content/write.js
CHANGED
|
@@ -1,152 +1,175 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const util = require('util')
|
|
4
4
|
|
|
5
5
|
const contentPath = require('./path')
|
|
6
6
|
const fixOwner = require('../util/fix-owner')
|
|
7
7
|
const fs = require('graceful-fs')
|
|
8
8
|
const moveFile = require('../util/move-file')
|
|
9
|
-
const
|
|
9
|
+
const Minipass = require('minipass')
|
|
10
|
+
const Pipeline = require('minipass-pipeline')
|
|
11
|
+
const Flush = require('minipass-flush')
|
|
10
12
|
const path = require('path')
|
|
11
|
-
const
|
|
12
|
-
const rimraf = BB.promisify(require('rimraf'))
|
|
13
|
+
const rimraf = util.promisify(require('rimraf'))
|
|
13
14
|
const ssri = require('ssri')
|
|
14
|
-
const to = require('mississippi').to
|
|
15
15
|
const uniqueFilename = require('unique-filename')
|
|
16
|
-
const
|
|
16
|
+
const { disposer } = require('./../util/disposer')
|
|
17
|
+
const fsm = require('fs-minipass')
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const writeFile = util.promisify(fs.writeFile)
|
|
19
20
|
|
|
20
21
|
module.exports = write
|
|
22
|
+
|
|
21
23
|
function write (cache, data, opts) {
|
|
22
24
|
opts = opts || {}
|
|
23
25
|
if (opts.algorithms && opts.algorithms.length > 1) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
Y`opts.algorithms only supports a single algorithm for now`
|
|
26
|
-
)
|
|
26
|
+
throw new Error('opts.algorithms only supports a single algorithm for now')
|
|
27
27
|
}
|
|
28
28
|
if (typeof opts.size === 'number' && data.length !== opts.size) {
|
|
29
|
-
return
|
|
29
|
+
return Promise.reject(sizeError(opts.size, data.length))
|
|
30
30
|
}
|
|
31
31
|
const sri = ssri.fromData(data, {
|
|
32
32
|
algorithms: opts.algorithms
|
|
33
33
|
})
|
|
34
34
|
if (opts.integrity && !ssri.checkData(data, opts.integrity, opts)) {
|
|
35
|
-
return
|
|
35
|
+
return Promise.reject(checksumError(opts.integrity, sri))
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
|
|
37
|
+
|
|
38
|
+
return disposer(makeTmp(cache, opts), makeTmpDisposer,
|
|
39
|
+
(tmp) => {
|
|
40
|
+
return writeFile(tmp.target, data, { flag: 'wx' })
|
|
41
|
+
.then(() => moveToDestination(tmp, cache, sri, opts))
|
|
42
|
+
})
|
|
43
|
+
.then(() => ({ integrity: sri, size: data.length }))
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
module.exports.stream = writeStream
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
|
|
48
|
+
// writes proxied to the 'inputStream' that is passed to the Promise
|
|
49
|
+
// 'end' is deferred until content is handled.
|
|
50
|
+
class CacacheWriteStream extends Flush {
|
|
51
|
+
constructor (cache, opts) {
|
|
52
|
+
super()
|
|
53
|
+
this.opts = opts
|
|
54
|
+
this.cache = cache
|
|
55
|
+
this.inputStream = new Minipass()
|
|
56
|
+
this.inputStream.on('error', er => this.emit('error', er))
|
|
57
|
+
this.inputStream.on('drain', () => this.emit('drain'))
|
|
58
|
+
this.handleContentP = null
|
|
53
59
|
}
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
write (chunk, encoding, cb) {
|
|
62
|
+
if (!this.handleContentP) {
|
|
63
|
+
this.handleContentP = handleContent(
|
|
64
|
+
this.inputStream,
|
|
65
|
+
this.cache,
|
|
66
|
+
this.opts
|
|
67
|
+
)
|
|
59
68
|
}
|
|
60
|
-
inputStream.write(
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
return this.inputStream.write(chunk, encoding, cb)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
flush (cb) {
|
|
73
|
+
this.inputStream.end(() => {
|
|
74
|
+
if (!this.handleContentP) {
|
|
75
|
+
const e = new Error('Cache input stream was empty')
|
|
65
76
|
e.code = 'ENODATA'
|
|
66
|
-
|
|
77
|
+
// empty streams are probably emitting end right away.
|
|
78
|
+
// defer this one tick by rejecting a promise on it.
|
|
79
|
+
return Promise.reject(e).catch(cb)
|
|
67
80
|
}
|
|
68
|
-
|
|
69
|
-
res
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
this.handleContentP.then(
|
|
82
|
+
(res) => {
|
|
83
|
+
res.integrity && this.emit('integrity', res.integrity)
|
|
84
|
+
res.size !== null && this.emit('size', res.size)
|
|
85
|
+
cb()
|
|
86
|
+
},
|
|
87
|
+
(er) => cb(er)
|
|
88
|
+
)
|
|
75
89
|
})
|
|
76
|
-
}
|
|
77
|
-
ret.once('error', e => {
|
|
78
|
-
inputErr = e
|
|
79
|
-
})
|
|
80
|
-
return ret
|
|
90
|
+
}
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
function
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
function writeStream (cache, opts) {
|
|
94
|
+
opts = opts || {}
|
|
95
|
+
return new CacacheWriteStream(cache, opts)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function handleContent (inputStream, cache, opts) {
|
|
99
|
+
return disposer(makeTmp(cache, opts), makeTmpDisposer, (tmp) => {
|
|
100
|
+
return pipeToTmp(inputStream, cache, tmp.target, opts)
|
|
101
|
+
.then((res) => {
|
|
102
|
+
return moveToDestination(
|
|
103
|
+
tmp,
|
|
104
|
+
cache,
|
|
105
|
+
res.integrity,
|
|
106
|
+
opts
|
|
107
|
+
).then(() => res)
|
|
108
|
+
})
|
|
93
109
|
})
|
|
94
110
|
}
|
|
95
111
|
|
|
96
|
-
function pipeToTmp (inputStream, cache, tmpTarget, opts
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const outStream = fs.createWriteStream(tmpTarget, {
|
|
110
|
-
flags: 'wx'
|
|
111
|
-
})
|
|
112
|
-
errCheck()
|
|
113
|
-
return pipe(inputStream, hashStream, outStream).then(() => {
|
|
114
|
-
return { integrity, size }
|
|
115
|
-
}).catch(err => {
|
|
116
|
-
return rimraf(tmpTarget).then(() => { throw err })
|
|
117
|
-
})
|
|
112
|
+
function pipeToTmp (inputStream, cache, tmpTarget, opts) {
|
|
113
|
+
let integrity
|
|
114
|
+
let size
|
|
115
|
+
const hashStream = ssri.integrityStream({
|
|
116
|
+
integrity: opts.integrity,
|
|
117
|
+
algorithms: opts.algorithms,
|
|
118
|
+
size: opts.size
|
|
119
|
+
})
|
|
120
|
+
hashStream.on('integrity', i => { integrity = i })
|
|
121
|
+
hashStream.on('size', s => { size = s })
|
|
122
|
+
|
|
123
|
+
const outStream = new fsm.WriteStream(tmpTarget, {
|
|
124
|
+
flags: 'wx'
|
|
118
125
|
})
|
|
126
|
+
|
|
127
|
+
// NB: this can throw if the hashStream has a problem with
|
|
128
|
+
// it, and the data is fully written. but pipeToTmp is only
|
|
129
|
+
// called in promisory contexts where that is handled.
|
|
130
|
+
const pipeline = new Pipeline(
|
|
131
|
+
inputStream,
|
|
132
|
+
hashStream,
|
|
133
|
+
outStream
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
return pipeline.promise()
|
|
137
|
+
.then(() => ({ integrity, size }))
|
|
138
|
+
.catch(er => rimraf(tmpTarget).then(() => { throw er }))
|
|
119
139
|
}
|
|
120
140
|
|
|
121
141
|
function makeTmp (cache, opts) {
|
|
122
142
|
const tmpTarget = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix)
|
|
123
|
-
return fixOwner.mkdirfix(
|
|
124
|
-
cache, path.dirname(tmpTarget)
|
|
125
|
-
).then(() => ({
|
|
143
|
+
return fixOwner.mkdirfix(cache, path.dirname(tmpTarget)).then(() => ({
|
|
126
144
|
target: tmpTarget,
|
|
127
145
|
moved: false
|
|
128
|
-
}))
|
|
146
|
+
}))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function makeTmpDisposer (tmp) {
|
|
150
|
+
if (tmp.moved) {
|
|
151
|
+
return Promise.resolve()
|
|
152
|
+
}
|
|
153
|
+
return rimraf(tmp.target)
|
|
129
154
|
}
|
|
130
155
|
|
|
131
|
-
function moveToDestination (tmp, cache, sri, opts
|
|
132
|
-
errCheck && errCheck()
|
|
156
|
+
function moveToDestination (tmp, cache, sri, opts) {
|
|
133
157
|
const destination = contentPath(cache, sri)
|
|
134
158
|
const destDir = path.dirname(destination)
|
|
135
159
|
|
|
136
|
-
return fixOwner
|
|
137
|
-
cache, destDir
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
})
|
|
160
|
+
return fixOwner
|
|
161
|
+
.mkdirfix(cache, destDir)
|
|
162
|
+
.then(() => {
|
|
163
|
+
return moveFile(tmp.target, destination)
|
|
164
|
+
})
|
|
165
|
+
.then(() => {
|
|
166
|
+
tmp.moved = true
|
|
167
|
+
return fixOwner.chownr(cache, destination)
|
|
168
|
+
})
|
|
146
169
|
}
|
|
147
170
|
|
|
148
171
|
function sizeError (expected, found) {
|
|
149
|
-
|
|
172
|
+
const err = new Error(`Bad data size: expected inserted data to be ${expected} bytes, but got ${found} instead`)
|
|
150
173
|
err.expected = expected
|
|
151
174
|
err.found = found
|
|
152
175
|
err.code = 'EBADSIZE'
|
|
@@ -154,7 +177,7 @@ function sizeError (expected, found) {
|
|
|
154
177
|
}
|
|
155
178
|
|
|
156
179
|
function checksumError (expected, found) {
|
|
157
|
-
|
|
180
|
+
const err = new Error(`Integrity check failed:
|
|
158
181
|
Wanted: ${expected}
|
|
159
182
|
Found: ${found}`)
|
|
160
183
|
err.code = 'EINTEGRITY'
|