-
-
Notifications
You must be signed in to change notification settings - Fork 933
/
linkHoistedModules.ts
140 lines (136 loc) · 4.02 KB
/
linkHoistedModules.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
140
import path from 'path'
import { calcDepState, DepsStateCache } from '@pnpm/calc-dep-state'
import {
progressLogger,
removalLogger,
statsLogger,
} from '@pnpm/core-loggers'
import { linkBins } from '@pnpm/link-bins'
import { logger } from '@pnpm/logger'
import {
PackageFilesResponse,
StoreController,
} from '@pnpm/store-controller-types'
import difference from 'ramda/src/difference'
import isEmpty from 'ramda/src/isEmpty'
import rimraf from '@zkochan/rimraf'
import {
DepHierarchy,
DependenciesGraph,
} from './lockfileToDepGraph'
export async function linkHoistedModules (
storeController: StoreController,
graph: DependenciesGraph,
prevGraph: DependenciesGraph,
hierarchy: DepHierarchy,
opts: {
depsStateCache: DepsStateCache
force: boolean
ignoreScripts: boolean
lockfileDir: string
preferSymlinkedExecutables?: boolean
sideEffectsCacheRead: boolean
}
): Promise<void> {
// TODO: remove nested node modules first
const dirsToRemove = difference(
Object.keys(prevGraph),
Object.keys(graph)
)
statsLogger.debug({
prefix: opts.lockfileDir,
removed: dirsToRemove.length,
})
await Promise.all([
...dirsToRemove.map((dir) => tryRemoveDir(dir)),
...Object.entries(hierarchy)
.map(([parentDir, depsHierarchy]) => {
function warn (message: string) {
logger.info({
message,
prefix: parentDir,
})
}
return linkAllPkgsInOrder(storeController, graph, prevGraph, depsHierarchy, parentDir, {
...opts,
warn,
})
}),
])
}
async function tryRemoveDir (dir: string) {
removalLogger.debug(dir)
try {
await rimraf(dir)
} catch (err: any) { // eslint-disable-line
/* Just ignoring for now. Not even logging.
logger.warn({
error: err,
message: `Failed to remove "${pathToRemove}"`,
prefix: lockfileDir,
})
*/
}
}
async function linkAllPkgsInOrder (
storeController: StoreController,
graph: DependenciesGraph,
prevGraph: DependenciesGraph,
hierarchy: DepHierarchy,
parentDir: string,
opts: {
depsStateCache: DepsStateCache
force: boolean
ignoreScripts: boolean
lockfileDir: string
preferSymlinkedExecutables?: boolean
sideEffectsCacheRead: boolean
warn: (message: string) => void
}
) {
const _calcDepState = calcDepState.bind(null, graph, opts.depsStateCache)
await Promise.all(
Object.entries(hierarchy).map(async ([dir, deps]) => {
const depNode = graph[dir]
if (depNode.fetchingFiles) {
let filesResponse!: PackageFilesResponse
try {
filesResponse = await depNode.fetchingFiles()
} catch (err: any) { // eslint-disable-line
if (depNode.optional) return
throw err
}
let sideEffectsCacheKey: string | undefined
if (opts.sideEffectsCacheRead && filesResponse.sideEffects && !isEmpty(filesResponse.sideEffects)) {
sideEffectsCacheKey = _calcDepState(dir, {
isBuilt: !opts.ignoreScripts && depNode.requiresBuild,
patchFileHash: depNode.patchFile?.hash,
})
}
const { importMethod, isBuilt } = await storeController.importPackage(depNode.dir, {
filesResponse,
force: opts.force || depNode.depPath !== prevGraph[dir]?.depPath,
requiresBuild: depNode.requiresBuild || depNode.patchFile != null,
sideEffectsCacheKey,
})
if (importMethod) {
progressLogger.debug({
method: importMethod,
requester: opts.lockfileDir,
status: 'imported',
to: depNode.dir,
})
}
depNode.isBuilt = isBuilt
}
return linkAllPkgsInOrder(storeController, graph, prevGraph, deps, dir, opts)
})
)
const modulesDir = path.join(parentDir, 'node_modules')
const binsDir = path.join(modulesDir, '.bin')
await linkBins(modulesDir, binsDir, {
allowExoticManifests: true,
preferSymlinkedExecutables: opts.preferSymlinkedExecutables,
warn: opts.warn,
})
}