Skip to content

Commit 9e0859b

Browse files
committed
fix: make prepare and normalize have feature parity with legacy packages
Due to npm/cli#6470, I added `read-package-json` and `read-package-json-fast` to this repo as dev deps to run the new tests from #31 against those packages. I found a few discrepancies which I fixed in this PR. Full list of changes are as follows: **`normalize` / `read-package-json-fast`** - convert `bundleDependencies: false` to `[]` **`prepare` / `read-package-json`** - ignore `directories.bin` if `bin` is present - walk up filesystem to look for git directory - log a warning for inaccessible bin entries but dont delete These changes will be tracked in npm/statusboard#487 to see if they should be made as breaking changes with npm 10. These legacy tests can be removed once we have decided to make these breaking changes. Ref: npm/cli#6470 Fixes: #35
1 parent adb0c17 commit 9e0859b

File tree

5 files changed

+930
-790
lines changed

5 files changed

+930
-790
lines changed

lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class PackageJson {
3838
'_attributes',
3939
'bundledDependencies',
4040
'bundleDependencies',
41+
'bundleDependenciesDeleteFalse',
4142
'gypfile',
4243
'serverjs',
4344
'scriptpath',

lib/normalize.js

+34-12
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,27 @@ const { glob } = require('glob')
33
const normalizePackageBin = require('npm-normalize-package-bin')
44
const normalizePackageData = require('normalize-package-data')
55
const path = require('path')
6+
const log = require('proc-log')
7+
const git = require('@npmcli/git')
68

7-
const normalize = async (pkg, { strict, steps }) => {
9+
// Replace with https://github.com/npm/git/pull/135 once it lands
10+
const gitFind = async ({ cwd, root }) => {
11+
if (await git.is({ cwd })) {
12+
return cwd
13+
}
14+
while (cwd !== path.dirname(cwd) && cwd !== root) {
15+
cwd = path.dirname(cwd)
16+
if (await git.is({ cwd })) {
17+
return cwd
18+
}
19+
}
20+
return null
21+
}
22+
23+
const normalize = async (pkg, { strict, steps, root }) => {
824
const data = pkg.content
925
const scripts = data.scripts || {}
26+
const pkgId = `${data.name ?? ''}@${data.version ?? ''}`
1027

1128
// remove attributes that start with "_"
1229
if (steps.includes('_attributes')) {
@@ -20,7 +37,7 @@ const normalize = async (pkg, { strict, steps }) => {
2037
// build the "_id" attribute
2138
if (steps.includes('_id')) {
2239
if (data.name && data.version) {
23-
data._id = `${data.name}@${data.version}`
40+
data._id = pkgId
2441
}
2542
}
2643

@@ -34,7 +51,9 @@ const normalize = async (pkg, { strict, steps }) => {
3451
// expand "bundleDependencies: true or translate from object"
3552
if (steps.includes('bundleDependencies')) {
3653
const bd = data.bundleDependencies
37-
if (bd === true) {
54+
if (bd === false && !steps.includes('bundleDependenciesDeleteFalse')) {
55+
data.bundleDependencies = []
56+
} else if (bd === true) {
3857
data.bundleDependencies = Object.keys(data.dependencies || {})
3958
} else if (bd && typeof bd === 'object') {
4059
if (!Array.isArray(bd)) {
@@ -158,7 +177,7 @@ const normalize = async (pkg, { strict, steps }) => {
158177
}
159178

160179
// expand "directories.bin"
161-
if (steps.includes('binDir') && data.directories?.bin) {
180+
if (steps.includes('binDir') && data.directories?.bin && !data.bin) {
162181
const binsDir = path.resolve(pkg.path, path.join('.', path.join('/', data.directories.bin)))
163182
const bins = await glob('**', { cwd: binsDir })
164183
data.bin = bins.reduce((acc, binFile) => {
@@ -174,25 +193,28 @@ const normalize = async (pkg, { strict, steps }) => {
174193

175194
// populate "gitHead" attribute
176195
if (steps.includes('gitHead') && !data.gitHead) {
196+
const gitRoot = await gitFind({ cwd: pkg.path, root })
177197
let head
178-
try {
179-
head = await fs.readFile(path.resolve(pkg.path, '.git/HEAD'), 'utf8')
180-
} catch (err) {
198+
if (gitRoot) {
199+
try {
200+
head = await fs.readFile(path.resolve(gitRoot, '.git/HEAD'), 'utf8')
201+
} catch (err) {
181202
// do nothing
203+
}
182204
}
183205
let headData
184206
if (head) {
185207
if (head.startsWith('ref: ')) {
186208
const headRef = head.replace(/^ref: /, '').trim()
187-
const headFile = path.resolve(pkg.path, '.git', headRef)
209+
const headFile = path.resolve(gitRoot, '.git', headRef)
188210
try {
189211
headData = await fs.readFile(headFile, 'utf8')
190212
headData = headData.replace(/^ref: /, '').trim()
191213
} catch (err) {
192214
// do nothing
193215
}
194216
if (!headData) {
195-
const packFile = path.resolve(pkg.path, '.git/packed-refs')
217+
const packFile = path.resolve(gitRoot, '.git/packed-refs')
196218
try {
197219
let refs = await fs.readFile(packFile, 'utf8')
198220
if (refs) {
@@ -271,11 +293,11 @@ const normalize = async (pkg, { strict, steps }) => {
271293
// in normalize-package-data if it had access to the file path.
272294
if (steps.includes('binRefs') && data.bin instanceof Object) {
273295
for (const key in data.bin) {
274-
const binPath = path.resolve(pkg.path, data.bin[key])
275296
try {
276-
await fs.access(binPath)
297+
await fs.access(path.resolve(pkg.path, data.bin[key]))
277298
} catch {
278-
delete data.bin[key]
299+
log.warn('package-json', pkgId, `No bin file found at ${data.bin[key]}`)
300+
// XXX: should a future breaking change delete bin entries that cannot be accessed?
279301
}
280302
}
281303
}

package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@
2626
"devDependencies": {
2727
"@npmcli/eslint-config": "^4.0.0",
2828
"@npmcli/template-oss": "4.15.1",
29+
"read-package-json": "^6.0.4",
30+
"read-package-json-fast": "^3.0.2",
2931
"tap": "^16.0.1"
3032
},
3133
"dependencies": {
34+
"@npmcli/git": "^4.0.4",
3235
"glob": "^10.2.2",
3336
"json-parse-even-better-errors": "^3.0.0",
3437
"normalize-package-data": "^5.0.0",
35-
"npm-normalize-package-bin": "^3.0.1"
38+
"npm-normalize-package-bin": "^3.0.1",
39+
"proc-log": "^3.0.0"
3640
},
3741
"repository": {
3842
"type": "git",

0 commit comments

Comments
 (0)