Skip to content

Commit

Permalink
fix: respect gitignore and npmignore files in workspace roots
Browse files Browse the repository at this point in the history
  • Loading branch information
nlf authored and wraithgar committed May 19, 2022
1 parent 7e1fc71 commit 839e6e8
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
41 changes: 40 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,33 @@ const fs = require('fs')
const glob = require('glob')
const globify = pattern => pattern.split('\\').join('/')

const readOutOfTreeIgnoreFiles = (root, rel, result = '') => {
for (const file of ['.gitignore', '.npmignore']) {
try {
const ignoreContent = fs.readFileSync(path.join(root, file), { encoding: 'utf8' })
result += ignoreContent + '\n'
} catch (err) {
// we ignore ENOENT errors completely because we don't care if the file doesn't exist
// but we throw everything else because failing to read a file that does exist is
// something that the user likely wants to know about. we don't need to test this.
/* istanbul ignore next */
if (err.code !== 'ENOENT') {
throw err
}
}
}

if (!rel) {
return result
}

const firstRel = rel.split(path.sep)[0]
const newRoot = path.join(root, firstRel)
const newRel = path.relative(newRoot, path.join(root, rel))

return readOutOfTreeIgnoreFiles(newRoot, newRel, result)
}

const pathHasPkg = (input) => {
if (!input.startsWith('node_modules/')) {
return false
Expand Down Expand Up @@ -119,9 +146,21 @@ class Walker extends IgnoreWalker {
this.bundledScopes = Array.from(new Set(
this.bundled.filter(f => /^@/.test(f))
.map(f => f.split('/')[0])))
const rules = defaultRules.join('\n') + '\n'
this.packageJsonCache = this.parent ? this.parent.packageJsonCache
: (opt.packageJsonCache || new Map())
let rules = defaultRules.join('\n') + '\n'
// if opt.path and opt.prefix are not the same directory, and opt.workspaces has opt.path
// in it, then we know that opt.path is a workspace directory. in order to not drop ignore
// rules from directories between the workspace root (opt.prefix) and the workspace itself
// (opt.path), we need to find and read those now
if (opt.prefix && opt.path !== opt.prefix &&
opt.workspaces && opt.workspaces.includes(opt.path)) {
// relpath is the relative path between the prefix and the parent of opt.path
// we use the parent because ignore-walk will read the files in opt.path already
const relpath = path.relative(opt.prefix, path.dirname(opt.path))
rules += readOutOfTreeIgnoreFiles(opt.prefix, relpath)
}

super.onReadIgnoreFile(rootBuiltinRules, rules, _ => _)
} else {
this.bundled = []
Expand Down
47 changes: 47 additions & 0 deletions test/workspace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict'

const path = require('path')
const t = require('tap')

const packlist = require('../')

t.test('respects workspace root ignore files', async (t) => {
const root = t.testdir({
'package.json': JSON.stringify({
name: 'workspace-root',
version: '1.0.0',
main: 'index.js',
workspaces: ['./workspaces/foo'],
}),
'index.js': `console.log('hello')`,
'.gitignore': 'ignore-me',
'ignore-me': 'should be ignored',
workspaces: {
'.gitignore': 'ignore-me-also',
'ignore-me': 'should be ignored',
'ignore-me-also': 'should also be ignored',
foo: {
'package.json': JSON.stringify({
name: 'workspace-child',
version: '1.0.0',
main: 'index.js',
}),
'index.js': `console.log('hello')`,
'ignore-me': 'should be ignored',
'ignore-me-also': 'should also be ignored',
},
},
})

const workspacePath = path.join(root, 'workspaces', 'foo')
// this simulates what it looks like when a user does i.e. npm pack -w ./workspaces/foo
const files = await packlist({
path: workspacePath,
prefix: root,
workspaces: [workspacePath],
})
t.same(files, [
'index.js',
'package.json',
])
})

0 comments on commit 839e6e8

Please sign in to comment.