@@ -33,6 +33,33 @@ const fs = require('fs')
33
33
const glob = require ( 'glob' )
34
34
const globify = pattern => pattern . split ( '\\' ) . join ( '/' )
35
35
36
+ const readOutOfTreeIgnoreFiles = ( root , rel , result = '' ) => {
37
+ for ( const file of [ '.gitignore' , '.npmignore' ] ) {
38
+ try {
39
+ const ignoreContent = fs . readFileSync ( path . join ( root , file ) , { encoding : 'utf8' } )
40
+ result += ignoreContent + '\n'
41
+ } catch ( err ) {
42
+ // we ignore ENOENT errors completely because we don't care if the file doesn't exist
43
+ // but we throw everything else because failing to read a file that does exist is
44
+ // something that the user likely wants to know about. we don't need to test this.
45
+ /* istanbul ignore next */
46
+ if ( err . code !== 'ENOENT' ) {
47
+ throw err
48
+ }
49
+ }
50
+ }
51
+
52
+ if ( ! rel ) {
53
+ return result
54
+ }
55
+
56
+ const firstRel = rel . split ( path . sep ) [ 0 ]
57
+ const newRoot = path . join ( root , firstRel )
58
+ const newRel = path . relative ( newRoot , path . join ( root , rel ) )
59
+
60
+ return readOutOfTreeIgnoreFiles ( newRoot , newRel , result )
61
+ }
62
+
36
63
const pathHasPkg = ( input ) => {
37
64
if ( ! input . startsWith ( 'node_modules/' ) ) {
38
65
return false
@@ -119,9 +146,31 @@ class Walker extends IgnoreWalker {
119
146
this . bundledScopes = Array . from ( new Set (
120
147
this . bundled . filter ( f => / ^ @ / . test ( f ) )
121
148
. map ( f => f . split ( '/' ) [ 0 ] ) ) )
122
- const rules = defaultRules . join ( '\n' ) + '\n'
123
149
this . packageJsonCache = this . parent ? this . parent . packageJsonCache
124
150
: ( opt . packageJsonCache || new Map ( ) )
151
+ let rules = defaultRules . join ( '\n' ) + '\n'
152
+
153
+ if ( opt . prefix && opt . workspaces ) {
154
+ const gPath = globify ( opt . path )
155
+ const gPrefix = globify ( opt . prefix )
156
+ const gWorkspaces = opt . workspaces . map ( ( ws ) => globify ( ws ) )
157
+ // if opt.path and opt.prefix are not the same directory, and opt.workspaces has opt.path
158
+ // in it, then we know that opt.path is a workspace directory. in order to not drop ignore
159
+ // rules from directories between the workspace root (opt.prefix) and the workspace itself
160
+ // (opt.path), we need to find and read those now
161
+ /* istanbul ignore else */
162
+ if ( gPath !== gPrefix && gWorkspaces . includes ( gPath ) ) {
163
+ // relpath is the relative path between the prefix and the parent of opt.path
164
+ // we use the parent because ignore-walk will read the files in opt.path already
165
+ const relpath = path . relative ( opt . prefix , path . dirname ( opt . path ) )
166
+ rules += readOutOfTreeIgnoreFiles ( opt . prefix , relpath )
167
+ } else if ( gPath === gPrefix ) {
168
+ // on the other hand, if the path and the prefix are the same, then we ignore workspaces
169
+ // so that we don't pack workspaces inside of a root project
170
+ rules += opt . workspaces . map ( ( ws ) => globify ( path . relative ( opt . path , ws ) ) ) . join ( '\n' )
171
+ }
172
+ }
173
+
125
174
super . onReadIgnoreFile ( rootBuiltinRules , rules , _ => _ )
126
175
} else {
127
176
this . bundled = [ ]
0 commit comments