@claudexor/workspace 4.8.2 → 5.0.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.
Files changed (136) hide show
  1. package/dist/anchor-store.d.ts +20 -9
  2. package/dist/anchor-store.d.ts.map +1 -1
  3. package/dist/anchor-store.js +89 -14
  4. package/dist/anchor-store.js.map +1 -1
  5. package/dist/capture-failure.d.ts.map +1 -1
  6. package/dist/capture-failure.js +7 -2
  7. package/dist/capture-failure.js.map +1 -1
  8. package/dist/capture-inventory.d.ts +10 -0
  9. package/dist/capture-inventory.d.ts.map +1 -0
  10. package/dist/capture-inventory.js +63 -0
  11. package/dist/capture-inventory.js.map +1 -0
  12. package/dist/capture-objects.d.ts +32 -0
  13. package/dist/capture-objects.d.ts.map +1 -0
  14. package/dist/capture-objects.js +129 -0
  15. package/dist/capture-objects.js.map +1 -0
  16. package/dist/cleanup-fault.d.ts +18 -0
  17. package/dist/cleanup-fault.d.ts.map +1 -0
  18. package/dist/cleanup-fault.js +45 -0
  19. package/dist/cleanup-fault.js.map +1 -0
  20. package/dist/continuation-evidence.d.ts +61 -15
  21. package/dist/continuation-evidence.d.ts.map +1 -1
  22. package/dist/continuation-evidence.js +151 -36
  23. package/dist/continuation-evidence.js.map +1 -1
  24. package/dist/continuation-facts.d.ts +93 -0
  25. package/dist/continuation-facts.d.ts.map +1 -0
  26. package/dist/continuation-facts.js +162 -0
  27. package/dist/continuation-facts.js.map +1 -0
  28. package/dist/directory-workspace.d.ts.map +1 -1
  29. package/dist/directory-workspace.js +1 -3
  30. package/dist/directory-workspace.js.map +1 -1
  31. package/dist/files-io.d.ts.map +1 -1
  32. package/dist/files-io.js +1 -7
  33. package/dist/files-io.js.map +1 -1
  34. package/dist/fs-presence.d.ts +12 -0
  35. package/dist/fs-presence.d.ts.map +1 -0
  36. package/dist/fs-presence.js +35 -0
  37. package/dist/fs-presence.js.map +1 -0
  38. package/dist/git-nested-repositories.d.ts.map +1 -1
  39. package/dist/git-nested-repositories.js +11 -2
  40. package/dist/git-nested-repositories.js.map +1 -1
  41. package/dist/git-observed.d.ts +75 -0
  42. package/dist/git-observed.d.ts.map +1 -0
  43. package/dist/git-observed.js +172 -0
  44. package/dist/git-observed.js.map +1 -0
  45. package/dist/git-result.d.ts +36 -0
  46. package/dist/git-result.d.ts.map +1 -0
  47. package/dist/git-result.js +96 -0
  48. package/dist/git-result.js.map +1 -0
  49. package/dist/git-run.d.ts +11 -0
  50. package/dist/git-run.d.ts.map +1 -1
  51. package/dist/git-run.js +24 -0
  52. package/dist/git-run.js.map +1 -1
  53. package/dist/git-snapshot.d.ts +40 -0
  54. package/dist/git-snapshot.d.ts.map +1 -0
  55. package/dist/git-snapshot.js +238 -0
  56. package/dist/git-snapshot.js.map +1 -0
  57. package/dist/git-transient-capture.d.ts +63 -16
  58. package/dist/git-transient-capture.d.ts.map +1 -1
  59. package/dist/git-transient-capture.js +170 -57
  60. package/dist/git-transient-capture.js.map +1 -1
  61. package/dist/git.d.ts +46 -21
  62. package/dist/git.d.ts.map +1 -1
  63. package/dist/git.js +164 -103
  64. package/dist/git.js.map +1 -1
  65. package/dist/index.d.ts +9 -1
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +9 -1
  68. package/dist/index.js.map +1 -1
  69. package/dist/lanes.d.ts +2 -1
  70. package/dist/lanes.d.ts.map +1 -1
  71. package/dist/lanes.js +7 -6
  72. package/dist/lanes.js.map +1 -1
  73. package/dist/manager.d.ts +21 -7
  74. package/dist/manager.d.ts.map +1 -1
  75. package/dist/manager.js +30 -17
  76. package/dist/manager.js.map +1 -1
  77. package/dist/object-compose.d.ts +58 -0
  78. package/dist/object-compose.d.ts.map +1 -0
  79. package/dist/object-compose.js +444 -0
  80. package/dist/object-compose.js.map +1 -0
  81. package/dist/object-materialize.d.ts +52 -0
  82. package/dist/object-materialize.d.ts.map +1 -0
  83. package/dist/object-materialize.js +467 -0
  84. package/dist/object-materialize.js.map +1 -0
  85. package/dist/object-occupied.d.ts +27 -0
  86. package/dist/object-occupied.d.ts.map +1 -0
  87. package/dist/object-occupied.js +131 -0
  88. package/dist/object-occupied.js.map +1 -0
  89. package/dist/object-revert.d.ts +45 -0
  90. package/dist/object-revert.d.ts.map +1 -0
  91. package/dist/object-revert.js +265 -0
  92. package/dist/object-revert.js.map +1 -0
  93. package/dist/object-saved-files.d.ts +50 -0
  94. package/dist/object-saved-files.d.ts.map +1 -0
  95. package/dist/object-saved-files.js +176 -0
  96. package/dist/object-saved-files.js.map +1 -0
  97. package/dist/object-sparse.d.ts +22 -0
  98. package/dist/object-sparse.d.ts.map +1 -0
  99. package/dist/object-sparse.js +72 -0
  100. package/dist/object-sparse.js.map +1 -0
  101. package/dist/object-store-leases.d.ts +41 -0
  102. package/dist/object-store-leases.d.ts.map +1 -0
  103. package/dist/object-store-leases.js +277 -0
  104. package/dist/object-store-leases.js.map +1 -0
  105. package/dist/object-store-roots.d.ts +25 -0
  106. package/dist/object-store-roots.d.ts.map +1 -0
  107. package/dist/object-store-roots.js +114 -0
  108. package/dist/object-store-roots.js.map +1 -0
  109. package/dist/object-store.d.ts +110 -0
  110. package/dist/object-store.d.ts.map +1 -0
  111. package/dist/object-store.js +404 -0
  112. package/dist/object-store.js.map +1 -0
  113. package/dist/object-transfer.d.ts +41 -0
  114. package/dist/object-transfer.d.ts.map +1 -0
  115. package/dist/object-transfer.js +267 -0
  116. package/dist/object-transfer.js.map +1 -0
  117. package/dist/plain-diff-capture.d.ts +1 -2
  118. package/dist/plain-diff-capture.d.ts.map +1 -1
  119. package/dist/plain-diff-capture.js +2 -7
  120. package/dist/plain-diff-capture.js.map +1 -1
  121. package/dist/plain-diff.d.ts +0 -4
  122. package/dist/plain-diff.d.ts.map +1 -1
  123. package/dist/plain-diff.js +2 -44
  124. package/dist/plain-diff.js.map +1 -1
  125. package/dist/raw-patch.d.ts.map +1 -1
  126. package/dist/raw-patch.js +5 -8
  127. package/dist/raw-patch.js.map +1 -1
  128. package/dist/run-expiry.d.ts +3 -0
  129. package/dist/run-expiry.d.ts.map +1 -0
  130. package/dist/run-expiry.js +15 -0
  131. package/dist/run-expiry.js.map +1 -0
  132. package/dist/thread-tree.d.ts +36 -2
  133. package/dist/thread-tree.d.ts.map +1 -1
  134. package/dist/thread-tree.js +87 -11
  135. package/dist/thread-tree.js.map +1 -1
  136. package/package.json +5 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-occupied.js","sourceRoot":"","sources":["../src/object-occupied.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { GitDeliveryPair, GitResultRefusal } from "@claudexor/schema";
