harnessbrew 0.5.2 → 0.6.1
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 +31 -0
- package/README.md +157 -80
- package/README.zh-CN.md +373 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +184 -26
- package/dist/cli.js.map +1 -1
- package/dist/core/adapter-plugins.d.ts +12 -0
- package/dist/core/adapter-plugins.d.ts.map +1 -0
- package/dist/core/adapter-plugins.js +151 -0
- package/dist/core/adapter-plugins.js.map +1 -0
- package/dist/core/bundle.d.ts +33 -5
- package/dist/core/bundle.d.ts.map +1 -1
- package/dist/core/bundle.js +329 -60
- package/dist/core/bundle.js.map +1 -1
- package/dist/core/doctor.d.ts +2 -2
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +2 -0
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/git.d.ts +1 -0
- package/dist/core/git.d.ts.map +1 -1
- package/dist/core/git.js +17 -0
- package/dist/core/git.js.map +1 -1
- package/dist/core/installations.d.ts +1 -0
- package/dist/core/installations.d.ts.map +1 -1
- package/dist/core/installations.js +135 -14
- package/dist/core/installations.js.map +1 -1
- package/dist/core/journal.d.ts +26 -0
- package/dist/core/journal.d.ts.map +1 -0
- package/dist/core/journal.js +363 -0
- package/dist/core/journal.js.map +1 -0
- package/dist/core/locks.d.ts +10 -0
- package/dist/core/locks.d.ts.map +1 -0
- package/dist/core/locks.js +90 -0
- package/dist/core/locks.js.map +1 -0
- package/dist/core/paths.d.ts +1 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +3 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/state.d.ts +2 -0
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/state.js +21 -2
- package/dist/core/state.js.map +1 -1
- package/dist/core/taps.d.ts +7 -1
- package/dist/core/taps.d.ts.map +1 -1
- package/dist/core/taps.js +74 -16
- package/dist/core/taps.js.map +1 -1
- package/dist/core/targets/claude-code.d.ts.map +1 -1
- package/dist/core/targets/claude-code.js +11 -1
- package/dist/core/targets/claude-code.js.map +1 -1
- package/dist/core/targets/codex.d.ts.map +1 -1
- package/dist/core/targets/codex.js +11 -1
- package/dist/core/targets/codex.js.map +1 -1
- package/dist/core/targets/planner.d.ts +2 -3
- package/dist/core/targets/planner.d.ts.map +1 -1
- package/dist/core/targets/planner.js +43 -3
- package/dist/core/targets/planner.js.map +1 -1
- package/dist/core/targets/registry.d.ts +7 -3
- package/dist/core/targets/registry.d.ts.map +1 -1
- package/dist/core/targets/registry.js +55 -0
- package/dist/core/targets/registry.js.map +1 -1
- package/dist/core/targets/transaction.d.ts.map +1 -1
- package/dist/core/targets/transaction.js +46 -10
- package/dist/core/targets/transaction.js.map +1 -1
- package/dist/core/targets/types.d.ts +8 -4
- package/dist/core/targets/types.d.ts.map +1 -1
- package/dist/core/targets/types.js +1 -1
- package/dist/core/targets/types.js.map +1 -1
- package/dist/core/targets.d.ts +6 -7
- package/dist/core/targets.d.ts.map +1 -1
- package/dist/core/targets.js +33 -22
- package/dist/core/targets.js.map +1 -1
- package/dist/core/upgrades.d.ts.map +1 -1
- package/dist/core/upgrades.js +10 -1
- package/dist/core/upgrades.js.map +1 -1
- package/dist/index.d.ts +13 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-plugins.js","sourceRoot":"","sources":["../../src/core/adapter-plugins.ts"],"names":[],"mappings":"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"}
|
package/dist/core/bundle.d.ts
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type TargetName } from "./targets.js";
|
|
2
2
|
export interface HarnessTapDeclaration {
|
|
3
3
|
name: string;
|
|
4
4
|
git: string;
|
|
5
5
|
ref?: string;
|
|
6
|
+
trust?: boolean;
|
|
6
7
|
}
|
|
7
8
|
export interface HarnessAssetDeclaration {
|
|
8
9
|
formula: string;
|
|
9
|
-
targets:
|
|
10
|
+
targets: HarnessTargetDeclaration[];
|
|
11
|
+
}
|
|
12
|
+
export interface HarnessTargetDeclaration {
|
|
13
|
+
target: TargetName;
|
|
14
|
+
scope: "user" | "project";
|
|
15
|
+
project?: string;
|
|
16
|
+
root?: string;
|
|
10
17
|
}
|
|
11
18
|
export interface Harnessfile {
|
|
12
|
-
schemaVersion: 1;
|
|
19
|
+
schemaVersion: 1 | 2;
|
|
13
20
|
taps: HarnessTapDeclaration[];
|
|
14
21
|
assets: HarnessAssetDeclaration[];
|
|
15
22
|
}
|
|
16
|
-
export interface
|
|
23
|
+
export interface HarnessLockV1 {
|
|
17
24
|
schemaVersion: 1;
|
|
18
25
|
taps: Array<{
|
|
19
26
|
name: string;
|
|
@@ -28,8 +35,29 @@ export interface HarnessLock {
|
|
|
28
35
|
targets: string[];
|
|
29
36
|
}>;
|
|
30
37
|
}
|
|
38
|
+
export interface HarnessLockV2 {
|
|
39
|
+
schemaVersion: 2;
|
|
40
|
+
manifestDigest: string;
|
|
41
|
+
adapterVersion: string;
|
|
42
|
+
taps: Array<{
|
|
43
|
+
name: string;
|
|
44
|
+
git: string;
|
|
45
|
+
commit: string;
|
|
46
|
+
ref?: string;
|
|
47
|
+
}>;
|
|
48
|
+
assets: Array<{
|
|
49
|
+
formula: string;
|
|
50
|
+
commit: string;
|
|
51
|
+
digest: string;
|
|
52
|
+
dependencies: string[];
|
|
53
|
+
requested: boolean;
|
|
54
|
+
targets: HarnessTargetDeclaration[];
|
|
55
|
+
}>;
|
|
56
|
+
}
|
|
57
|
+
export type HarnessLock = HarnessLockV1 | HarnessLockV2;
|
|
31
58
|
export interface BundleOptions {
|
|
32
|
-
targetRoots?: Partial<Record<
|
|
59
|
+
targetRoots?: Partial<Record<TargetName, string>>;
|
|
60
|
+
updateLock?: boolean;
|
|
33
61
|
}
|
|
34
62
|
export interface BundleCleanupResult {
|
|
35
63
|
removed: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/core/bundle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/core/bundle.ts"],"names":[],"mappings":"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"}
|
package/dist/core/bundle.js
CHANGED
|
@@ -1,15 +1,56 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { parse } from "yaml";
|
|
4
5
|
import { HarnessBrewError } from "./errors.js";
|
|
5
6
|
import { getFormula } from "./formulas.js";
|
|
6
|
-
import { installFormula, listInstalled, resolveDependencies, uninstallFormula } from "./installations.js";
|
|
7
|
-
import { addTap, checkoutTap, listTaps, updateTaps } from "./taps.js";
|
|
8
|
-
import {
|
|
7
|
+
import { installFormula, listInstalled, resolveDependencies, uninstallFormula, writeReceipt } from "./installations.js";
|
|
8
|
+
import { addTap, checkoutTap, listTaps, setTapTrust, updateTaps } from "./taps.js";
|
|
9
|
+
import { linkFormula, targetDestination } from "./targets.js";
|
|
10
|
+
import { removeTargetOperation } from "./targets/transaction.js";
|
|
11
|
+
import { hasTargetAdapter, targetAdapterVersion } from "./targets/registry.js";
|
|
9
12
|
import { upgradeFormulas } from "./upgrades.js";
|
|
13
|
+
import { captureMissingParents, captureTransactionPath, markTransactionPath, withJournalTransaction } from "./journal.js";
|
|
10
14
|
function isRecord(value) {
|
|
11
15
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12
16
|
}
|
|
17
|
+
function assertKeys(value, allowed, context) {
|
|
18
|
+
const unknown = Object.keys(value).find((key) => !allowed.includes(key));
|
|
19
|
+
if (unknown !== undefined)
|
|
20
|
+
throw new HarnessBrewError(`Unknown ${context} field: ${unknown}`);
|
|
21
|
+
}
|
|
22
|
+
function targetDeclaration(value, context) {
|
|
23
|
+
if (!isRecord(value))
|
|
24
|
+
throw new HarnessBrewError(`Invalid Target declaration for ${context}`);
|
|
25
|
+
assertKeys(value, ["target", "scope", "project", "root"], `Target declaration for ${context}`);
|
|
26
|
+
if (typeof value.target !== "string" || !hasTargetAdapter(value.target)) {
|
|
27
|
+
throw new HarnessBrewError(`Invalid Target in ${context}`);
|
|
28
|
+
}
|
|
29
|
+
if (value.scope !== "user" && value.scope !== "project") {
|
|
30
|
+
throw new HarnessBrewError(`Target scope must be user or project in ${context}`);
|
|
31
|
+
}
|
|
32
|
+
if (value.project !== undefined && (typeof value.project !== "string" || value.project.trim() === "")) {
|
|
33
|
+
throw new HarnessBrewError(`Invalid Target project path in ${context}`);
|
|
34
|
+
}
|
|
35
|
+
if (value.root !== undefined && (typeof value.root !== "string" || value.root.trim() === "")) {
|
|
36
|
+
throw new HarnessBrewError(`Invalid Target root path in ${context}`);
|
|
37
|
+
}
|
|
38
|
+
if (value.scope === "user" && value.project !== undefined) {
|
|
39
|
+
throw new HarnessBrewError(`User Target cannot declare project in ${context}`);
|
|
40
|
+
}
|
|
41
|
+
if (value.scope === "project" && value.project === undefined) {
|
|
42
|
+
throw new HarnessBrewError(`Project Target must declare project in ${context}`);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
target: value.target,
|
|
46
|
+
scope: value.scope,
|
|
47
|
+
...(value.project === undefined ? {} : { project: path.posix.normalize(value.project) }),
|
|
48
|
+
...(value.root === undefined ? {} : { root: path.posix.normalize(value.root) })
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function targetKey(target) {
|
|
52
|
+
return JSON.stringify([target.target, target.scope, target.project ?? "", target.root ?? ""]);
|
|
53
|
+
}
|
|
13
54
|
export async function readHarnessfile(filePath) {
|
|
14
55
|
let raw;
|
|
15
56
|
try {
|
|
@@ -18,9 +59,12 @@ export async function readHarnessfile(filePath) {
|
|
|
18
59
|
catch (error) {
|
|
19
60
|
throw new HarnessBrewError(`Invalid Harnessfile ${filePath}: ${error.message}`);
|
|
20
61
|
}
|
|
21
|
-
if (!isRecord(raw) || (raw.schemaVersion ?? 1) !== 1) {
|
|
62
|
+
if (!isRecord(raw) || ((raw.schemaVersion ?? 1) !== 1 && raw.schemaVersion !== 2)) {
|
|
22
63
|
throw new HarnessBrewError(`Unsupported Harnessfile schema: ${filePath}`);
|
|
23
64
|
}
|
|
65
|
+
const schemaVersion = (raw.schemaVersion ?? 1);
|
|
66
|
+
if (schemaVersion === 2)
|
|
67
|
+
assertKeys(raw, ["schemaVersion", "taps", "assets"], "Harnessfile");
|
|
24
68
|
if (!Array.isArray(raw.taps) || !Array.isArray(raw.assets)) {
|
|
25
69
|
throw new HarnessBrewError(`Harnessfile must contain taps and assets arrays: ${filePath}`);
|
|
26
70
|
}
|
|
@@ -28,20 +72,46 @@ export async function readHarnessfile(filePath) {
|
|
|
28
72
|
if (!isRecord(item) || typeof item.name !== "string" || typeof item.git !== "string") {
|
|
29
73
|
throw new HarnessBrewError(`Invalid tap declaration in ${filePath}`);
|
|
30
74
|
}
|
|
31
|
-
if (
|
|
75
|
+
if (schemaVersion === 2)
|
|
76
|
+
assertKeys(item, ["name", "git", "ref", "trust"], `Tap ${item.name}`);
|
|
77
|
+
if (item.git.trim() === "")
|
|
78
|
+
throw new HarnessBrewError(`Invalid tap Git URL in ${filePath}`);
|
|
79
|
+
if (item.ref !== undefined && (typeof item.ref !== "string" || item.ref.trim() === "")) {
|
|
32
80
|
throw new HarnessBrewError(`Invalid tap ref in ${filePath}`);
|
|
33
81
|
}
|
|
34
|
-
|
|
82
|
+
if (item.trust !== undefined && typeof item.trust !== "boolean") {
|
|
83
|
+
throw new HarnessBrewError(`Invalid tap trust policy in ${filePath}`);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
name: item.name,
|
|
87
|
+
git: item.git,
|
|
88
|
+
...(item.ref === undefined ? {} : { ref: item.ref }),
|
|
89
|
+
...(item.trust === undefined ? {} : { trust: item.trust })
|
|
90
|
+
};
|
|
35
91
|
});
|
|
36
92
|
const assets = raw.assets.map((item) => {
|
|
37
93
|
if (!isRecord(item) || typeof item.formula !== "string") {
|
|
38
94
|
throw new HarnessBrewError(`Invalid asset declaration in ${filePath}`);
|
|
39
95
|
}
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
42
|
-
|
|
96
|
+
const formula = item.formula;
|
|
97
|
+
if (schemaVersion === 2)
|
|
98
|
+
assertKeys(item, ["formula", "targets"], `Asset ${formula}`);
|
|
99
|
+
const declaredTargets = item.targets ?? [];
|
|
100
|
+
if (!Array.isArray(declaredTargets)) {
|
|
101
|
+
throw new HarnessBrewError(`Invalid asset targets for ${formula}`);
|
|
102
|
+
}
|
|
103
|
+
const targets = schemaVersion === 1
|
|
104
|
+
? declaredTargets.map((target) => {
|
|
105
|
+
if (typeof target !== "string" || !hasTargetAdapter(target)) {
|
|
106
|
+
throw new HarnessBrewError(`Invalid asset targets for ${formula}`);
|
|
107
|
+
}
|
|
108
|
+
return { target, scope: "user" };
|
|
109
|
+
})
|
|
110
|
+
: declaredTargets.map((target) => targetDeclaration(target, formula));
|
|
111
|
+
if (new Set(targets.map(targetKey)).size !== targets.length) {
|
|
112
|
+
throw new HarnessBrewError(`Harnessfile contains duplicate Target placements for ${formula}.`);
|
|
43
113
|
}
|
|
44
|
-
return { formula
|
|
114
|
+
return { formula, targets };
|
|
45
115
|
});
|
|
46
116
|
if (new Set(taps.map((tap) => tap.name)).size !== taps.length) {
|
|
47
117
|
throw new HarnessBrewError("Harnessfile contains duplicate taps.");
|
|
@@ -49,17 +119,79 @@ export async function readHarnessfile(filePath) {
|
|
|
49
119
|
if (new Set(assets.map((asset) => asset.formula)).size !== assets.length) {
|
|
50
120
|
throw new HarnessBrewError("Harnessfile contains duplicate assets.");
|
|
51
121
|
}
|
|
52
|
-
return { schemaVersion
|
|
122
|
+
return { schemaVersion, taps, assets };
|
|
53
123
|
}
|
|
54
124
|
export function lockfilePath(harnessfilePath) {
|
|
55
125
|
return `${harnessfilePath}.lock`;
|
|
56
126
|
}
|
|
57
127
|
async function readLock(filePath) {
|
|
58
128
|
try {
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
129
|
+
const value = JSON.parse(await readFile(filePath, "utf8"));
|
|
130
|
+
if (!isRecord(value) || (value.schemaVersion !== 1 && value.schemaVersion !== 2)
|
|
131
|
+
|| !Array.isArray(value.taps) || !Array.isArray(value.assets))
|
|
61
132
|
throw new Error("shape");
|
|
62
|
-
|
|
133
|
+
const validCommit = (commit) => typeof commit === "string" && /^[0-9a-f]{40}$/u.test(commit);
|
|
134
|
+
const validDigest = (digest) => typeof digest === "string" && /^[0-9a-f]{64}$/u.test(digest);
|
|
135
|
+
const validStrings = (items) => Array.isArray(items)
|
|
136
|
+
&& items.every((item) => typeof item === "string");
|
|
137
|
+
const taps = value.taps.map((item) => {
|
|
138
|
+
if (!isRecord(item) || typeof item.name !== "string" || typeof item.git !== "string" || !validCommit(item.commit)
|
|
139
|
+
|| (item.ref !== undefined && typeof item.ref !== "string"))
|
|
140
|
+
throw new Error("tap");
|
|
141
|
+
if (value.schemaVersion === 2)
|
|
142
|
+
assertKeys(item, ["name", "git", "commit", "ref"], `Lock Tap ${item.name}`);
|
|
143
|
+
return {
|
|
144
|
+
name: item.name,
|
|
145
|
+
git: item.git,
|
|
146
|
+
commit: item.commit,
|
|
147
|
+
...(item.ref === undefined ? {} : { ref: item.ref })
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
if (new Set(taps.map((tap) => tap.name)).size !== taps.length)
|
|
151
|
+
throw new Error("duplicate tap");
|
|
152
|
+
if (value.schemaVersion === 1) {
|
|
153
|
+
const assets = value.assets.map((item) => {
|
|
154
|
+
if (!isRecord(item) || typeof item.formula !== "string" || !validCommit(item.commit)
|
|
155
|
+
|| !validStrings(item.dependencies) || !validStrings(item.targets))
|
|
156
|
+
throw new Error("asset");
|
|
157
|
+
return { formula: item.formula, commit: item.commit, dependencies: item.dependencies, targets: item.targets };
|
|
158
|
+
});
|
|
159
|
+
return { schemaVersion: 1, taps, assets };
|
|
160
|
+
}
|
|
161
|
+
assertKeys(value, ["schemaVersion", "manifestDigest", "adapterVersion", "taps", "assets"], "Harnessfile lock");
|
|
162
|
+
if (!validDigest(value.manifestDigest) || typeof value.adapterVersion !== "string" || value.adapterVersion === "") {
|
|
163
|
+
throw new Error("metadata");
|
|
164
|
+
}
|
|
165
|
+
const assets = value.assets.map((item) => {
|
|
166
|
+
if (!isRecord(item))
|
|
167
|
+
throw new Error("asset");
|
|
168
|
+
assertKeys(item, ["formula", "commit", "digest", "dependencies", "requested", "targets"], "Lock asset");
|
|
169
|
+
if (typeof item.formula !== "string" || !validCommit(item.commit) || !validDigest(item.digest)
|
|
170
|
+
|| !validStrings(item.dependencies) || typeof item.requested !== "boolean" || !Array.isArray(item.targets)) {
|
|
171
|
+
throw new Error("asset");
|
|
172
|
+
}
|
|
173
|
+
const formula = item.formula;
|
|
174
|
+
const targets = item.targets.map((target) => targetDeclaration(target, formula));
|
|
175
|
+
if (new Set(targets.map(targetKey)).size !== targets.length)
|
|
176
|
+
throw new Error("duplicate target");
|
|
177
|
+
return {
|
|
178
|
+
formula,
|
|
179
|
+
commit: item.commit,
|
|
180
|
+
digest: item.digest,
|
|
181
|
+
dependencies: item.dependencies,
|
|
182
|
+
requested: item.requested,
|
|
183
|
+
targets
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
if (new Set(assets.map((asset) => asset.formula)).size !== assets.length)
|
|
187
|
+
throw new Error("duplicate asset");
|
|
188
|
+
return {
|
|
189
|
+
schemaVersion: 2,
|
|
190
|
+
manifestDigest: value.manifestDigest,
|
|
191
|
+
adapterVersion: value.adapterVersion,
|
|
192
|
+
taps,
|
|
193
|
+
assets
|
|
194
|
+
};
|
|
63
195
|
}
|
|
64
196
|
catch (error) {
|
|
65
197
|
if (error.code === "ENOENT")
|
|
@@ -68,10 +200,15 @@ async function readLock(filePath) {
|
|
|
68
200
|
}
|
|
69
201
|
}
|
|
70
202
|
async function writeLock(filePath, lock) {
|
|
71
|
-
await mkdir(path.dirname(filePath), { recursive: true });
|
|
72
203
|
const temporaryPath = `${filePath}.${process.pid}.tmp`;
|
|
204
|
+
await captureMissingParents(filePath);
|
|
205
|
+
await captureTransactionPath(filePath);
|
|
206
|
+
await captureTransactionPath(temporaryPath);
|
|
207
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
73
208
|
await writeFile(temporaryPath, `${JSON.stringify(lock, null, 2)}\n`, "utf8");
|
|
74
209
|
await rename(temporaryPath, filePath);
|
|
210
|
+
await markTransactionPath(filePath);
|
|
211
|
+
await markTransactionPath(temporaryPath);
|
|
75
212
|
}
|
|
76
213
|
async function syncTaps(home, manifest, lock) {
|
|
77
214
|
const registered = new Map((await listTaps(home)).map((tap) => [tap.name, tap]));
|
|
@@ -85,8 +222,10 @@ async function syncTaps(home, manifest, lock) {
|
|
|
85
222
|
throw new HarnessBrewError(`Lockfile Tap URL mismatch for ${declaration.name}`);
|
|
86
223
|
}
|
|
87
224
|
if (existing === undefined) {
|
|
88
|
-
|
|
89
|
-
|
|
225
|
+
await addTap(home, declaration.name, declaration.git, {
|
|
226
|
+
...(declaration.ref === undefined ? {} : { ref: declaration.ref }),
|
|
227
|
+
trust: manifest.schemaVersion === 1 ? true : declaration.trust ?? false
|
|
228
|
+
});
|
|
90
229
|
}
|
|
91
230
|
else if (locked === undefined) {
|
|
92
231
|
if (existing.ref !== declaration.ref) {
|
|
@@ -94,63 +233,187 @@ async function syncTaps(home, manifest, lock) {
|
|
|
94
233
|
}
|
|
95
234
|
await updateTaps(home, declaration.name);
|
|
96
235
|
}
|
|
236
|
+
if (manifest.schemaVersion === 2) {
|
|
237
|
+
await setTapTrust(home, declaration.name, declaration.trust ?? false);
|
|
238
|
+
}
|
|
97
239
|
if (locked !== undefined)
|
|
98
240
|
await checkoutTap(home, declaration.name, locked.commit);
|
|
99
241
|
}
|
|
100
242
|
}
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
243
|
+
function canonicalTargets(targets) {
|
|
244
|
+
return [...targets].sort((left, right) => targetKey(left).localeCompare(targetKey(right)));
|
|
245
|
+
}
|
|
246
|
+
function manifestDigest(manifest) {
|
|
247
|
+
const normalized = {
|
|
248
|
+
schemaVersion: manifest.schemaVersion,
|
|
249
|
+
taps: [...manifest.taps].sort((left, right) => left.name.localeCompare(right.name)),
|
|
250
|
+
assets: [...manifest.assets]
|
|
251
|
+
.sort((left, right) => left.formula.localeCompare(right.formula))
|
|
252
|
+
.map((asset) => ({ formula: asset.formula, targets: canonicalTargets(asset.targets) }))
|
|
253
|
+
};
|
|
254
|
+
return createHash("sha256").update(JSON.stringify(normalized)).digest("hex");
|
|
255
|
+
}
|
|
256
|
+
function formulaDigest(receipt) {
|
|
257
|
+
const inventory = [...receipt.files]
|
|
258
|
+
.sort((left, right) => left.path.localeCompare(right.path))
|
|
259
|
+
.map((file) => [file.path, file.sha256, file.mode ?? null]);
|
|
260
|
+
return createHash("sha256").update(JSON.stringify(inventory)).digest("hex");
|
|
104
261
|
}
|
|
105
|
-
|
|
262
|
+
function resolveDeclaredPath(harnessfilePath, declared) {
|
|
263
|
+
const resolved = path.resolve(path.dirname(harnessfilePath), declared);
|
|
264
|
+
if (resolved === path.parse(resolved).root) {
|
|
265
|
+
throw new HarnessBrewError(`Unsafe Harnessfile Target path: ${declared}`);
|
|
266
|
+
}
|
|
267
|
+
return resolved;
|
|
268
|
+
}
|
|
269
|
+
function placementOptions(harnessfilePath, declaration, options) {
|
|
270
|
+
const override = options.targetRoots?.[declaration.target];
|
|
271
|
+
const resolvedOverride = override === undefined ? undefined : path.resolve(override);
|
|
272
|
+
if (resolvedOverride !== undefined && resolvedOverride === path.parse(resolvedOverride).root) {
|
|
273
|
+
throw new HarnessBrewError(`Unsafe Target root override: ${override}`);
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
scope: declaration.scope,
|
|
277
|
+
...(resolvedOverride !== undefined
|
|
278
|
+
? { root: resolvedOverride }
|
|
279
|
+
: declaration.root === undefined ? {} : { root: resolveDeclaredPath(harnessfilePath, declaration.root) }),
|
|
280
|
+
...(declaration.project === undefined
|
|
281
|
+
? {} : { projectRoot: resolveDeclaredPath(harnessfilePath, declaration.project) })
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async function desiredFormulas(home, manifest) {
|
|
285
|
+
const desired = new Map();
|
|
286
|
+
for (const asset of manifest.assets) {
|
|
287
|
+
const root = await getFormula(home, asset.formula);
|
|
288
|
+
for (const formula of await resolveDependencies(home, root)) {
|
|
289
|
+
const current = desired.get(formula.coordinate) ?? { requested: false, targets: new Map() };
|
|
290
|
+
if (formula.coordinate === root.coordinate)
|
|
291
|
+
current.requested = true;
|
|
292
|
+
for (const target of asset.targets)
|
|
293
|
+
current.targets.set(targetKey(target), target);
|
|
294
|
+
desired.set(formula.coordinate, current);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return desired;
|
|
298
|
+
}
|
|
299
|
+
async function reconcileTargets(home, harnessfilePath, receipt, desired, options) {
|
|
300
|
+
const placements = [...desired.targets.values()].map((declaration) => ({
|
|
301
|
+
declaration,
|
|
302
|
+
options: placementOptions(harnessfilePath, declaration, options),
|
|
303
|
+
destination: targetDestination(receipt, declaration.target, placementOptions(harnessfilePath, declaration, options))
|
|
304
|
+
}));
|
|
305
|
+
const destinations = new Set(placements.map((placement) => placement.destination));
|
|
306
|
+
const removed = receipt.operations.filter((operation) => !destinations.has(operation.destination));
|
|
307
|
+
for (const operation of [...removed].reverse())
|
|
308
|
+
await removeTargetOperation(operation);
|
|
309
|
+
if (removed.length > 0 || receipt.requested !== desired.requested) {
|
|
310
|
+
receipt.operations = receipt.operations.filter((operation) => !removed.includes(operation));
|
|
311
|
+
receipt.links = receipt.links.filter((link) => destinations.has(link.path));
|
|
312
|
+
receipt.targets = [...new Set(receipt.operations.map((operation) => operation.target))];
|
|
313
|
+
receipt.requested = desired.requested;
|
|
314
|
+
await writeReceipt(home, receipt);
|
|
315
|
+
}
|
|
316
|
+
for (const placement of placements) {
|
|
317
|
+
await linkFormula(home, receipt.coordinate, placement.declaration.target, placement.options);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function sameLock(left, right) {
|
|
321
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
322
|
+
}
|
|
323
|
+
async function bundleInstallInternal(home, harnessfilePath, options) {
|
|
106
324
|
const manifest = await readHarnessfile(harnessfilePath);
|
|
107
325
|
const targetLockPath = lockfilePath(harnessfilePath);
|
|
108
326
|
const existingLock = await readLock(targetLockPath);
|
|
109
|
-
|
|
110
|
-
const
|
|
327
|
+
const digest = manifestDigest(manifest);
|
|
328
|
+
const adapterVersion = targetAdapterVersion(manifest.assets.flatMap((asset) => asset.targets.map((target) => target.target)));
|
|
329
|
+
if (options.updateLock !== true && existingLock !== undefined) {
|
|
330
|
+
if (existingLock.schemaVersion !== manifest.schemaVersion) {
|
|
331
|
+
throw new HarnessBrewError("Harnessfile and lockfile schema versions differ; use --update-lock.");
|
|
332
|
+
}
|
|
333
|
+
if (existingLock.schemaVersion === 2 && existingLock.manifestDigest !== digest) {
|
|
334
|
+
throw new HarnessBrewError("Harnessfile changed since the lockfile was created; use --update-lock.");
|
|
335
|
+
}
|
|
336
|
+
if (existingLock.schemaVersion === 2 && existingLock.adapterVersion !== adapterVersion) {
|
|
337
|
+
throw new HarnessBrewError(`Harnessfile lock requires adapter version ${existingLock.adapterVersion}; installed version is ${adapterVersion}. Use --update-lock.`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const resolutionLock = options.updateLock === true ? undefined : existingLock;
|
|
341
|
+
await syncTaps(home, manifest, resolutionLock);
|
|
111
342
|
for (const asset of manifest.assets) {
|
|
112
343
|
await upgradeFormulas(home, asset.formula);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
344
|
+
await installFormula(home, asset.formula);
|
|
345
|
+
}
|
|
346
|
+
const desired = await desiredFormulas(home, manifest);
|
|
347
|
+
let installed = new Map((await listInstalled(home)).map((receipt) => [receipt.coordinate, receipt]));
|
|
348
|
+
for (const [coordinate, declaration] of [...desired].sort(([left], [right]) => left.localeCompare(right))) {
|
|
349
|
+
const receipt = installed.get(coordinate);
|
|
350
|
+
if (receipt === undefined)
|
|
351
|
+
throw new HarnessBrewError(`Bundle formula was not installed: ${coordinate}`);
|
|
352
|
+
await reconcileTargets(home, harnessfilePath, receipt, declaration, options);
|
|
353
|
+
}
|
|
354
|
+
installed = new Map((await listInstalled(home)).map((receipt) => [receipt.coordinate, receipt]));
|
|
355
|
+
const resolved = [...desired.keys()].sort().map((coordinate) => {
|
|
356
|
+
const receipt = installed.get(coordinate);
|
|
357
|
+
if (receipt === undefined)
|
|
358
|
+
throw new HarnessBrewError(`Bundle formula was not installed: ${coordinate}`);
|
|
359
|
+
return receipt;
|
|
360
|
+
});
|
|
361
|
+
const taps = await listTaps(home);
|
|
362
|
+
const lockedTaps = [...manifest.taps].sort((left, right) => left.name.localeCompare(right.name)).map((declaration) => {
|
|
363
|
+
const tap = taps.find((candidate) => candidate.name === declaration.name);
|
|
364
|
+
if (tap === undefined)
|
|
365
|
+
throw new HarnessBrewError(`Tap was not synchronized: ${declaration.name}`);
|
|
366
|
+
return {
|
|
367
|
+
name: tap.name,
|
|
368
|
+
git: tap.url,
|
|
369
|
+
commit: tap.commit,
|
|
370
|
+
...(declaration.ref === undefined ? {} : { ref: declaration.ref })
|
|
371
|
+
};
|
|
372
|
+
});
|
|
373
|
+
const lock = manifest.schemaVersion === 1
|
|
374
|
+
? {
|
|
375
|
+
schemaVersion: 1,
|
|
376
|
+
taps: lockedTaps,
|
|
377
|
+
assets: resolved.map((receipt) => ({
|
|
378
|
+
formula: receipt.coordinate,
|
|
379
|
+
commit: receipt.commit,
|
|
380
|
+
dependencies: receipt.dependencies,
|
|
381
|
+
targets: [...receipt.targets].sort()
|
|
382
|
+
}))
|
|
383
|
+
}
|
|
384
|
+
: {
|
|
385
|
+
schemaVersion: 2,
|
|
386
|
+
manifestDigest: digest,
|
|
387
|
+
adapterVersion,
|
|
388
|
+
taps: lockedTaps,
|
|
389
|
+
assets: resolved.map((receipt) => ({
|
|
390
|
+
formula: receipt.coordinate,
|
|
391
|
+
commit: receipt.commit,
|
|
392
|
+
digest: formulaDigest(receipt),
|
|
393
|
+
dependencies: [...receipt.dependencies].sort(),
|
|
394
|
+
requested: desired.get(receipt.coordinate)?.requested ?? false,
|
|
395
|
+
targets: canonicalTargets([...(desired.get(receipt.coordinate)?.targets.values() ?? [])])
|
|
396
|
+
}))
|
|
397
|
+
};
|
|
398
|
+
if (resolutionLock !== undefined) {
|
|
399
|
+
if (resolutionLock.schemaVersion === 2 && !sameLock(lock, resolutionLock)) {
|
|
400
|
+
throw new HarnessBrewError("Installed bundle does not match Harnessfile.lock; use --update-lock to regenerate it.");
|
|
401
|
+
}
|
|
402
|
+
if (resolutionLock.schemaVersion === 1) {
|
|
403
|
+
for (const asset of resolutionLock.assets) {
|
|
404
|
+
const receipt = installed.get(asset.formula);
|
|
405
|
+
if (receipt !== undefined && receipt.commit !== asset.commit) {
|
|
406
|
+
throw new HarnessBrewError(`Locked commit mismatch for ${asset.formula}`);
|
|
407
|
+
}
|
|
127
408
|
}
|
|
128
409
|
}
|
|
129
410
|
}
|
|
130
|
-
const taps = await listTaps(home);
|
|
131
|
-
const lock = {
|
|
132
|
-
schemaVersion: 1,
|
|
133
|
-
taps: manifest.taps.map((declaration) => {
|
|
134
|
-
const tap = taps.find((candidate) => candidate.name === declaration.name);
|
|
135
|
-
if (tap === undefined)
|
|
136
|
-
throw new HarnessBrewError(`Tap was not synchronized: ${declaration.name}`);
|
|
137
|
-
return {
|
|
138
|
-
name: tap.name,
|
|
139
|
-
git: tap.url,
|
|
140
|
-
commit: tap.commit,
|
|
141
|
-
...(declaration.ref === undefined ? {} : { ref: declaration.ref })
|
|
142
|
-
};
|
|
143
|
-
}),
|
|
144
|
-
assets: [...resolved.values()].sort((left, right) => left.coordinate.localeCompare(right.coordinate)).map((receipt) => ({
|
|
145
|
-
formula: receipt.coordinate,
|
|
146
|
-
commit: receipt.commit,
|
|
147
|
-
dependencies: receipt.dependencies,
|
|
148
|
-
targets: receipt.targets
|
|
149
|
-
}))
|
|
150
|
-
};
|
|
151
411
|
await writeLock(targetLockPath, lock);
|
|
152
412
|
return lock;
|
|
153
413
|
}
|
|
414
|
+
export function bundleInstall(home, harnessfilePath, options = {}) {
|
|
415
|
+
return withJournalTransaction(home, "bundle:install", () => bundleInstallInternal(home, harnessfilePath, options));
|
|
416
|
+
}
|
|
154
417
|
async function desiredCoordinates(home, manifest) {
|
|
155
418
|
const desired = new Set();
|
|
156
419
|
for (const asset of manifest.assets) {
|
|
@@ -177,7 +440,7 @@ function removalOrder(receipts) {
|
|
|
177
440
|
receipts.forEach(visit);
|
|
178
441
|
return ordered;
|
|
179
442
|
}
|
|
180
|
-
|
|
443
|
+
async function bundleCleanupInternal(home, harnessfilePath) {
|
|
181
444
|
const manifest = await readHarnessfile(harnessfilePath);
|
|
182
445
|
const desired = await desiredCoordinates(home, manifest);
|
|
183
446
|
const installed = await listInstalled(home);
|
|
@@ -189,7 +452,13 @@ export async function bundleCleanup(home, harnessfilePath) {
|
|
|
189
452
|
}
|
|
190
453
|
return { removed, retained: installed.filter((receipt) => desired.has(receipt.coordinate)).map((receipt) => receipt.coordinate) };
|
|
191
454
|
}
|
|
455
|
+
export function bundleCleanup(home, harnessfilePath) {
|
|
456
|
+
return withJournalTransaction(home, "bundle:cleanup", () => bundleCleanupInternal(home, harnessfilePath));
|
|
457
|
+
}
|
|
192
458
|
export async function removeLock(harnessfilePath) {
|
|
193
|
-
|
|
459
|
+
const filePath = lockfilePath(harnessfilePath);
|
|
460
|
+
await captureTransactionPath(filePath);
|
|
461
|
+
await rm(filePath, { force: true });
|
|
462
|
+
await markTransactionPath(filePath);
|
|
194
463
|
}
|
|
195
464
|
//# sourceMappingURL=bundle.js.map
|