@@ -7,6 +7,10 @@ import Git from '../util/git.js';
7
7
import * as fsUtil from '../util/fs.js' ;
8
8
import * as constants from '../constants.js' ;
9
9
import * as crypto from '../util/crypto.js' ;
10
+ import { install } from '../cli/commands/install.js' ;
11
+ import Lockfile from '../lockfile/wrapper.js' ;
12
+ import Config from '../config.js' ;
13
+ import { packTarball } from '../cli/commands/pack.js' ;
10
14
11
15
const tarFs = require ( 'tar-fs' ) ;
12
16
const url = require ( 'url' ) ;
@@ -15,6 +19,8 @@ const fs = require('fs');
15
19
16
20
const invariant = require ( 'invariant' ) ;
17
21
22
+ const PACKED_FLAG = '1' ;
23
+
18
24
export default class GitFetcher extends BaseFetcher {
19
25
async setupMirrorFromCache ( ) : Promise < ?string > {
20
26
const tarballMirrorPath = this . getTarballMirrorPath ( ) ;
@@ -90,11 +96,7 @@ export default class GitFetcher extends BaseFetcher {
90
96
}
91
97
92
98
return new Promise ( ( resolve , reject ) => {
93
- const untarStream = tarFs . extract ( this . dest , {
94
- dmode : 0o555 , // all dirs should be readable
95
- fmode : 0o444 , // all files should be readable
96
- chown : false , // don't chown. just leave as it is
97
- } ) ;
99
+ const untarStream = this . _createUntarStream ( this . dest ) ;
98
100
99
101
const hashStream = new crypto . HashStream ( ) ;
100
102
@@ -131,22 +133,130 @@ export default class GitFetcher extends BaseFetcher {
131
133
const gitUrl = Git . npmUrlToGitUrl ( this . reference ) ;
132
134
const git = new Git ( this . config , gitUrl , hash ) ;
133
135
await git . init ( ) ;
134
- await git . clone ( this . dest ) ;
136
+
137
+ const manifestFile = await git . getFile ( 'package.json' ) ;
138
+ if ( ! manifestFile ) {
139
+ throw new MessageError ( this . reporter . lang ( 'couldntFindPackagejson' , gitUrl ) ) ;
140
+ }
141
+ const scripts = JSON . parse ( manifestFile ) . scripts ;
142
+ const hasPrepareScript = Boolean ( scripts && scripts . prepare ) ;
143
+
144
+ if ( hasPrepareScript ) {
145
+ await this . fetchFromInstallAndPack ( git ) ;
146
+ } else {
147
+ await this . fetchFromGitArchive ( git ) ;
148
+ }
149
+
150
+ return {
151
+ hash,
152
+ } ;
153
+ }
154
+
155
+ async fetchFromInstallAndPack ( git : Git ) : Promise < void > {
156
+ const prepareDirectory = this . config . getTemp ( `${ crypto . hash ( git . gitUrl . repository ) } .${ git . hash } .prepare` ) ;
157
+ await fsUtil . unlink ( prepareDirectory ) ;
158
+
159
+ await git . clone ( prepareDirectory ) ;
160
+
161
+ const [ prepareConfig , prepareLockFile ] = await Promise . all ( [
162
+ Config . create (
163
+ {
164
+ cwd : prepareDirectory ,
165
+ disablePrepublish : true ,
166
+ } ,
167
+ this . reporter ,
168
+ ) ,
169
+ Lockfile . fromDirectory ( prepareDirectory , this . reporter ) ,
170
+ ] ) ;
171
+ await install ( prepareConfig , this . reporter , { } , prepareLockFile ) ;
135
172
136
173
const tarballMirrorPath = this . getTarballMirrorPath ( ) ;
137
174
const tarballCachePath = this . getTarballCachePath ( ) ;
138
175
176
+ if ( tarballMirrorPath ) {
177
+ await this . _packToTarball ( prepareConfig , tarballMirrorPath ) ;
178
+ }
179
+ if ( tarballCachePath ) {
180
+ await this . _packToTarball ( prepareConfig , tarballCachePath ) ;
181
+ }
182
+
183
+ await this . _packToDirectory ( prepareConfig , this . dest ) ;
184
+
185
+ await fsUtil . unlink ( prepareDirectory ) ;
186
+ }
187
+
188
+ async _packToTarball ( config : Config , path : string ) : Promise < void > {
189
+ const tarballStream = await this . _createTarballStream ( config ) ;
190
+ await new Promise ( ( resolve , reject ) => {
191
+ const writeStream = fs . createWriteStream ( path ) ;
192
+ tarballStream . on ( 'error' , reject ) ;
193
+ writeStream . on ( 'error' , reject ) ;
194
+ writeStream . on ( 'end' , resolve ) ;
195
+ writeStream . on ( 'open' , ( ) => {
196
+ tarballStream . pipe ( writeStream ) ;
197
+ } ) ;
198
+ writeStream . once ( 'finish' , resolve ) ;
199
+ } ) ;
200
+ }
201
+
202
+ async _packToDirectory ( config : Config , dest : string ) : Promise < void > {
203
+ const tarballStream = await this . _createTarballStream ( config ) ;
204
+ await new Promise ( ( resolve , reject ) => {
205
+ const untarStream = this . _createUntarStream ( dest ) ;
206
+ tarballStream . on ( 'error' , reject ) ;
207
+ untarStream . on ( 'error' , reject ) ;
208
+ untarStream . on ( 'end' , resolve ) ;
209
+ untarStream . once ( 'finish' , resolve ) ;
210
+ tarballStream . pipe ( untarStream ) ;
211
+ } ) ;
212
+ }
213
+
214
+ _createTarballStream ( config : Config ) : Promise < stream$Duplex > {
215
+ let savedPackedHeader = false ;
216
+ return packTarball ( config , {
217
+ mapHeader ( header : Object ) : Object {
218
+ if ( ! savedPackedHeader ) {
219
+ savedPackedHeader = true ;
220
+ header . pax = header . pax || { } ;
221
+ // add a custom data on the first header
222
+ // in order to distinguish a tar from "git archive" and a tar from "pack" command
223
+ header . pax . packed = PACKED_FLAG ;
224
+ }
225
+ return header ;
226
+ } ,
227
+ } ) ;
228
+ }
229
+
230
+ _createUntarStream ( dest : string ) : stream$Writable {
231
+ const PREFIX = 'package/' ;
232
+ let isPackedTarball = undefined ;
233
+ return tarFs . extract ( dest , {
234
+ dmode : 0o555 , // all dirs should be readable
235
+ fmode : 0o444 , // all files should be readable
236
+ chown : false , // don't chown. just leave as it is
237
+ map : header => {
238
+ if ( isPackedTarball === undefined ) {
239
+ isPackedTarball = header . pax && header . pax . packed === PACKED_FLAG ;
240
+ }
241
+ if ( isPackedTarball ) {
242
+ header . name = header . name . substr ( PREFIX . length ) ;
243
+ }
244
+ } ,
245
+ } ) ;
246
+ }
247
+
248
+ async fetchFromGitArchive ( git : Git ) : Promise < void > {
249
+ await git . clone ( this . dest ) ;
250
+ const tarballMirrorPath = this . getTarballMirrorPath ( ) ;
251
+ const tarballCachePath = this . getTarballCachePath ( ) ;
252
+
139
253
if ( tarballMirrorPath ) {
140
254
await git . archive ( tarballMirrorPath ) ;
141
255
}
142
256
143
257
if ( tarballCachePath ) {
144
258
await git . archive ( tarballCachePath ) ;
145
259
}
146
-
147
- return {
148
- hash,
149
- } ;
150
260
}
151
261
152
262
async _fetch ( ) : Promise < FetchedOverride > {
0 commit comments