2
+ import { type ComposeStats } from "./object-compose.js";
3
+ export type PairRevertResult = {
4
+ ok: true;
5
+ reverted: true;
6
+ tree: string;
7
+ changed: number;
8
+ stats: ComposeStats;
9
+ } | {
10
+ ok: false;
11
+ reverted: false;
12
+ refusal: GitResultRefusal;
13
+ treeMutated: boolean;
14
+ stats: ComposeStats | null;
15
+ /** A path the delivery changed was changed again since (an overlap, or an edit
16
+ * under the checkout): the revert cannot run on this tree. Every other refusal
17
+ * (the sparse patterns, a path it cannot read, a store or Git fault) can, once
18
+ * its cause is gone. */
19
+ diverged: boolean;
20
+ };
21
+ /** The paths two trees differ in (a delivery's T to M, a result's B to C): what an
22
+ * operation on them decides on, so what its snapshot reads by content. */
23
+ export declare function pairPaths(worktree: string, from: string, to: string, env?: Record<string, string>): Promise<string[]>;
24
+ /**
25
+ * Revert one object delivery on its actual pair (rev 12 B): with M the tree the
26
+ * delivery wrote, T the target it started from and S the tree the worktree holds
27
+ * now, `read-tree -m -i --aggressive M S T` keeps every later change outside
28
+ * the delivery, and the paths both moved get the reversed M->T records by
29
+ * today's apply rules (offsets allowed, overlap refused), all-or-nothing.
30
+ * Revert IS composition with roles (base M, target S, candidate T), so one owner
31
+ * holds the per-path semantics of both directions. S includes what the delivery
32
+ * added that S lacks on disk ({@link withDeliveredAdditions}). A pair path outside
33
+ * the sparse-checkout patterns refuses first: S cannot see what such a path holds.
34
+ */
35
+ export declare function revertDeliveryPair(input: {
36
+ worktree: string;
37
+ pair: Pick<GitDeliveryPair, "pre_tree" | "post_tree">;
38
+ /** Tree of the current worktree snapshot S (tracked and untracked state). */
39
+ currentTree: string;
40
+ /** Taking back a failed write: the paths whose content proof did not hold. */
41
+ unproven?: readonly string[];
42
+ }): Promise<PairRevertResult>;
43
+ /** The worktree's top level, the only directory materialization and composition address. */
44
+ export declare function worktreeTopLevel(repo: string): Promise<string>;
45
+ //# sourceMappingURL=object-revert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-revert.d.ts","sourceRoot":"","sources":["../src/object-revert.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAIL,KAAK,YAAY,EAElB,MAAM,qBAAqB,CAAC;AAM7B,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GAChF;IACE,EAAE,EAAE,KAAK,CAAC;IACV,QAAQ,EAAE,KAAK,CAAC;IAChB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B;;;4BAGwB;IACxB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAqHN;0EAC0E;AAC1E,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAUnB;AAwFD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,WAAW,CAAC,CAAC;IACtD,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsE5B;AAED,4FAA4F;AAC5F,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpE"}
@@ -0,0 +1,265 @@
1
+ import { createHash } from "node:crypto";
2
+ import { createReadStream, lstatSync, mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { WorkspaceError } from "@claudexor/core";
6
+ import { lstatPresent } from "./fs-presence.js";
7
+ import { composeOnTarget, parseRawRecords, pathspecBatches, } from "./object-compose.js";
8
+ import { materializeTree } from "./object-materialize.js";
9
+ import { sparseCheckoutRefusal } from "./object-sparse.js";
10
+ import { diskProgress, gitObserved } from "./git-observed.js";
11
+ import { SCRATCH_INDEX_CONFIG } from "./git-run.js";
12
+ /** `path` holds exactly what checkout writes for blob `oid`: the same filters render it. */
13
+ async function holdsCheckoutOf(worktree, path, oid) {
14
+ const file = join(worktree, path);
15
+ if (!lstatSync(file, { throwIfNoEntry: false })?.isFile())
16
+ return false;
17
+ const rendered = createHash("sha256");
18
+ await gitObserved(worktree, ["cat-file", "--filters", `--path=${path}`, oid], {
19
+ label: "cat-file --filters",
20
+ stdout: {
21
+ write: (chunk) => void rendered.update(chunk),
22
+ end: () => "",
23
+ },
24
+ });
25
+ const onDisk = createHash("sha256");
26
+ for await (const chunk of createReadStream(file))
27
+ onDisk.update(chunk);
28
+ return rendered.digest("hex") === onDisk.digest("hex");
29
+ }
30
+ /**
31
+ * The tree a failed write actually left. A path whose content proof failed can
32
+ * still hold exactly what checkout wrote (a filter that does not round-trip):
33
+ * such a path enters the revert's base as the snapshot saw it, so it reverts
34
+ * like any other. Every other path keeps M's entry, so a later edit of it (its
35
+ * bytes or its mode) stays an overlap the composition refuses.
36
+ */
37
+ async function asWrittenTree(worktree, postTree, currentTree, unproven) {
38
+ const wanted = new Set(unproven);
39
+ const records = parseRawRecords((await gitObserved(worktree, ["diff-tree", "-r", "--raw", "-z", "--no-renames", "--no-abbrev", postTree, currentTree], { label: "diff-tree --raw (as written)" })).stdout);
40
+ let info = "";
41
+ for (const record of records) {
42
+ if (!wanted.has(record.src) || record.status === "A" || record.status === "D")
43
+ continue;
44
+ if (record.newMode !== record.oldMode)
45
+ continue; // a chmod since the write is the user's
46
+ if (await holdsCheckoutOf(worktree, record.src, record.oldOid))
47
+ info += `${record.newMode} ${record.newOid}\t${record.src}\0`;
48
+ }
49
+ if (!info)
50
+ return postTree;
51
+ const scratch = mkdtempSync(join(tmpdir(), "claudexor-as-written-"));
52
+ try {
53
+ const env = { GIT_INDEX_FILE: join(scratch, "index"), GIT_OPTIONAL_LOCKS: "0" };
54
+ await gitObserved(worktree, [...SCRATCH_INDEX_CONFIG, "read-tree", postTree], {
55
+ env,
56
+ label: "read-tree (as written)",
57
+ });
58
+ await gitObserved(worktree, [...SCRATCH_INDEX_CONFIG, "update-index", "-z", "--index-info"], {
59
+ env,
60
+ label: "update-index --index-info (as written)",
61
+ input: info,
62
+ });
63
+ const tree = await gitObserved(worktree, [...SCRATCH_INDEX_CONFIG, "write-tree"], {
64
+ env,
65
+ label: "write-tree (as written)",
66
+ });
67
+ return tree.stdout.trim();
68
+ }
69
+ finally {
70
+ rmSync(scratch, { recursive: true, force: true });
71
+ }
72
+ }
73
+ /**
74
+ * Whether `path` is a file or symlink Git can reach: no parent is a symlink or a
75
+ * file. Only ENOENT and ENOTDIR are absence: a path the revert cannot look at (a
76
+ * parent it cannot search, an I/O error) is thrown, so the revert refuses with
77
+ * nothing written instead of calling the addition gone.
78
+ */
79
+ function reachableFile(worktree, path) {
80
+ try {
81
+ const parts = path.split("/");
82
+ for (let at = 1; at < parts.length; at += 1)
83
+ if (!lstatPresent(join(worktree, ...parts.slice(0, at)))?.isDirectory())
84
+ return false;
85
+ const stat = lstatPresent(join(worktree, path));
86
+ return stat !== undefined && !stat.isDirectory();
87
+ }
88
+ catch (error) {
89
+ throw new WorkspaceError(`the revert cannot tell whether ${path}, which the delivery added, is still as delivered: ${error instanceof Error ? error.message : String(error)}`);
90
+ }
91
+ }
92
+ /** The pair's own records: what the delivery changed, T to M. */
93
+ async function deliveredRecords(worktree, pair) {
94
+ return parseRawRecords((await gitObserved(worktree, [
95
+ "diff-tree",
96
+ "-r",
97
+ "--raw",
98
+ "-z",
99
+ "--no-renames",
100
+ "--no-abbrev",
101
+ pair.pre_tree,
102
+ pair.post_tree,
103
+ ], { label: "diff-tree --raw (delivered pair)" })).stdout);
104
+ }
105
+ /** The paths two trees differ in (a delivery's T to M, a result's B to C): what an
106
+ * operation on them decides on, so what its snapshot reads by content. */
107
+ export async function pairPaths(worktree, from, to, env = {}) {
108
+ return parseRawRecords((await gitObserved(worktree, ["diff-tree", "-r", "--raw", "-z", "--no-renames", "--no-abbrev", from, to], { env, label: "diff-tree --raw (pair paths)" })).stdout).map((record) => record.src);
109
+ }
110
+ /** Which of `paths` `tree` holds, read through the same literal pathspec batches. */
111
+ async function heldBy(worktree, tree, paths) {
112
+ const held = new Set();
113
+ for (const batch of pathspecBatches(paths)) {
114
+ const listed = await gitObserved(worktree, ["ls-tree", "-r", "-z", "--name-only", tree, "--", ...batch], { label: "ls-tree (delivered additions)" });
115
+ for (const path of listed.stdout.split("\0"))
116
+ if (path)
117
+ held.add(path);
118
+ }
119
+ return held;
120
+ }
121
+ /**
122
+ * S with what the delivery added that S lacks while it is on disk: what the target's
123
+ * ignore rules hide now (a name in `.git/info/exclude`, a rule written after the
124
+ * apply, an ignored empty directory a delivered file replaced), and a file inside a
125
+ * nested repository, which a snapshot leaves out. Such a path read as already gone
126
+ * and the revert answered reverted:true over it. Exactly those paths are taken in as
127
+ * they are, no others: a changed one is an overlap the composition refuses, an
128
+ * unchanged one is removed, and every other ignored file stays out of reach.
129
+ * `add -f` silently skips a path inside a nested repository (exit 0), so whatever
130
+ * the written tree lacks is staged by `update-index --add`, which has no such rule
131
+ * and, unlike `hash-object`, reads a symlink as a link; a path that still cannot
132
+ * be taken in refuses the revert, naming it, with nothing written.
133
+ */
134
+ async function withDeliveredAdditions(worktree, delivered, currentTree) {
135
+ const added = delivered
136
+ .filter((record) => record.oldMode === "000000" && record.newMode !== "160000")
137
+ .map((record) => record.src)
138
+ .filter((path) => reachableFile(worktree, path));
139
+ if (added.length === 0)
140
+ return { ok: true, tree: currentTree };
141
+ const inS = await heldBy(worktree, currentTree, added);
142
+ const hidden = added.filter((path) => !inS.has(path));
143
+ if (hidden.length === 0)
144
+ return { ok: true, tree: currentTree };
145
+ const scratch = mkdtempSync(join(tmpdir(), "claudexor-revert-snapshot-"));
146
+ try {
147
+ const env = { GIT_INDEX_FILE: join(scratch, "index"), GIT_OPTIONAL_LOCKS: "0" };
148
+ const progress = diskProgress(worktree);
149
+ const git = (args, label, extra = {}) => gitObserved(worktree, [...SCRATCH_INDEX_CONFIG, ...args], { env, label, progress, ...extra });
150
+ const writeTree = async () => (await git(["write-tree"], "write-tree (revert snapshot)")).stdout.trim();
151
+ await git(["read-tree", currentTree], "read-tree (revert snapshot)");
152
+ for (const batch of pathspecBatches(hidden))
153
+ await git(["add", "-f", "--", ...batch], "add -f (delivered additions)");
154
+ let tree = await writeTree();
155
+ const forced = await heldBy(worktree, tree, hidden);
156
+ const skipped = hidden.filter((path) => !forced.has(path));
157
+ if (skipped.length === 0)
158
+ return { ok: true, tree };
159
+ const staged = await git(["update-index", "--add", "-z", "--stdin"], "update-index --add (delivered additions)", { allowFailure: true, input: skipped.map((path) => `${path}\0`).join("") });
160
+ tree = await writeTree();
161
+ const held = await heldBy(worktree, tree, skipped);
162
+ const missing = skipped.filter((path) => !held.has(path)).sort();
163
+ if (missing.length === 0)
164
+ return { ok: true, tree };
165
+ return {
166
+ ok: false,
167
+ refusal: {
168
+ code: "revert_conflict",
169
+ message: `revert refused: what the delivery added at ${missing.length} path(s) could not be read into the revert's view of the target, so the revert cannot tell whether it is still as delivered; nothing was written: ${missing.slice(0, 20).join(", ")}${staged.stderr.trim() ? ` (${staged.stderr.trim()})` : ""}`.slice(0, 4_000),
170
+ paths: missing.slice(0, 200),
171
+ pathCount: missing.length,
172
+ },
173
+ };
174
+ }
175
+ finally {
176
+ rmSync(scratch, { recursive: true, force: true });
177
+ }
178
+ }
179
+ /**
180
+ * Revert one object delivery on its actual pair (rev 12 B): with M the tree the
181
+ * delivery wrote, T the target it started from and S the tree the worktree holds
182
+ * now, `read-tree -m -i --aggressive M S T` keeps every later change outside
183
+ * the delivery, and the paths both moved get the reversed M->T records by
184
+ * today's apply rules (offsets allowed, overlap refused), all-or-nothing.
185
+ * Revert IS composition with roles (base M, target S, candidate T), so one owner
186
+ * holds the per-path semantics of both directions. S includes what the delivery
187
+ * added that S lacks on disk ({@link withDeliveredAdditions}). A pair path outside
188
+ * the sparse-checkout patterns refuses first: S cannot see what such a path holds.
189
+ */
190
+ export async function revertDeliveryPair(input) {
191
+ const refused = (refusal) => ({
192
+ ok: false,
193
+ reverted: false,
194
+ treeMutated: false,
195
+ stats: null,
196
+ refusal,
197
+ diverged: false,
198
+ });
199
+ const delivered = await deliveredRecords(input.worktree, input.pair);
200
+ const outside = await sparseCheckoutRefusal(input.worktree, delivered.map((record) => record.src), "revert");
201
+ if (outside)
202
+ return refused(outside);
203
+ const additions = await withDeliveredAdditions(input.worktree, delivered, input.currentTree);
204
+ if (!additions.ok)
205
+ return refused(additions.refusal);
206
+ const current = additions.tree;
207
+ const composed = await composeOnTarget({
208
+ repo: input.worktree,
209
+ base: input.unproven?.length
210
+ ? await asWrittenTree(input.worktree, input.pair.post_tree, current, input.unproven)
211
+ : input.pair.post_tree,
212
+ target: current,
213
+ candidate: input.pair.pre_tree,
214
+ });
215
+ if (!composed.ok) {
216
+ // A name that cannot be addressed keeps its own code; anything else is a conflict.
217
+ const encoding = composed.refusal.code === "result_path_encoding";
218
+ return {
219
+ ok: false,
220
+ reverted: false,
221
+ treeMutated: false,
222
+ stats: composed.stats,
223
+ refusal: {
224
+ ...composed.refusal,
225
+ code: encoding ? "result_path_encoding" : "revert_conflict",
226
+ message: `revert refused: ${composed.refusal.message}`,
227
+ },
228
+ diverged: !encoding,
229
+ };
230
+ }
231
+ const written = await materializeTree({
232
+ worktree: input.worktree,
233
+ from: current,
234
+ to: composed.tree,
235
+ index: "temporary",
236
+ });
237
+ if (!written.ok) {
238
+ const changed = written.refusal.code === "delivery_target_changed";
239
+ return {
240
+ ok: false,
241
+ reverted: false,
242
+ treeMutated: written.treeMutated,
243
+ stats: composed.stats,
244
+ refusal: {
245
+ ...written.refusal,
246
+ code: changed ? "revert_target_changed" : written.refusal.code,
247
+ },
248
+ diverged: changed,
249
+ };
250
+ }
251
+ return {
252
+ ok: true,
253
+ reverted: true,
254
+ tree: composed.tree,
255
+ changed: written.changed,
256
+ stats: composed.stats,
257
+ };
258
+ }
259
+ /** The worktree's top level, the only directory materialization and composition address. */
260
+ export async function worktreeTopLevel(repo) {
261
+ return (await gitObserved(repo, ["rev-parse", "--show-toplevel"], {
262
+ label: "rev-parse --show-toplevel",
263
+ })).stdout.trim();
264
+ }
265
+ //# sourceMappingURL=object-revert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-revert.js","sourceRoot":"","sources":["../src/object-revert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EACL,eAAe,EACf,eAAe,EACf,eAAe,GAGhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAiBpD,4FAA4F;AAC5F,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAY,EAAE,GAAW;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE;QAAE,OAAO,KAAK,CAAC;IACxE,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE;QAC5E,KAAK,EAAE,oBAAoB;QAC3B,MAAM,EAAE;YACN,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;YAC7C,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE;SACd;KACF,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC;QAAE,MAAM,CAAC,MAAM,CAAC,KAAe,CAAC,CAAC;IACjF,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,aAAa,CAC1B,QAAgB,EAChB,QAAgB,EAChB,WAAmB,EACnB,QAA2B;IAE3B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,eAAe,CAC7B,CACE,MAAM,WAAW,CACf,QAAQ,EACR,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,EACxF,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAC1C,CACF,CAAC,MAAM,CACT,CAAC;IACF,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG;YAAE,SAAS;QACxF,IAAI,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO;YAAE,SAAS,CAAC,wCAAwC;QACzF,IAAI,MAAM,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC;YAC5D,IAAI,IAAI,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAC;IAC3B,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC;QAChF,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG,oBAAoB,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE;YAC5E,GAAG;YACH,KAAK,EAAE,wBAAwB;SAChC,CAAC,CAAC;QACH,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG,oBAAoB,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE;YAC3F,GAAG;YACH,KAAK,EAAE,wCAAwC;YAC/C,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG,oBAAoB,EAAE,YAAY,CAAC,EAAE;YAChF,GAAG;YACH,KAAK,EAAE,yBAAyB;SACjC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAC,QAAgB,EAAE,IAAY;IACnD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE;gBAAE,OAAO,KAAK,CAAC;QACxF,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAChD,OAAO,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,cAAc,CACtB,kCAAkC,IAAI,sDAAsD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACrJ,CAAC;IACJ,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,KAAK,UAAU,gBAAgB,CAC7B,QAAgB,EAChB,IAAqD;IAErD,OAAO,eAAe,CACpB,CACE,MAAM,WAAW,CACf,QAAQ,EACR;QACE,WAAW;QACX,IAAI;QACJ,OAAO;QACP,IAAI;QACJ,cAAc;QACd,aAAa;QACb,IAAI,CAAC,QAAQ;QACb,IAAI,CAAC,SAAS;KACf,EACD,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAC9C,CACF,CAAC,MAAM,CACT,CAAC;AACJ,CAAC;AAED;0EAC0E;AAC1E,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,IAAY,EACZ,EAAU,EACV,GAAG,GAA2B,EAAE;IAEhC,OAAO,eAAe,CACpB,CACE,MAAM,WAAW,CACf,QAAQ,EACR,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,EAC3E,EAAE,GAAG,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAC/C,CACF,CAAC,MAAM,CACT,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,qFAAqF;AACrF,KAAK,UAAU,MAAM,CAAC,QAAgB,EAAE,IAAY,EAAE,KAAwB;IAC5E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,QAAQ,EACR,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,EAC5D,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAC3C,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,IAAI,IAAI;gBAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,UAAU,sBAAsB,CACnC,QAAgB,EAChB,SAA+B,EAC/B,WAAmB;IAEnB,MAAM,KAAK,GAAG,SAAS;SACpB,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC;SAC9E,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;SAC3B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAC/D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAChE,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAAC,CAAC;IAC1E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC;QAChF,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,CACV,IAAc,EACd,KAAa,EACb,KAAK,GAA+C,EAAE,EACtD,EAAE,CACF,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG,oBAAoB,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QAChG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE,CAC3B,CAAC,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,8BAA8B,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5E,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,6BAA6B,CAAC,CAAC;QACrE,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,MAAM,CAAC;YACzC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,8BAA8B,CAAC,CAAC;QAC3E,IAAI,IAAI,GAAG,MAAM,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,GAAG,CACtB,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,EAC1C,0CAA0C,EAC1C,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAC3E,CAAC;QACF,IAAI,GAAG,MAAM,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACjE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACpD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE;gBACP,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EACL,8CAA8C,OAAO,CAAC,MAAM,qJAAqJ,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CACjT,CAAC,EACD,KAAK,CACN;gBACH,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBAC5B,SAAS,EAAE,OAAO,CAAC,MAAM;aAC1B;SACF,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAOxC;IACC,MAAM,OAAO,GAAG,CAAC,OAAyB,EAAoB,EAAE,CAAC,CAAC;QAChE,EAAE,EAAE,KAAK;QACT,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,KAAK;QAClB,KAAK,EAAE,IAAI;QACX,OAAO;QACP,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,MAAM,qBAAqB,CACzC,KAAK,CAAC,QAAQ,EACd,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EACrC,QAAQ,CACT,CAAC;IACF,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC7F,IAAI,CAAC,SAAS,CAAC,EAAE;QAAE,OAAO,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC;IAC/B,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC;QACrC,IAAI,EAAE,KAAK,CAAC,QAAQ;QACpB,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM;YAC1B,CAAC,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC;YACpF,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS;QACxB,MAAM,EAAE,OAAO;QACf,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;KAC/B,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,mFAAmF;QACnF,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,sBAAsB,CAAC;QAClE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,OAAO,EAAE;gBACP,GAAG,QAAQ,CAAC,OAAO;gBACnB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,iBAAiB;gBAC3D,OAAO,EAAE,mBAAmB,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE;aACvD;YACD,QAAQ,EAAE,CAAC,QAAQ;SACpB,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC;QACpC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,QAAQ,CAAC,IAAI;QACjB,KAAK,EAAE,WAAW;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,yBAAyB,CAAC;QACnE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,OAAO,EAAE;gBACP,GAAG,OAAO,CAAC,OAAO;gBAClB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI;aAC/D;YACD,QAAQ,EAAE,OAAO;SAClB,CAAC;IACJ,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,OAAO,CACL,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE;QACxD,KAAK,EAAE,2BAA2B;KACnC,CAAC,CACH,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import type { GitObjectResult } from "@claudexor/schema";
2
+ /** A path the result holds whose content the copy does not hold, and why. */
3
+ export interface UnavailableSavedFile {
4
+ path: string;
5
+ /** The copy's typed fault: `space_insufficient` for a full disk, `git_stalled`,
6
+ * `git_signal`, or `git_failed` for any other Git fault. */
7
+ reason: string;
8
+ }
9
+ /**
10
+ * A copy holds every file the result holds, or, when it fails, none of them: then
11
+ * `written` is empty and `unavailable` names each one. What the failed copy wrote or
12
+ * found in `into` and could not remove may still be there (a partial file, an earlier
13
+ * leftover); it is never the result's content, so no reader of a failed copy reads it.
14
+ */
15
+ export interface SavedFiles {
16
+ /** Paths the result holds (not those it deleted), written whole under `into`. */
17
+ written: string[];
18
+ /** Paths the result holds that the copy does not hold, each with the copy's fault. */
19
+ unavailable: UnavailableSavedFile[];
20
+ }
21
+ /**
22
+ * Copy the files a saved result changed out of its candidate tree into `into`: what
23
+ * review and synthesis read of a result with no patch view, so they read the bytes
24
+ * apply consumes, not whatever the workspace holds by then (a configured gate may
25
+ * have rewritten an output since the capture). Checkout conversion applies as the
26
+ * result itself defines it and nothing else: the attributes its candidate tree holds
27
+ * (`--attr-source`) with Git's built-in defaults, in a private Git directory
28
+ * ({@link privateCopyContext}), so neither the workspace's `.gitattributes`, its
29
+ * `.git/info/attributes` or `.git/config`, nor the user's global or system
30
+ * configuration and attributes reach the copy, whenever they changed. A filter driver
31
+ * is configuration, which the result does not carry: a file whose attributes name
32
+ * one is copied as its stored blob, as the rendered patch view shows it. Big blobs
33
+ * stream. The store is mounted under a pending lease. A read that fails, a copy that
34
+ * cannot fit (it is not started) and a disk that fills on the way, the copy's own
35
+ * scratch included, are one answer: a failed copy (see {@link SavedFiles}), every file
36
+ * unavailable with that cause, never a thrown run, even when the copy directory then
37
+ * cannot be emptied.
38
+ */
39
+ export declare function materializeSavedFiles(input: {
40
+ /** A worktree whose Git reads the result's objects (its capture's own). */
41
+ repo: string;
42
+ /** Project root owning the object store. */
43
+ projectRoot: string;
44
+ result: GitObjectResult;
45
+ /** Every path it changed, as recorded at its capture: what stays unavailable when
46
+ * not even its tree can be read. */
47
+ changedPaths: readonly string[];
48
+ into: string;
49
+ }): Promise<SavedFiles>;
50
+ //# sourceMappingURL=object-saved-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-saved-files.d.ts","sourceRoot":"","sources":["../src/object-saved-files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAc1E,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb;gEAC4D;IAC5D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AAiFD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,CAAC;IACxB;wCACoC;IACpC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,UAAU,CAAC,CAiGtB"}
@@ -0,0 +1,176 @@
1
+ import { existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { delimiter, join } from "node:path";
4
+ import { diskProgress, gitObserved, GitOperationError } from "./git-observed.js";
5
+ import { SCRATCH_INDEX_CONFIG } from "./git-run.js";
6
+ import { parseRawRecords } from "./object-compose.js";
7
+ import { gitFaultRefusalCode } from "./object-materialize.js";
8
+ import { assertSpaceFor } from "./object-transfer.js";
9
+ import { beginPendingRoots, endPendingRoots, objectStorePath, repositoryEndpoint, } from "./object-store.js";
10
+ /** Nothing outside the result decides a copy's bytes: no system or global configuration
11
+ * or attributes file, and no configuration a caller's environment injects. */
12
+ const SAVED_COPY_ENV = {
13
+ GIT_CONFIG_NOSYSTEM: "1",
14
+ GIT_CONFIG_GLOBAL: "/dev/null",
15
+ GIT_ATTR_NOSYSTEM: "1",
16
+ GIT_CONFIG_PARAMETERS: null,
17
+ GIT_CONFIG_COUNT: null,
18
+ GIT_ATTR_SOURCE: null,
19
+ GIT_DIR: null,
20
+ GIT_COMMON_DIR: null,
21
+ GIT_WORK_TREE: null,
22
+ GIT_OBJECT_DIRECTORY: null,
23
+ GIT_INDEX_FILE: null,
24
+ };
25
+ /** The user's attributes file (`core.attributesFile`, else Git's XDG default) is no source. */
26
+ const NO_GLOBAL_ATTRIBUTES = ["-c", "core.attributesFile=/dev/null"];
27
+ /**
28
+ * The Git context a copy runs in: a private Git directory under `scratch` with no
29
+ * configuration but what `init` writes for this filesystem and no `info/attributes`,
30
+ * reading the capture's objects (and the store's, while leased) as alternates. The
31
+ * capture's own repository is read for the place of its objects only: its
32
+ * configuration and `info/attributes` change after the capture as a gate pleases.
33
+ */
34
+ async function privateCopyContext(repo, scratch, objectFormat, storeObjects) {
35
+ const gitDir = join(scratch, "git");
36
+ await gitObserved(scratch, ["init", "--bare", "--quiet", "--template=", `--object-format=${objectFormat}`, gitDir], { env: SAVED_COPY_ENV, label: "init (saved files)" });
37
+ const { objectsDir } = await repositoryEndpoint(repo);
38
+ return {
39
+ ...SAVED_COPY_ENV,
40
+ GIT_DIR: gitDir,
41
+ GIT_INDEX_FILE: join(scratch, "index"),
42
+ GIT_OPTIONAL_LOCKS: "0",
43
+ GIT_ALTERNATE_OBJECT_DIRECTORIES: [objectsDir, ...(storeObjects ? [storeObjects] : [])]
44
+ .map((path) => JSON.stringify(path))
45
+ .join(delimiter),
46
+ };
47
+ }
48
+ /**
49
+ * Empty `dir` where it is, one entry at a time. The typed fault that ended the copy is
50
+ * the answer, so a fault here (a disk that fails again, a busy file) never replaces
51
+ * it. A directory that cannot be listed is removed whole instead. What still stays is
52
+ * the failed copy's leftover, no file of the result: its readers never read a failed
53
+ * copy, and its owner removes the directory again when done (see `SavedFiles`).
54
+ */
55
+ function emptyCopy(dir) {
56
+ if (!existsSync(dir))
57
+ return;
58
+ let entries;
59
+ try {
60
+ entries = readdirSync(dir);
61
+ }
62
+ catch {
63
+ try {
64
+ rmSync(dir, { recursive: true, force: true });
65
+ }
66
+ catch {
67
+ /* unlistable and unremovable: left for its owner */
68
+ }
69
+ return;
70
+ }
71
+ for (const entry of entries) {
72
+ try {
73
+ rmSync(join(dir, entry), { recursive: true, force: true });
74
+ }
75
+ catch {
76
+ /* left for its owner */
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Copy the files a saved result changed out of its candidate tree into `into`: what
82
+ * review and synthesis read of a result with no patch view, so they read the bytes
83
+ * apply consumes, not whatever the workspace holds by then (a configured gate may
84
+ * have rewritten an output since the capture). Checkout conversion applies as the
85
+ * result itself defines it and nothing else: the attributes its candidate tree holds
86
+ * (`--attr-source`) with Git's built-in defaults, in a private Git directory
87
+ * ({@link privateCopyContext}), so neither the workspace's `.gitattributes`, its
88
+ * `.git/info/attributes` or `.git/config`, nor the user's global or system
89
+ * configuration and attributes reach the copy, whenever they changed. A filter driver
90
+ * is configuration, which the result does not carry: a file whose attributes name
91
+ * one is copied as its stored blob, as the rendered patch view shows it. Big blobs
92
+ * stream. The store is mounted under a pending lease. A read that fails, a copy that
93
+ * cannot fit (it is not started) and a disk that fills on the way, the copy's own
94
+ * scratch included, are one answer: a failed copy (see {@link SavedFiles}), every file
95
+ * unavailable with that cause, never a thrown run, even when the copy directory then
96
+ * cannot be emptied.
97
+ */
98
+ export async function materializeSavedFiles(input) {
99
+ const store = objectStorePath(input.projectRoot);
100
+ let scratch = null;
101
+ let lease = null;
102
+ let written = null;
103
+ try {
104
+ scratch = mkdtempSync(join(tmpdir(), "claudexor-saved-files-"));
105
+ // A copy starts empty: a checkout never overwrites, and an old file is no content.
106
+ rmSync(input.into, { recursive: true, force: true });
107
+ mkdirSync(input.into, { recursive: true, mode: 0o700 });
108
+ if (existsSync(join(store, "objects")))
109
+ lease = await beginPendingRoots(store, []);
110
+ const env = await privateCopyContext(input.repo, scratch, input.result.object_format, lease ? join(store, "objects") : null);
111
+ const records = parseRawRecords((await gitObserved(scratch, [
112
+ "diff-tree",
113
+ "-r",
114
+ "--raw",
115
+ "-z",
116
+ "--no-renames",
117
+ "--no-abbrev",
118
+ input.result.base_tree,
119
+ input.result.candidate_tree,
120
+ ], { env, label: "diff-tree --raw (saved files)" })).stdout).filter((record) => !/^0+$/.test(record.newMode));
121
+ written = records.map((record) => record.src);
122
+ if (written.length === 0)
123
+ return { written, unavailable: [] };
124
+ const sizes = await gitObserved(scratch, ["cat-file", "--batch-check=%(objectsize)"], {
125
+ env,
126
+ label: "cat-file --batch-check (saved files)",
127
+ input: `${records.map((record) => record.newOid).join("\n")}\n`,
128
+ });
129
+ assertSpaceFor(input.into, sizes.stdout
130
+ .split("\n")
131
+ .reduce((sum, line) => sum + (/^\d+$/.test(line) ? Number(line) : 0), 0), "the saved-file copy");
132
+ await gitObserved(scratch, [...SCRATCH_INDEX_CONFIG, "read-tree", input.result.candidate_tree], { env, label: "read-tree (saved files)" });
133
+ // Attributes come from the saved tree alone (`--attr-source`), in the private
134
+ // context: whatever the workspace's Git holds since the capture is no source.
135
+ await gitObserved(input.into, [
136
+ `--work-tree=${input.into}`,
137
+ `--attr-source=${input.result.candidate_tree}`,
138
+ ...NO_GLOBAL_ATTRIBUTES,
139
+ ...SCRATCH_INDEX_CONFIG,
140
+ "checkout-index",
141
+ "-z",
142
+ "--stdin",
143
+ ], {
144
+ env,
145
+ label: "checkout-index (saved files)",
146
+ input: `${written.join("\0")}\0`,
147
+ progress: diskProgress(input.into),
148
+ });
149
+ return { written, unavailable: [] };
150
+ }
151
+ catch (error) {
152
+ const errno = error?.code;
153
+ if (!(error instanceof GitOperationError) && errno !== "ENOSPC" && errno !== "EDQUOT")
154
+ throw error;
155
+ const reason = error instanceof GitOperationError ? gitFaultRefusalCode(error.code) : "space_insufficient";
156
+ // Any of them may be partial: none is offered as the result's content, whatever
157
+ // emptying the copy where it is (a full disk may not give a new directory) leaves.
158
+ emptyCopy(input.into);
159
+ return {
160
+ written: [],
161
+ unavailable: (written ?? [...input.changedPaths]).map((path) => ({ path, reason })),
162
+ };
163
+ }
164
+ finally {
165
+ endPendingRoots(lease);
166
+ // Best effort: a scratch that cannot be removed never replaces the answer.
167
+ try {
168
+ if (scratch)
169
+ rmSync(scratch, { recursive: true, force: true });
170
+ }
171
+ catch {
172
+ /* left in the OS temp dir */
173
+ }
174
+ }
175
+ }
176
+ //# sourceMappingURL=object-saved-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-saved-files.js","sourceRoot":"","sources":["../src/object-saved-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { GitResultRefusal } from "@claudexor/schema";
2
+ /**
3
+ * The paths among `paths` that the worktree's sparse-checkout patterns leave out
4
+ * (none when it is not a sparse checkout), from one `check-rules` call, or null when
5
+ * this Git cannot evaluate the patterns (older than 2.41). A snapshot's `add -A`
6
+ * skips such a path, a tracked one keeping HEAD's blob whether its file is absent,
7
+ * as a sparse checkout usually leaves it, or present, so an operation that addresses
8
+ * one could not tell what it holds before or after writing. With
9
+ * `core.sparseCheckout` set but no patterns file, Git checks out everything, and so
10
+ * nothing is left out here either. A worktree that is not sparse costs one
11
+ * `git config` and never asks `check-rules`.
12
+ */
13
+ export declare function outsideSparseCheckout(worktree: string, paths: readonly string[], env: Record<string, string>): Promise<string[] | null>;
14
+ /**
15
+ * The refusal of an operation that must write or remove a path outside the
16
+ * sparse-checkout patterns, naming those paths, or of any operation in a sparse
17
+ * checkout whose Git cannot evaluate its patterns; nothing is written. Widening the
18
+ * sparse checkout (`git sparse-checkout add`) lets the same operation run. Paths it
19
+ * does not address keep their files: the checkout runs with the patterns off.
20
+ */
21
+ export declare function sparseCheckoutRefusal(worktree: string, paths: readonly string[], operation: "delivery" | "revert", env?: Record<string, string>): Promise<GitResultRefusal | null>;
22
+ //# sourceMappingURL=object-sparse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-sparse.d.ts","sourceRoot":"","sources":["../src/object-sparse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAQ1D;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CA4B1B;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,UAAU,GAAG,QAAQ,EAChC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC/B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA4BlC"}