Skip to content

Commit 8047b19

Browse files
larsgwzkat
authored andcommitted
install: match git semver ranges (#115)
Fixes: https://npm.community/t/3784 PR-URL: #115 Credit: @larsgw Reviewed-By: @iarna Reviewed-By: @zkat
1 parent 433020e commit 8047b19

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

Diff for: lib/install/deps.js

+9
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ function doesChildVersionMatch (child, requested, requestor) {
5757
if (fromSw.toString() === requested.toString()) return true
5858
}
5959

60+
if (requested.type === 'git' && requested.gitRange) {
61+
const sameRepo = npa(child.package._from).fetchSpec === requested.fetchSpec
62+
try {
63+
return sameRepo && semver.satisfies(child.package.version, requested.gitRange, true)
64+
} catch (e) {
65+
return false
66+
}
67+
}
68+
6069
if (!registryTypes[requested.type]) {
6170
var childReq = child.package._requested
6271
if (childReq) {

Diff for: test/tap/dedupe-git-semver.js

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
'use strict'
2+
const fs = require('fs')
3+
const path = require('path')
4+
const test = require('tap').test
5+
const requireInject = require('require-inject')
6+
const Tacks = require('tacks')
7+
const File = Tacks.File
8+
const Dir = Tacks.Dir
9+
10+
const manifests = {
11+
'git-wrap': {
12+
name: 'git-wrap',
13+
version: '1.0.0',
14+
dependencies: {
15+
git: 'git+https://example.com/git#semver:1.0'
16+
}
17+
},
18+
git: {
19+
name: 'git',
20+
version: '1.0.0'
21+
}
22+
}
23+
24+
const npm = requireInject.installGlobally('../../lib/npm.js', {
25+
pacote: {
26+
manifest: function (spec) {
27+
const manifest = manifests[spec.name]
28+
manifest._requested = spec
29+
manifest._resolved = spec.saveSpec.replace(/^file:/, '').replace(/(:?#.*)$/, '#0000000000000000000000000000000000000000')
30+
manifest._from = spec.rawSpec
31+
return Promise.resolve(manifest)
32+
}
33+
},
34+
'../../lib/utils/output.js': function () {
35+
// do not output to stdout
36+
}
37+
})
38+
39+
const basedir = path.join(__dirname, path.basename(__filename, '.js'))
40+
const testdir = path.join(basedir, 'testdir')
41+
const cachedir = path.join(basedir, 'cache')
42+
const tmpdir = path.join(basedir, 'tmp')
43+
44+
const cwd = process.cwd()
45+
46+
const conf = {
47+
cache: cachedir,
48+
tmp: tmpdir,
49+
loglevel: 'silent',
50+
'package-lock-only': true
51+
}
52+
53+
const fixture = new Tacks(Dir({
54+
cache: Dir(),
55+
global: Dir(),
56+
tmp: Dir(),
57+
testdir: Dir({
58+
'package.json': File({
59+
name: 'fixture',
60+
version: '1.0.0',
61+
dependencies: {
62+
git: 'git+https://example.com/git#semver:1',
63+
'git-wrap': 'file:git-wrap-1.0.0.tgz'
64+
}
65+
}),
66+
// Tarball source:
67+
// 'git-wrap': Dir({
68+
// 'package.json': File({
69+
// name: 'git-wrap',
70+
// version: '1.0.0',
71+
// dependencies: {
72+
// git: 'git+https://example.com/git#semver:1.0'
73+
// }
74+
// })
75+
// }),
76+
'git-wrap-1.0.0.tgz': File(Buffer.from(
77+
'1f8b0800000000000003ed8fcd0ac23010843df729423caaf9c13642df26' +
78+
'b44bad9a3434f107a4efeec68aa7de2c8898ef32cb0c3bec3a5d1d7503dc' +
79+
'8dca0ebeb38b991142a83c27537e44ee30db164a48a994c01987a210a873' +
80+
'1f32c5d907dde3299ff68cbf90b7fe08f78c106ab5015a12dab46173edb5' +
81+
'a3ebe85ea0f76d676320996062746b70606bb0550b1ea3b84f9e9baf82d5' +
82+
'3e04e74bcee1a68d3b01ab3ac3d15f7a30d8586215c59d211bb26fff9e48' +
83+
'2412ffcc034458283d00080000',
84+
'hex'
85+
))
86+
})
87+
}))
88+
89+
function setup () {
90+
cleanup()
91+
fixture.create(basedir)
92+
}
93+
94+
function cleanup () {
95+
fixture.remove(basedir)
96+
}
97+
98+
test('setup', function (t) {
99+
setup()
100+
process.chdir(testdir)
101+
npm.load(conf, function (err) {
102+
if (err) throw err
103+
t.done()
104+
})
105+
})
106+
107+
test('dedupe matching git semver ranges', function (t) {
108+
npm.commands.install(function (err) {
109+
if (err) throw err
110+
const packageLock = JSON.parse(fs.readFileSync('package-lock.json'))
111+
t.same(packageLock, {
112+
name: 'fixture',
113+
version: '1.0.0',
114+
lockfileVersion: 1,
115+
requires: true,
116+
dependencies: {
117+
git: {
118+
from: 'git+https://example.com/git#semver:1',
119+
version: 'git+https://example.com/git#0000000000000000000000000000000000000000'
120+
},
121+
'git-wrap': {
122+
version: 'file:git-wrap-1.0.0.tgz',
123+
requires: {
124+
git: 'git+https://example.com/git#semver:1'
125+
}
126+
}
127+
}
128+
})
129+
t.done()
130+
})
131+
})
132+
133+
test('cleanup', function (t) {
134+
process.chdir(cwd)
135+
cleanup()
136+
t.done()
137+
})

0 commit comments

Comments
 (0)