@@ -14,7 +14,7 @@ const os = require('os')
14
14
15
15
const isWindows = os . platform ( ) === 'win32'
16
16
17
- const readDir = ( path , prefix , output = [ ] ) => {
17
+ const readDir = ( path , prefix , includeMetadata , output = [ ] ) => {
18
18
const entries = fs . readdirSync ( path )
19
19
20
20
entries . forEach ( entry => {
@@ -23,21 +23,25 @@ const readDir = (path, prefix, output = []) => {
23
23
const type = fs . statSync ( entryPath )
24
24
25
25
if ( type . isDirectory ( ) ) {
26
- readDir ( entryPath , `${ prefix } /${ entry } ` , output )
26
+ readDir ( entryPath , `${ prefix } /${ entry } ` , includeMetadata , output )
27
+
28
+ output . push ( {
29
+ path : `${ prefix } /${ entry } ` ,
30
+ mtime : includeMetadata ? new Date ( type . mtimeMs ) : undefined ,
31
+ mode : includeMetadata ? type . mode : undefined
32
+ } )
27
33
}
28
34
29
35
if ( type . isFile ( ) ) {
30
36
output . push ( {
31
37
path : `${ prefix } /${ entry } ` ,
32
- content : fs . createReadStream ( entryPath )
38
+ content : fs . createReadStream ( entryPath ) ,
39
+ mtime : includeMetadata ? new Date ( type . mtimeMs ) : undefined ,
40
+ mode : includeMetadata ? type . mode : undefined
33
41
} )
34
42
}
35
43
} )
36
44
37
- output . push ( {
38
- path : prefix
39
- } )
40
-
41
45
return output
42
46
}
43
47
@@ -75,6 +79,8 @@ describe('parser', () => {
75
79
describe ( 'single file' , ( ) => {
76
80
const filePath = path . resolve ( __dirname , 'fixtures/config' )
77
81
const fileContent = fs . readFileSync ( filePath , 'utf8' )
82
+ const fileMtime = parseInt ( Date . now ( ) / 1000 )
83
+ const fileMode = parseInt ( '0777' , 8 )
78
84
79
85
before ( ( ) => {
80
86
handler = async ( req ) => {
@@ -84,7 +90,7 @@ describe('parser', () => {
84
90
85
91
for await ( const entry of parser ( req ) ) {
86
92
if ( entry . type === 'file' ) {
87
- const file = { name : entry . name , content : '' }
93
+ const file = { ... entry , content : '' }
88
94
89
95
for await ( const data of entry . content ) {
90
96
file . content += data . toString ( )
@@ -95,13 +101,12 @@ describe('parser', () => {
95
101
}
96
102
97
103
expect ( files . length ) . to . equal ( 1 )
98
- expect ( files [ 0 ] . name ) . to . equal ( 'config' )
99
- expect ( files [ 0 ] . content ) . to . equal ( fileContent )
104
+ expect ( JSON . parse ( files [ 0 ] . content ) ) . to . deep . equal ( JSON . parse ( fileContent ) )
100
105
}
101
106
} )
102
107
103
108
it ( 'parses ctl.config.replace correctly' , async ( ) => {
104
- await ctl . config . replace ( filePath )
109
+ await ctl . config . replace ( JSON . parse ( fileContent ) )
105
110
} )
106
111
107
112
it ( 'parses regular multipart requests correctly' , ( done ) => {
@@ -111,6 +116,22 @@ describe('parser', () => {
111
116
112
117
request . post ( { url : `http://localhost:${ PORT } ` , formData : formData } , ( err ) => done ( err ) )
113
118
} )
119
+
120
+ it ( 'parses multipart requests with metadata correctly' , ( done ) => {
121
+ const formData = {
122
+ file : {
123
+ value : fileContent ,
124
+ options : {
125
+ header : {
126
+ mtime : fileMtime ,
127
+ mode : fileMode
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ request . post ( { url : `http://localhost:${ PORT } ` , formData } , ( err ) => done ( err ) )
134
+ } )
114
135
} )
115
136
116
137
describe ( 'directory' , ( ) => {
@@ -123,15 +144,15 @@ describe('parser', () => {
123
144
expect ( req . headers [ 'content-type' ] ) . to . be . a ( 'string' )
124
145
125
146
for await ( const entry of parser ( req ) ) {
126
- if ( entry . type === 'file' ) {
127
- const file = { name : entry . name , content : '' }
147
+ const file = { ...entry , content : '' }
128
148
149
+ if ( entry . content ) {
129
150
for await ( const data of entry . content ) {
130
151
file . content += data . toString ( )
131
152
}
132
-
133
- files . push ( file )
134
153
}
154
+
155
+ files . push ( file )
135
156
}
136
157
}
137
158
} )
@@ -149,12 +170,37 @@ describe('parser', () => {
149
170
return
150
171
}
151
172
152
- expect ( files . length ) . to . equal ( 5 )
153
- expect ( files [ 0 ] . name ) . to . equal ( 'fixtures/config' )
154
- expect ( files [ 1 ] . name ) . to . equal ( 'fixtures/folderlink/deepfile' )
155
- expect ( files [ 2 ] . name ) . to . equal ( 'fixtures/link' )
156
- expect ( files [ 3 ] . name ) . to . equal ( 'fixtures/otherfile' )
157
- expect ( files [ 4 ] . name ) . to . equal ( 'fixtures/subfolder/deepfile' )
173
+ expect ( files ) . to . have . lengthOf ( contents . length )
174
+
175
+ for ( let i = 0 ; i < contents . length ; i ++ ) {
176
+ expect ( files [ i ] . name ) . to . equal ( contents [ i ] . path )
177
+ expect ( files [ i ] . mode ) . to . be . undefined
178
+ expect ( files [ i ] . mtime ) . to . be . undefined
179
+ }
180
+ } )
181
+
182
+ it ( 'parses ctl.add with metadata correctly' , async ( ) => {
183
+ const contents = readDir ( dirPath , 'fixtures' , true )
184
+
185
+ await ctl . add ( contents , { recursive : true , followSymlinks : false } )
186
+
187
+ if ( isWindows ) {
188
+ return
189
+ }
190
+
191
+ expect ( files ) . to . have . lengthOf ( contents . length )
192
+
193
+ for ( let i = 0 ; i < contents . length ; i ++ ) {
194
+ const msecs = contents [ i ] . mtime . getTime ( )
195
+ const secs = Math . floor ( msecs / 1000 )
196
+
197
+ expect ( files [ i ] . name ) . to . equal ( contents [ i ] . path )
198
+ expect ( files [ i ] . mode ) . to . equal ( contents [ i ] . mode )
199
+ expect ( files [ i ] . mtime ) . to . deep . equal ( {
200
+ secs,
201
+ nsecs : ( msecs - ( secs * 1000 ) ) * 1000
202
+ } )
203
+ }
158
204
} )
159
205
} )
160
206
0 commit comments