1
1
'use strict'
2
2
3
- const util = require ( 'util' )
4
-
5
- const fs = require ( 'fs' )
3
+ const fs = require ( '@npmcli/fs' )
6
4
const fsm = require ( 'fs-minipass' )
7
5
const ssri = require ( 'ssri' )
8
6
const contentPath = require ( './path' )
9
7
const Pipeline = require ( 'minipass-pipeline' )
10
8
11
- const lstat = util . promisify ( fs . lstat )
12
- const readFile = util . promisify ( fs . readFile )
13
- const copyFile = util . promisify ( fs . copyFile )
14
-
15
9
module . exports = read
16
10
17
11
const MAX_SINGLE_READ_SIZE = 64 * 1024 * 1024
18
- function read ( cache , integrity , opts = { } ) {
12
+ async function read ( cache , integrity , opts = { } ) {
19
13
const { size } = opts
20
- return withContentSri ( cache , integrity , ( cpath , sri ) => {
14
+ const { stat , cpath , sri } = await withContentSri ( cache , integrity , async ( cpath , sri ) => {
21
15
// get size
22
- return lstat ( cpath ) . then ( stat => ( { stat, cpath, sri } ) )
23
- } ) . then ( ( { stat, cpath, sri } ) => {
24
- if ( typeof size === 'number' && stat . size !== size ) {
25
- throw sizeError ( size , stat . size )
26
- }
16
+ const stat = await fs . lstat ( cpath )
17
+ return { stat, cpath, sri }
18
+ } )
19
+ if ( typeof size === 'number' && stat . size !== size ) {
20
+ throw sizeError ( size , stat . size )
21
+ }
27
22
28
- if ( stat . size > MAX_SINGLE_READ_SIZE ) {
29
- return readPipeline ( cpath , stat . size , sri , new Pipeline ( ) ) . concat ( )
30
- }
23
+ if ( stat . size > MAX_SINGLE_READ_SIZE ) {
24
+ return readPipeline ( cpath , stat . size , sri , new Pipeline ( ) ) . concat ( )
25
+ }
31
26
32
- return readFile ( cpath , null ) . then ( ( data ) => {
33
- if ( ! ssri . checkData ( data , sri ) ) {
34
- throw integrityError ( sri , cpath )
35
- }
27
+ const data = await fs . readFile ( cpath , null )
28
+ if ( ! ssri . checkData ( data , sri ) ) {
29
+ throw integrityError ( sri , cpath )
30
+ }
36
31
37
- return data
38
- } )
39
- } )
32
+ return data
40
33
}
41
34
42
35
const readPipeline = ( cpath , size , sri , stream ) => {
@@ -77,16 +70,19 @@ module.exports.readStream = readStream
77
70
function readStream ( cache , integrity , opts = { } ) {
78
71
const { size } = opts
79
72
const stream = new Pipeline ( )
80
- withContentSri ( cache , integrity , ( cpath , sri ) => {
81
- // just lstat to ensure it exists
82
- return lstat ( cpath ) . then ( ( stat ) => ( { stat, cpath, sri } ) )
83
- } ) . then ( ( { stat, cpath, sri } ) => {
73
+ // Set all this up to run on the stream and then just return the stream
74
+ Promise . resolve ( ) . then ( async ( ) => {
75
+ const { stat, cpath, sri } = await withContentSri ( cache , integrity , async ( cpath , sri ) => {
76
+ // just lstat to ensure it exists
77
+ const stat = await fs . lstat ( cpath )
78
+ return { stat, cpath, sri }
79
+ } )
84
80
if ( typeof size === 'number' && size !== stat . size ) {
85
81
return stream . emit ( 'error' , sizeError ( size , stat . size ) )
86
82
}
87
83
88
84
readPipeline ( cpath , stat . size , sri , stream )
89
- } , er => stream . emit ( 'error' , er ) )
85
+ } ) . catch ( err => stream . emit ( 'error' , err ) )
90
86
91
87
return stream
92
88
}
@@ -96,7 +92,7 @@ module.exports.copy.sync = copySync
96
92
97
93
function copy ( cache , integrity , dest ) {
98
94
return withContentSri ( cache , integrity , ( cpath , sri ) => {
99
- return copyFile ( cpath , dest )
95
+ return fs . copyFile ( cpath , dest )
100
96
} )
101
97
}
102
98
@@ -108,14 +104,17 @@ function copySync (cache, integrity, dest) {
108
104
109
105
module . exports . hasContent = hasContent
110
106
111
- function hasContent ( cache , integrity ) {
107
+ async function hasContent ( cache , integrity ) {
112
108
if ( ! integrity ) {
113
- return Promise . resolve ( false )
109
+ return false
114
110
}
115
111
116
- return withContentSri ( cache , integrity , ( cpath , sri ) => {
117
- return lstat ( cpath ) . then ( ( stat ) => ( { size : stat . size , sri, stat } ) )
118
- } ) . catch ( ( err ) => {
112
+ try {
113
+ return await withContentSri ( cache , integrity , async ( cpath , sri ) => {
114
+ const stat = await fs . lstat ( cpath )
115
+ return { size : stat . size , sri, stat }
116
+ } )
117
+ } catch ( err ) {
119
118
if ( err . code === 'ENOENT' ) {
120
119
return false
121
120
}
@@ -128,7 +127,7 @@ function hasContent (cache, integrity) {
128
127
return false
129
128
}
130
129
}
131
- } )
130
+ }
132
131
}
133
132
134
133
module . exports . hasContent . sync = hasContentSync
@@ -159,61 +158,47 @@ function hasContentSync (cache, integrity) {
159
158
} )
160
159
}
161
160
162
- function withContentSri ( cache , integrity , fn ) {
163
- const tryFn = ( ) => {
164
- const sri = ssri . parse ( integrity )
165
- // If `integrity` has multiple entries, pick the first digest
166
- // with available local data.
167
- const algo = sri . pickAlgorithm ( )
168
- const digests = sri [ algo ]
169
-
170
- if ( digests . length <= 1 ) {
171
- const cpath = contentPath ( cache , digests [ 0 ] )
172
- return fn ( cpath , digests [ 0 ] )
173
- } else {
174
- // Can't use race here because a generic error can happen before
175
- // a ENOENT error, and can happen before a valid result
176
- return Promise
177
- . all ( digests . map ( ( meta ) => {
178
- return withContentSri ( cache , meta , fn )
179
- . catch ( ( err ) => {
180
- if ( err . code === 'ENOENT' ) {
181
- return Object . assign (
182
- new Error ( 'No matching content found for ' + sri . toString ( ) ) ,
183
- { code : 'ENOENT' }
184
- )
185
- }
186
- return err
187
- } )
188
- } ) )
189
- . then ( ( results ) => {
190
- // Return the first non error if it is found
191
- const result = results . find ( ( r ) => ! ( r instanceof Error ) )
192
- if ( result ) {
193
- return result
194
- }
195
-
196
- // Throw the No matching content found error
197
- const enoentError = results . find ( ( r ) => r . code === 'ENOENT' )
198
- if ( enoentError ) {
199
- throw enoentError
200
- }
201
-
202
- // Throw generic error
203
- throw results . find ( ( r ) => r instanceof Error )
204
- } )
161
+ async function withContentSri ( cache , integrity , fn ) {
162
+ const sri = ssri . parse ( integrity )
163
+ // If `integrity` has multiple entries, pick the first digest
164
+ // with available local data.
165
+ const algo = sri . pickAlgorithm ( )
166
+ const digests = sri [ algo ]
167
+
168
+ if ( digests . length <= 1 ) {
169
+ const cpath = contentPath ( cache , digests [ 0 ] )
170
+ return fn ( cpath , digests [ 0 ] )
171
+ } else {
172
+ // Can't use race here because a generic error can happen before
173
+ // a ENOENT error, and can happen before a valid result
174
+ const results = await Promise . all ( digests . map ( async ( meta ) => {
175
+ try {
176
+ return await withContentSri ( cache , meta , fn )
177
+ } catch ( err ) {
178
+ if ( err . code === 'ENOENT' ) {
179
+ return Object . assign (
180
+ new Error ( 'No matching content found for ' + sri . toString ( ) ) ,
181
+ { code : 'ENOENT' }
182
+ )
183
+ }
184
+ return err
185
+ }
186
+ } ) )
187
+ // Return the first non error if it is found
188
+ const result = results . find ( ( r ) => ! ( r instanceof Error ) )
189
+ if ( result ) {
190
+ return result
205
191
}
206
- }
207
192
208
- return new Promise ( ( resolve , reject ) => {
209
- try {
210
- tryFn ( )
211
- . then ( resolve )
212
- . catch ( reject )
213
- } catch ( err ) {
214
- reject ( err )
193
+ // Throw the No matching content found error
194
+ const enoentError = results . find ( ( r ) => r . code === 'ENOENT' )
195
+ if ( enoentError ) {
196
+ throw enoentError
215
197
}
216
- } )
198
+
199
+ // Throw generic error
200
+ throw results . find ( ( r ) => r instanceof Error )
201
+ }
217
202
}
218
203
219
204
function withContentSriSync ( cache , integrity , fn ) {
0 commit comments