Skip to content

Commit db21624

Browse files
authored
feat: implement gitSubdir according to npa spec (#442)
This implements the `gitSubdir` parameter, which is already parsed by npa, finally allowing users of npm to specifiy subdirectories in git dependencies. The respective parsing logic has already been agreed on and implemented nearly 4 years ago here: npm/npm-package-arg#91. In this PR, the git fetcher is changed to resolve the `gitSubdir` parameter from the spec if found, as suggested by the author in the original npa PR. ## References Fixes npm/cli#528 Fixes npm/npm#2974 Relates to npm/npm-package-arg#46 Relates to npm/npm-package-arg#91 Inspired from and crediting sspiff@8bd5461, which seems to have been lost after merging the PR at npa.
1 parent c2a4217 commit db21624

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

lib/git.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ class GitFetcher extends Fetcher {
245245
pkgid: `git:${nameat}${this.resolved}`,
246246
resolved: this.resolved,
247247
integrity: null, // it'll always be different, if we have one
248-
}).extract(tmp).then(() => handler(tmp), er => {
248+
}).extract(tmp).then(() => handler(`${tmp}${this.spec.gitSubdir || ''}`), er => {
249249
// fall back to ssh download if tarball fails
250250
if (er.constructor.name.match(/^Http/)) {
251251
return this.#clone(handler, false)
@@ -263,7 +263,7 @@ class GitFetcher extends Fetcher {
263263
if (!this.resolved) {
264264
await this.#addGitSha(sha)
265265
}
266-
return handler(tmp)
266+
return handler(`${tmp}${this.spec.gitSubdir || ''}`)
267267
})
268268
}
269269

test/git.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,3 +781,50 @@ t.test('fails without arborist constructor', { skip: isWindows && 'posix only' }
781781
const extract = resolve(me, 'extract-prepack')
782782
t.rejects(() => ws.extract(extract))
783783
})
784+
785+
t.test('gitSubdir extraction', { skip: isWindows && 'posix only' }, async t => {
786+
const subdirRepo = resolve(me, 'subdir-repo')
787+
const git = (...cmd) => spawnGit(cmd, { cwd: subdirRepo })
788+
const write = (f, c) => fs.writeFileSync(`${subdirRepo}/${f}`, c)
789+
790+
await mkdir(subdirRepo, { recursive: true })
791+
await git('init')
792+
await git('config', 'user.name', 'pacotedev')
793+
await git('config', 'user.email', 'i+pacotedev@izs.me')
794+
await git('config', 'tag.gpgSign', 'false')
795+
await git('config', 'commit.gpgSign', 'false')
796+
await git('config', 'tag.forceSignAnnotated', 'false')
797+
798+
// root package.json (should be ignored)
799+
await write('package.json', JSON.stringify({
800+
name: 'root-package',
801+
version: '1.0.0',
802+
}))
803+
804+
// subdirectory with actual package
805+
await mkdir(`${subdirRepo}/packages/subpkg`, { recursive: true })
806+
await write('packages/subpkg/package.json', JSON.stringify({
807+
name: 'sub-package',
808+
version: '1.0.0',
809+
description: 'package in subdirectory',
810+
}))
811+
await write('packages/subpkg/index.js', 'console.log("subpkg")')
812+
813+
await git('add', '.')
814+
await git('commit', '-m', 'add subdirectory package')
815+
816+
const subdirRemote = `git://localhost:${gitPort}/subdir-repo`
817+
const gf = new GitFetcher(`${subdirRemote}#HEAD::path:packages/subpkg`, opts)
818+
const extract = resolve(me, 'extract-subdir')
819+
await gf.extract(extract)
820+
821+
// verify it reads from subdirectory, not root
822+
const manifest = await gf.manifest()
823+
t.equal(manifest.name, 'sub-package')
824+
t.equal(manifest.version, '1.0.0')
825+
t.equal(manifest.description, 'package in subdirectory')
826+
827+
// verify files are extracted from subdirectory
828+
t.ok(fs.statSync(`${extract}/index.js`))
829+
t.ok(fs.statSync(`${extract}/package.json`))
830+
})

0 commit comments

Comments
 (0)