@pnpm/deps.graph-hasher 1100.2.12 → 1100.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/lib/index.d.ts +30 -16
- package/lib/index.js +41 -21
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @pnpm/calc-dep-state
|
|
2
2
|
|
|
3
|
+
## 1100.2.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Installing a local `file:` directory dependency with the global virtual store enabled no longer fails with `TypeError: Cannot read properties of undefined (reading 'split')` [#13335](https://github.com/pnpm/pnpm/issues/13335).
|
|
8
|
+
|
|
9
|
+
Local directory dependencies — `file:` directories and injected workspace packages — now get a global-virtual-store slot of their own per project. They used to share one slot across every project that depended on a directory of the same name, so a project could end up linked to another project's copy of the dependency.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies:
|
|
12
|
+
- @pnpm/deps.path@1100.0.12
|
|
13
|
+
- @pnpm/engine.runtime.system-version@1100.0.7
|
|
14
|
+
- @pnpm/lockfile.types@1100.0.17
|
|
15
|
+
- @pnpm/lockfile.utils@1100.1.6
|
|
16
|
+
- @pnpm/resolving.resolver-base@1100.5.5
|
|
17
|
+
- @pnpm/types@1101.7.0
|
|
18
|
+
|
|
3
19
|
## 1100.2.12
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/lib/index.d.ts
CHANGED
|
@@ -77,28 +77,42 @@ export interface HashedDepPath<T extends PkgMeta> {
|
|
|
77
77
|
pkgMeta: T;
|
|
78
78
|
hash: string;
|
|
79
79
|
}
|
|
80
|
-
export
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
80
|
+
export interface GraphNodeHashOptions {
|
|
81
|
+
allowBuild?: AllowBuild;
|
|
82
|
+
supportedArchitectures?: SupportedArchitectures;
|
|
83
|
+
/**
|
|
84
|
+
* Install-wide fallback `engines.runtime` / `devEngines.runtime`
|
|
85
|
+
* Node version. Used only for snapshots that don't pin their own
|
|
86
|
+
* Node; pinning snapshots get resolved per-snapshot via
|
|
87
|
+
* {@link readSnapshotRuntimePin} so the GVS engine hash matches
|
|
88
|
+
* the Node the bin linker would actually spawn for each package
|
|
89
|
+
* (see [`bins/linker/src/index.ts`](https://github.com/pnpm/pnpm/blob/29a42efc3b/bins/linker/src/index.ts)).
|
|
90
|
+
* Typically obtained via {@link findRuntimeNodeVersion} over the
|
|
91
|
+
* lockfile's snapshot keys. `undefined` falls back to
|
|
92
|
+
* {@link engineName}'s default (system `node --version`, with
|
|
93
|
+
* `process.version` as a last resort).
|
|
94
|
+
*/
|
|
95
|
+
nodeVersion?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Directory the lockfile lives in. Scopes the slots of local directory
|
|
98
|
+
* dependencies to the project that owns them — see
|
|
99
|
+
* {@link isLocalDirectoryResolution}. Omitting it leaves those packages on a
|
|
100
|
+
* shared slot, which is only safe for a lockfile known to have no directory
|
|
101
|
+
* dependencies.
|
|
102
|
+
*/
|
|
103
|
+
lockfileDir?: string;
|
|
104
|
+
}
|
|
105
|
+
export declare function iterateHashedGraphNodes<T extends PkgMeta>(graph: DepsGraph<DepPath>, pkgMetaIterator: PkgMetaIterator<T>, opts?: GraphNodeHashOptions): IterableIterator<HashedDepPath<T>>;
|
|
106
|
+
export declare function calcGraphNodeHash<T extends PkgMeta>({ graph, cache, builtDepPaths, buildRequiredCache, supportedArchitectures, nodeVersion, lockfileDir }: {
|
|
95
107
|
graph: DepsGraph<DepPath>;
|
|
96
108
|
cache: DepsStateCache;
|
|
97
109
|
builtDepPaths?: Set<DepPath>;
|
|
98
110
|
buildRequiredCache?: Record<string, boolean>;
|
|
99
111
|
supportedArchitectures?: SupportedArchitectures;
|
|
100
|
-
/** See
|
|
112
|
+
/** See {@link GraphNodeHashOptions.nodeVersion}. */
|
|
101
113
|
nodeVersion?: string;
|
|
114
|
+
/** See {@link GraphNodeHashOptions.lockfileDir}. */
|
|
115
|
+
lockfileDir?: string;
|
|
102
116
|
}, pkgMeta: T): string;
|
|
103
117
|
export declare function calcLeafGlobalVirtualStorePath(fullPkgId: string, name: string, version: string): string;
|
|
104
118
|
/**
|
package/lib/index.js
CHANGED
|
@@ -113,25 +113,12 @@ function calcDepGraphHash(depsGraph, cache, parents, depPath, supportedArchitect
|
|
|
113
113
|
});
|
|
114
114
|
return cache[depPath];
|
|
115
115
|
}
|
|
116
|
-
export function* iterateHashedGraphNodes(graph, pkgMetaIterator,
|
|
117
|
-
/**
|
|
118
|
-
* Install-wide fallback `engines.runtime` / `devEngines.runtime`
|
|
119
|
-
* Node version. Used only for snapshots that don't pin their own
|
|
120
|
-
* Node; pinning snapshots get resolved per-snapshot via
|
|
121
|
-
* {@link readSnapshotRuntimePin} so the GVS engine hash matches
|
|
122
|
-
* the Node the bin linker would actually spawn for each package
|
|
123
|
-
* (see [`bins/linker/src/index.ts`](https://github.com/pnpm/pnpm/blob/29a42efc3b/bins/linker/src/index.ts)).
|
|
124
|
-
* Typically obtained via {@link findRuntimeNodeVersion} over the
|
|
125
|
-
* lockfile's snapshot keys. `undefined` falls back to
|
|
126
|
-
* {@link engineName}'s default (system `node --version`, with
|
|
127
|
-
* `process.version` as a last resort).
|
|
128
|
-
*/
|
|
129
|
-
nodeVersion) {
|
|
116
|
+
export function* iterateHashedGraphNodes(graph, pkgMetaIterator, opts = {}) {
|
|
130
117
|
let builtDepPaths;
|
|
131
118
|
let entries;
|
|
132
|
-
if (allowBuild != null) {
|
|
119
|
+
if (opts.allowBuild != null) {
|
|
133
120
|
const pkgMetaList = Array.from(pkgMetaIterator);
|
|
134
|
-
builtDepPaths = computeBuiltDepPaths(pkgMetaList, allowBuild);
|
|
121
|
+
builtDepPaths = computeBuiltDepPaths(pkgMetaList, opts.allowBuild);
|
|
135
122
|
entries = pkgMetaList;
|
|
136
123
|
}
|
|
137
124
|
else {
|
|
@@ -142,8 +129,9 @@ nodeVersion) {
|
|
|
142
129
|
cache: {},
|
|
143
130
|
builtDepPaths,
|
|
144
131
|
buildRequiredCache: builtDepPaths !== undefined ? {} : undefined,
|
|
145
|
-
supportedArchitectures,
|
|
146
|
-
nodeVersion,
|
|
132
|
+
supportedArchitectures: opts.supportedArchitectures,
|
|
133
|
+
nodeVersion: opts.nodeVersion,
|
|
134
|
+
lockfileDir: opts.lockfileDir,
|
|
147
135
|
};
|
|
148
136
|
for (const pkgMeta of entries) {
|
|
149
137
|
yield {
|
|
@@ -152,7 +140,7 @@ nodeVersion) {
|
|
|
152
140
|
};
|
|
153
141
|
}
|
|
154
142
|
}
|
|
155
|
-
export function calcGraphNodeHash({ graph, cache, builtDepPaths, buildRequiredCache, supportedArchitectures, nodeVersion }, pkgMeta) {
|
|
143
|
+
export function calcGraphNodeHash({ graph, cache, builtDepPaths, buildRequiredCache, supportedArchitectures, nodeVersion, lockfileDir }, pkgMeta) {
|
|
156
144
|
const { name, version, depPath } = pkgMeta;
|
|
157
145
|
// When builtDepPaths is provided (derived from the allowBuilds config),
|
|
158
146
|
// we only include the engine name for packages that are allowed to build
|
|
@@ -169,8 +157,39 @@ export function calcGraphNodeHash({ graph, cache, builtDepPaths, buildRequiredCa
|
|
|
169
157
|
const ownPin = readSnapshotRuntimePin(graph[depPath]?.children);
|
|
170
158
|
const engine = includeEngine ? engineName(ownPin ?? nodeVersion) : null;
|
|
171
159
|
const deps = calcDepGraphHash(graph, cache, new Set(), depPath, supportedArchitectures);
|
|
172
|
-
const
|
|
173
|
-
|
|
160
|
+
const isLocalDirectory = isLocalDirectoryResolution(graph[depPath]?.resolution);
|
|
161
|
+
// Scoping the slot needs the project's identity; the segment only needs to
|
|
162
|
+
// know that the package is a local directory, so a caller that leaves
|
|
163
|
+
// `lockfileDir` out still gets a well-formed path.
|
|
164
|
+
const project = isLocalDirectory ? lockfileDir : undefined;
|
|
165
|
+
const hexDigest = project == null
|
|
166
|
+
? hashObjectWithoutSorting({ engine, deps }, { encoding: 'hex' })
|
|
167
|
+
: hashObjectWithoutSorting({ engine, deps, project }, { encoding: 'hex' });
|
|
168
|
+
return formatGlobalVirtualStorePath(name, isLocalDirectory ? LOCAL_DIRECTORY_SEGMENT : version, hexDigest);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Slot segment that stands in for the version of a package resolved from a
|
|
172
|
+
* local directory. pnpm omits the version from a directory snapshot, so the
|
|
173
|
+
* lockfile has none to offer — and the resolver, which does know it from the
|
|
174
|
+
* manifest, must agree with the lockfile or a re-install would relocate the
|
|
175
|
+
* package. The segment is decoration in a store listing; the digest that
|
|
176
|
+
* follows it is what identifies the slot.
|
|
177
|
+
*/
|
|
178
|
+
const LOCAL_DIRECTORY_SEGMENT = 'directory';
|
|
179
|
+
/**
|
|
180
|
+
* Whether the package came from a local directory — a `file:` directory
|
|
181
|
+
* dependency or an injected workspace package.
|
|
182
|
+
*
|
|
183
|
+
* Such a package needs a slot of its own per project. A directory resolution is
|
|
184
|
+
* the one resolution with no integrity: it is a path relative to the lockfile,
|
|
185
|
+
* so `file:dep` hashes identically in every project that happens to depend on a
|
|
186
|
+
* directory of that name. Sharing the slot would hand one project the files of
|
|
187
|
+
* whichever project installed first, and because the source directory is
|
|
188
|
+
* mutable pnpm re-imports it on every install — so the projects would go on
|
|
189
|
+
* overwriting each other's dependency.
|
|
190
|
+
*/
|
|
191
|
+
function isLocalDirectoryResolution(resolution) {
|
|
192
|
+
return resolution != null && 'type' in resolution && resolution.type === 'directory';
|
|
174
193
|
}
|
|
175
194
|
export function calcLeafGlobalVirtualStorePath(fullPkgId, name, version) {
|
|
176
195
|
const depsHash = hashObject({ id: fullPkgId, deps: {} });
|
|
@@ -244,6 +263,7 @@ export function lockfileToDepGraph(lockfile, supportedArchitectures) {
|
|
|
244
263
|
});
|
|
245
264
|
graph[depPath] = {
|
|
246
265
|
children,
|
|
266
|
+
resolution: pkgSnapshot.resolution,
|
|
247
267
|
fullPkgId: createFullPkgId(getPkgIdWithPatchHash(depPath), pkgSnapshot.resolution, supportedArchitectures),
|
|
248
268
|
};
|
|
249
269
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/deps.graph-hasher",
|
|
3
|
-
"version": "1100.2.
|
|
3
|
+
"version": "1100.2.13",
|
|
4
4
|
"description": "Calculates the state of a dependency",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -28,17 +28,17 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@pnpm/crypto.object-hasher": "1100.0.1",
|
|
31
|
-
"@pnpm/deps.path": "1100.0.
|
|
32
|
-
"@pnpm/engine.runtime.system-version": "1100.0.
|
|
33
|
-
"@pnpm/lockfile.types": "1100.0.
|
|
34
|
-
"@pnpm/lockfile.utils": "1100.1.
|
|
35
|
-
"@pnpm/resolving.resolver-base": "1100.5.
|
|
36
|
-
"@pnpm/types": "1101.
|
|
31
|
+
"@pnpm/deps.path": "1100.0.12",
|
|
32
|
+
"@pnpm/engine.runtime.system-version": "1100.0.7",
|
|
33
|
+
"@pnpm/lockfile.types": "1100.0.17",
|
|
34
|
+
"@pnpm/lockfile.utils": "1100.1.6",
|
|
35
|
+
"@pnpm/resolving.resolver-base": "1100.5.5",
|
|
36
|
+
"@pnpm/types": "1101.7.0",
|
|
37
37
|
"detect-libc": "^2.1.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@jest/globals": "30.4.1",
|
|
41
|
-
"@pnpm/deps.graph-hasher": "1100.2.
|
|
41
|
+
"@pnpm/deps.graph-hasher": "1100.2.13"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=22.13"
|