/
link.ts
139 lines (105 loc) · 4.95 KB
/
link.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import assertProject, {isExecutable} from '@pnpm/assert-project'
import sinon = require('sinon')
import tape = require('tape')
import promisifyTape from 'tape-promise'
const test = promisifyTape(tape)
const testOnly = promisifyTape(tape.only)
import ncpCB = require('ncp')
import path = require('path')
import promisify = require('util.promisify')
import {
pathToLocalPkg,
prepare,
testDefaults,
} from './utils'
const ncp = promisify(ncpCB.ncp)
import exists = require('path-exists')
import {
installPkgs,
link,
linkFromGlobal,
linkToGlobal,
RootLog,
} from 'supi'
import writeJsonFile = require('write-json-file')
test('relative link', async (t: tape.Test) => {
const project = prepare(t, {
dependencies: {
'hello-world-js-bin': '*',
},
})
const linkedPkgName = 'hello-world-js-bin'
const linkedPkgPath = path.resolve('..', linkedPkgName)
await ncp(pathToLocalPkg(linkedPkgName), linkedPkgPath)
await link([`../${linkedPkgName}`], path.join(process.cwd(), 'node_modules'), await testDefaults())
await project.isExecutable('.bin/hello-world-js-bin')
// The linked package has been installed successfully as well with bins linked
// to node_modules/.bin
const linkedProject = assertProject(t, linkedPkgPath)
await linkedProject.isExecutable('.bin/cowsay')
const wantedShrinkwrap = await project.loadShrinkwrap()
t.equal(wantedShrinkwrap.dependencies['hello-world-js-bin'], 'link:../hello-world-js-bin', 'link added to wanted shrinkwrap')
t.equal(wantedShrinkwrap.specifiers['hello-world-js-bin'], '*', 'specifier of linked dependency added to shrinkwrap.yaml')
const currentShrinkwrap = await project.loadCurrentShrinkwrap()
t.equal(currentShrinkwrap.dependencies['hello-world-js-bin'], 'link:../hello-world-js-bin', 'link added to wanted shrinkwrap')
})
test('relative link is not rewritten by install', async (t: tape.Test) => {
const project = prepare(t)
const linkedPkgName = 'hello-world-js-bin'
const linkedPkgPath = path.resolve('..', linkedPkgName)
await ncp(pathToLocalPkg(linkedPkgName), linkedPkgPath)
await link([`../${linkedPkgName}`], path.join(process.cwd(), 'node_modules'), await testDefaults())
const reporter = sinon.spy()
await installPkgs(['hello-world-js-bin'], await testDefaults({reporter}))
t.ok(project.requireModule('hello-world-js-bin/package.json').isLocal)
t.ok(reporter.calledWithMatch({
level: 'debug',
linked: {
from: linkedPkgPath,
name: 'hello-world-js-bin',
to: path.resolve('node_modules'),
// TODO: the dependencyType should be `undefined` in this case
},
name: 'pnpm:root',
} as RootLog), 'linked root dependency logged')
const wantedShrinkwrap = await project.loadShrinkwrap()
t.equal(wantedShrinkwrap.dependencies['hello-world-js-bin'], 'link:../hello-world-js-bin', 'link still in wanted shrinkwrap')
const currentShrinkwrap = await project.loadCurrentShrinkwrap()
t.equal(currentShrinkwrap.dependencies['hello-world-js-bin'], 'link:../hello-world-js-bin', 'link still in wanted shrinkwrap')
})
test('global link', async (t: tape.Test) => {
const project = prepare(t)
const projectPath = process.cwd()
const linkedPkgName = 'hello-world-js-bin'
const linkedPkgPath = path.resolve('..', linkedPkgName)
await ncp(pathToLocalPkg(linkedPkgName), linkedPkgPath)
process.chdir(linkedPkgPath)
const globalPrefix = path.resolve('..', 'global')
const globalBin = path.resolve('..', 'global', 'bin')
await linkToGlobal(process.cwd(), await testDefaults({globalPrefix, globalBin}))
await isExecutable(t, path.join(globalBin, 'hello-world-js-bin'))
// bins of dependencies should not be linked, see issue https://github.com/pnpm/pnpm/issues/905
t.notOk(await exists(path.join(globalBin, 'cowsay')), 'cowsay not linked')
t.notOk(await exists(path.join(globalBin, 'cowthink')), 'cowthink not linked')
process.chdir(projectPath)
await linkFromGlobal([linkedPkgName], process.cwd(), await testDefaults({globalPrefix}))
await project.isExecutable('.bin/hello-world-js-bin')
})
test('failed linking should not create empty folder', async (t: tape.Test) => {
prepare(t)
const globalPrefix = path.resolve('..', 'global')
try {
await linkFromGlobal(['does-not-exist'], process.cwd(), await testDefaults({globalPrefix}))
t.fail('should have failed')
} catch (err) {
t.notOk(await exists(path.join(globalPrefix, 'node_modules', 'does-not-exist')))
}
})
test('node_modules is pruned after linking', async (t: tape.Test) => {
const project = prepare(t)
await writeJsonFile('../is-positive/package.json', {name: 'is-positive', version: '1.0.0'})
await installPkgs(['is-positive@1.0.0'], await testDefaults())
t.ok(await exists('node_modules/.localhost+4873/is-positive/1.0.0/node_modules/is-positive/package.json'))
await link(['../is-positive'], path.resolve('node_modules'), await testDefaults())
t.notOk(await exists('node_modules/.localhost+4873/is-positive/1.0.0/node_modules/is-positive/package.json'), 'pruned')
})