Skip to content

Commit

Permalink
fix: exclude non-root README.md/LICENSE files (#173)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The files array can now be used to exclude non-root readme, license, licence, and copying files.

Co-authored-by: rahulio96 <rahulgithub96@gmail.com>
  • Loading branch information
AaronHamilton965 and rahulio96 authored Aug 23, 2023
1 parent 21ed893 commit 24344a2
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 5 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ arborist.loadActual().then((tree) => {
This uses the following rules:

1. If a `package.json` file is found, and it has a `files` list,
then ignore everything that isn't in `files`. Always include the
then ignore everything that isn't in `files`. Always include the root
readme, license, licence and copying files, if they exist, as well
as the package.json file itself.
as the package.json file itself. Non-root readme, license, licence and
copying files are included by default, but can be excluded using the
`files` list e.g. `"!readme"`.
2. If there's no `package.json` file (or it has no `files` list), and
there is a `.npmignore` file, then ignore all the files in the
`.npmignore` file.
Expand Down
34 changes: 31 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,22 @@ const defaults = [
]

const strictDefaults = [
// these are forcibly included at all levels
// these are forcibly excluded
'/.git',
]

const allLevels = [
// these are included by default but can be excluded by package.json files array
'!/readme{,.*[^~$]}',
'!/copying{,.*[^~$]}',
'!/license{,.*[^~$]}',
'!/licence{,.*[^~$]}',
// these are forcibly excluded
'/.git',
]

const rootOnly = [
/^!.*readme/i,
/^!.*copying/i,
/^!.*licen[sc]e/i,
]

const normalizePath = (path) => path.split('\\').join('/')
Expand Down Expand Up @@ -132,6 +141,7 @@ class PackWalker extends IgnoreWalker {
// known required files for this directory
this.injectRules(strictRules, [
...strictDefaults,
...allLevels,
...this.requiredFiles.map((file) => `!${file}`),
])
}
Expand Down Expand Up @@ -284,6 +294,7 @@ class PackWalker extends IgnoreWalker {
const ignores = []
const strict = [
...strictDefaults,
...allLevels,
'!/package.json',
'/.git',
'/node_modules',
Expand All @@ -304,6 +315,9 @@ class PackWalker extends IgnoreWalker {
file = file.slice(0, -2)
}
const inverse = `!${file}`

this.excludeNonRoot(file)

try {
// if an entry in the files array is a specific file, then we need to include it as a
// strict requirement for this package. if it's a directory or a pattern, it's a default
Expand Down Expand Up @@ -352,6 +366,20 @@ class PackWalker extends IgnoreWalker {
this.injectRules(strictRules, strict, callback)
}

// excludes non root files by checking if elements from the files array in
// package.json contain an ! and readme/license/licence/copying, and then
// removing readme/license/licence/copying accordingly from strict defaults
excludeNonRoot (file) {
// Find the pattern
const matchingPattern = rootOnly.find(regex => regex.test(file))

if (matchingPattern) {
// Find which index matches the pattern and remove it from allLevels
const indexToRemove = allLevels.findIndex(element => matchingPattern.test(element))
allLevels.splice(indexToRemove, 1)
}
}

// custom method: after we've finished gathering the files for the root package, we call this
// before emitting the 'done' event in order to gather all of the files for bundled deps
async gatherBundles () {
Expand Down
69 changes: 69 additions & 0 deletions test/package-json-negate-non-root.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// exclude readme, license, and licnce files if package.json
// files array includes !readme, !license, or !licence
'use strict'

const Arborist = require('@npmcli/arborist')
const t = require('tap')
const packlist = require('../')

const pkg = t.testdir({
'package.json': JSON.stringify({
files: [
'**/*.js',
'!readme.md',
'!licence',
'!license',
'!copying',
],

}),
'readme.md': 'one',
licence: 'two',
license: 'tre',
copying: 'for',
lib: {
'readme.md': 'one',
licence: 'two',
license: 'tre',
copying: 'for',
a: {
'readme.md': 'one',
licence: 'two',
license: 'tre',
copying: 'for',
b: {
'readme.md': 'one',
licence: 'two',
license: 'tre',
copying: 'for',
c: {
'readme.md': 'one',
licence: 'two',
license: 'tre',
copying: 'for',
'file.txt': 'one',
'c.js': 'two',
},
'file.txt': 'one',
'b.js': 'two',
},
'file.txt': 'one',
'a.js': 'two',
},
} })

t.test('package with negated readme, licence and license files', async (t) => {
const arborist = new Arborist({ path: pkg })
const tree = await arborist.loadActual()
const files = await packlist(tree)
t.same(files, [
'copying',
'licence',
'license',
'lib/a/a.js',
'lib/a/b/b.js',
'lib/a/b/c/c.js',
'package.json',
'readme.md',
])
})

0 comments on commit 24344a2

Please sign in to comment.