@@ -4,6 +4,7 @@ import minimatch from 'minimatch';
4
4
import { createWriteStream } from 'fs' ;
5
5
import streamToPromise from 'stream-to-promise' ;
6
6
7
+ import defaultSourceWatcher from '../watcher' ;
7
8
import { zipDir } from '../util/zip-dir' ;
8
9
import getValidatedManifest from '../util/manifest' ;
9
10
import { prepareArtifactsDir } from '../util/artifacts' ;
@@ -12,49 +13,74 @@ import {createLogger} from '../util/logger';
12
13
const log = createLogger ( __filename ) ;
13
14
14
15
15
- export default function build (
16
- { sourceDir, artifactsDir} : Object ,
17
- { manifestData, fileFilter} : Object = { } ) : Promise {
16
+ function defaultPackageCreator (
17
+ { manifestData, sourceDir, fileFilter, artifactsDir} ) {
18
18
19
- log . info ( `Building web extension from ${ sourceDir } ` ) ;
19
+ return new Promise (
20
+ ( resolve ) => {
21
+ if ( manifestData ) {
22
+ log . debug ( `Using manifest id=${ manifestData . applications . gecko . id } ` ) ;
23
+ resolve ( manifestData ) ;
24
+ } else {
25
+ resolve ( getValidatedManifest ( sourceDir ) ) ;
26
+ }
27
+ } )
28
+ . then ( ( manifestData ) => {
29
+ return zipDir (
30
+ sourceDir , {
31
+ filter : ( ...args ) => fileFilter . wantFile ( ...args ) ,
32
+ } )
33
+ . then ( ( buffer ) => {
34
+ let packageName = safeFileName (
35
+ `${ manifestData . name } -${ manifestData . version } .xpi` ) ;
36
+ let extensionPath = path . join ( artifactsDir , packageName ) ;
37
+ let stream = createWriteStream ( extensionPath ) ;
38
+ let promisedStream = streamToPromise ( stream ) ;
39
+
40
+ stream . write ( buffer , ( ) => stream . end ( ) ) ;
41
+
42
+ return promisedStream
43
+ . then ( ( ) => {
44
+ log . info ( `Your web extension is ready: ${ extensionPath } ` ) ;
45
+ return { extensionPath} ;
46
+ } ) ;
47
+ } ) ;
48
+ } ) ;
49
+ }
20
50
21
- let resolveManifest ;
22
- if ( manifestData ) {
23
- log . debug ( `Using manifest id=${ manifestData . applications . gecko . id } ` ) ;
24
- resolveManifest = Promise . resolve ( manifestData ) ;
25
- } else {
26
- resolveManifest = getValidatedManifest ( sourceDir ) ;
27
- }
28
51
29
- if ( ! fileFilter ) {
30
- fileFilter = new FileFilter ( ) ;
31
- }
52
+ export default function build (
53
+ { sourceDir, artifactsDir, asNeeded} : Object ,
54
+ { manifestData, fileFilter= new FileFilter ( ) ,
55
+ onSourceChange= defaultSourceWatcher ,
56
+ packageCreator= defaultPackageCreator }
57
+ : Object = { } ) : Promise {
32
58
33
- return resolveManifest
34
- . then ( ( manifestData ) =>
35
- Promise . all ( [
36
- prepareArtifactsDir ( artifactsDir ) ,
37
- zipDir ( sourceDir , {
38
- filter : ( ... args ) => fileFilter . wantFile ( ... args ) ,
39
- } ) ,
40
- ] )
41
- . then ( ( results ) => {
42
- let [ artifactsDir , buffer ] = results ;
43
- let packageName = safeFileName (
44
- ` ${ manifestData . name } - ${ manifestData . version } .xpi` ) ;
45
- let extensionPath = path . join ( artifactsDir , packageName ) ;
46
- let stream = createWriteStream ( extensionPath ) ;
47
- let promisedStream = streamToPromise ( stream ) ;
48
-
49
- stream . write ( buffer , ( ) => stream . end ( ) ) ;
50
-
51
- return promisedStream
52
- . then ( ( ) => {
53
- log . info ( `Your web extension is ready: ${ extensionPath } ` ) ;
54
- return { extensionPath } ;
55
- } ) ;
56
- } )
57
- ) ;
59
+ const rebuildAsNeeded = asNeeded ; // alias for `build --as-needed`
60
+ log . info ( `Building web extension from ${ sourceDir } ` ) ;
61
+
62
+ const createPackage = ( ) => packageCreator ( {
63
+ manifestData , sourceDir, fileFilter , artifactsDir ,
64
+ } ) ;
65
+
66
+ return prepareArtifactsDir ( artifactsDir )
67
+ . then ( ( ) => createPackage ( ) )
68
+ . then ( ( result ) => {
69
+ if ( rebuildAsNeeded ) {
70
+ log . info ( 'Rebuilding when files change...' ) ;
71
+ onSourceChange ( {
72
+ sourceDir , artifactsDir ,
73
+ onChange : ( ) => {
74
+ return createPackage ( ) . catch ( ( error ) => {
75
+ log . error ( error . stack ) ;
76
+ throw error ;
77
+ } ) ;
78
+ } ,
79
+ shouldWatchFile : ( ... args ) => fileFilter . wantFile ( ... args ) ,
80
+ } ) ;
81
+ }
82
+ return result ;
83
+ } ) ;
58
84
}
59
85
60
86
@@ -86,7 +112,7 @@ export class FileFilter {
86
112
wantFile ( path : string ) : boolean {
87
113
for ( const test of this . filesToIgnore ) {
88
114
if ( minimatch ( path , test ) ) {
89
- log . debug ( `Not including file ${ path } in ZIP archive ` ) ;
115
+ log . debug ( `FileFilter: ignoring file ${ path } ` ) ;
90
116
return false ;
91
117
}
92
118
}
0 commit comments