@astrosheep/keiyaku 4.0.0 → 4.0.2
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/README.md +133 -8
- package/build/integrations/marketplace/plugins/keiyaku/.claude-plugin/plugin.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/.codex-plugin/plugin.json +4 -4
- package/build/integrations/marketplace/plugins/keiyaku/opencode.js +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/package.json +2 -2
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +13 -5
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +91 -32
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/SKILL.md +134 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-bind/agents/openai.yaml +4 -0
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-task/SKILL.md +41 -6
- package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +262 -46
- package/build/src/akuma/abort.d.ts +2 -0
- package/build/src/akuma/abort.js +50 -0
- package/build/src/akuma/akuma.d.ts +50 -33
- package/build/src/akuma/akuma.js +175 -127
- package/build/src/akuma/archetype.d.ts +14 -5
- package/build/src/akuma/archetype.js +85 -39
- package/build/src/akuma/body.d.ts +3 -5
- package/build/src/akuma/body.js +490 -183
- package/build/src/akuma/coordinate.d.ts +9 -0
- package/build/src/akuma/coordinate.js +22 -0
- package/build/src/akuma/heart/facts.d.ts +88 -45
- package/build/src/akuma/heart/facts.js +19 -8
- package/build/src/akuma/heart/index.d.ts +64 -55
- package/build/src/akuma/heart/index.js +172 -252
- package/build/src/akuma/heart/rows.d.ts +38 -83
- package/build/src/akuma/heart/rows.js +117 -155
- package/build/src/akuma/heart/schema.d.ts +1 -1
- package/build/src/akuma/heart/schema.js +61 -22
- package/build/src/akuma/heart/soul.d.ts +8 -0
- package/build/src/akuma/heart/soul.js +136 -0
- package/build/src/akuma/heart/storage.d.ts +47 -0
- package/build/src/akuma/heart/storage.js +224 -0
- package/build/src/akuma/heart/tells.d.ts +12 -0
- package/build/src/akuma/heart/tells.js +79 -0
- package/build/src/akuma/heart/timeline.d.ts +15 -0
- package/build/src/akuma/heart/timeline.js +86 -0
- package/build/src/akuma/identity.d.ts +2 -2
- package/build/src/akuma/identity.js +9 -9
- package/build/src/akuma/index.d.ts +10 -3
- package/build/src/akuma/index.js +7 -1
- package/build/src/akuma/projection.d.ts +176 -0
- package/build/src/akuma/projection.js +256 -0
- package/build/src/akuma/provider-recipe.d.ts +24 -0
- package/build/src/akuma/provider-recipe.js +100 -0
- package/build/src/akuma/provider.d.ts +67 -13
- package/build/src/akuma/provider.js +172 -105
- package/build/src/akuma/providers/acp/core.d.ts +19 -0
- package/build/src/akuma/providers/acp/core.js +159 -0
- package/build/src/akuma/providers/acp/events.d.ts +20 -0
- package/build/src/akuma/providers/acp/events.js +73 -0
- package/build/src/akuma/providers/acp/index.d.ts +12 -0
- package/build/src/akuma/providers/acp/index.js +94 -0
- package/build/src/akuma/providers/{claude.d.ts → claude/events.d.ts} +9 -41
- package/build/src/akuma/providers/claude/events.js +238 -0
- package/build/src/akuma/providers/claude/index.d.ts +47 -0
- package/build/src/akuma/providers/claude/index.js +279 -0
- package/build/src/akuma/providers/claude/input.d.ts +13 -0
- package/build/src/akuma/providers/claude/input.js +109 -0
- package/build/src/akuma/providers/codex-app-server/events.d.ts +1 -1
- package/build/src/akuma/providers/codex-app-server/events.js +15 -12
- package/build/src/akuma/providers/codex-app-server/index.d.ts +15 -13
- package/build/src/akuma/providers/codex-app-server/index.js +77 -33
- package/build/src/akuma/providers/grok-build/index.d.ts +4 -0
- package/build/src/akuma/providers/grok-build/index.js +70 -0
- package/build/src/akuma/providers/index.d.ts +5 -3
- package/build/src/akuma/providers/index.js +35 -56
- package/build/src/akuma/providers/opencode-sdk/events.d.ts +54 -0
- package/build/src/akuma/providers/opencode-sdk/events.js +235 -0
- package/build/src/akuma/providers/opencode-sdk/index.d.ts +33 -0
- package/build/src/akuma/providers/opencode-sdk/index.js +308 -0
- package/build/src/akuma/providers/opencode-sdk/session.d.ts +26 -0
- package/build/src/akuma/providers/opencode-sdk/session.js +63 -0
- package/build/src/akuma/providers/pi/events.d.ts +33 -0
- package/build/src/akuma/providers/pi/events.js +166 -0
- package/build/src/akuma/providers/pi/index.d.ts +11 -0
- package/build/src/akuma/providers/pi/index.js +191 -0
- package/build/src/akuma/publication.d.ts +3 -3
- package/build/src/akuma/publication.js +28 -40
- package/build/src/akuma/requests.d.ts +9 -6
- package/build/src/akuma/requests.js +95 -65
- package/build/src/alias/index.d.ts +4 -3
- package/build/src/alias/index.js +12 -13
- package/build/src/body/decode.js +7 -1
- package/build/src/body/region.d.ts +2 -0
- package/build/src/body/region.js +77 -7
- package/build/src/body/render.js +2 -1
- package/build/src/body/shape.js +7 -1
- package/build/src/body/verification.js +19 -4
- package/build/src/cli/accepted.d.ts +18 -12
- package/build/src/cli/accepted.js +73 -34
- package/build/src/cli/actor.js +3 -3
- package/build/src/cli/commands/akuma-invoke.d.ts +44 -19
- package/build/src/cli/commands/akuma-invoke.js +101 -52
- package/build/src/cli/commands/akuma.d.ts +27 -9
- package/build/src/cli/commands/akuma.js +151 -80
- package/build/src/cli/commands/contract.d.ts +155 -0
- package/build/src/cli/commands/contract.js +20 -0
- package/build/src/cli/commands/install.js +2 -0
- package/build/src/cli/commands/task-invoke.d.ts +19 -4
- package/build/src/cli/commands/task-invoke.js +65 -17
- package/build/src/cli/commands/task-query.d.ts +5 -0
- package/build/src/cli/commands/task-query.js +247 -0
- package/build/src/cli/commands/task.d.ts +3 -1
- package/build/src/cli/commands/task.js +52 -14
- package/build/src/cli/coordinates.d.ts +18 -0
- package/build/src/cli/coordinates.js +120 -0
- package/build/src/cli/draft.d.ts +8 -0
- package/build/src/cli/draft.js +96 -0
- package/build/src/cli/invoke.d.ts +9 -3
- package/build/src/cli/invoke.js +287 -108
- package/build/src/cli/main.js +54 -7
- package/build/src/cli/parse.d.ts +21 -117
- package/build/src/cli/parse.js +79 -84
- package/build/src/cli/render/akuma-tool-command.d.ts +6 -0
- package/build/src/cli/render/akuma-tool-command.js +144 -0
- package/build/src/cli/render/akuma-tool.d.ts +4 -2
- package/build/src/cli/render/akuma-tool.js +35 -5
- package/build/src/cli/render/akuma.d.ts +3 -1
- package/build/src/cli/render/akuma.js +247 -212
- package/build/src/cli/render/audit.d.ts +3 -0
- package/build/src/cli/render/audit.js +104 -0
- package/build/src/cli/render/catalog.d.ts +2 -0
- package/build/src/cli/render/catalog.js +16 -0
- package/build/src/cli/render/contract.d.ts +3 -3
- package/build/src/cli/render/contract.js +200 -54
- package/build/src/cli/render/kanshi.js +272 -129
- package/build/src/cli/render/receipt.d.ts +19 -0
- package/build/src/cli/render/receipt.js +106 -0
- package/build/src/cli/render/refusal.d.ts +16 -2
- package/build/src/cli/render/refusal.js +88 -3
- package/build/src/cli/render/region.d.ts +2 -0
- package/build/src/cli/render/region.js +17 -0
- package/build/src/cli/render/task.d.ts +2 -1
- package/build/src/cli/render/task.js +223 -60
- package/build/src/cli/render/terminal.d.ts +20 -0
- package/build/src/cli/render/terminal.js +121 -0
- package/build/src/cli/render/text.js +11 -3
- package/build/src/cli/result.d.ts +126 -19
- package/build/src/cli/usage.d.ts +1 -0
- package/build/src/cli/usage.js +3 -0
- package/build/src/contract-worktree.d.ts +44 -0
- package/build/src/contract-worktree.js +251 -0
- package/build/src/coordination/durable-file.d.ts +5 -1
- package/build/src/coordination/durable-file.js +57 -10
- package/build/src/coordination/sqlite-transaction-lock.d.ts +4 -0
- package/build/src/coordination/sqlite-transaction-lock.js +22 -5
- package/build/src/core/facts/codec.js +23 -4
- package/build/src/core/facts/eligibility.d.ts +1 -10
- package/build/src/core/facts/eligibility.js +0 -49
- package/build/src/core/facts/fold.js +1 -6
- package/build/src/core/facts/gate.d.ts +1 -0
- package/build/src/core/facts/gate.js +1 -0
- package/build/src/core/facts/observation.d.ts +3 -0
- package/build/src/core/facts/observation.js +12 -0
- package/build/src/core/facts/types.d.ts +10 -3
- package/build/src/core/subject.js +2 -2
- package/build/src/core/verbs/amend.d.ts +1 -1
- package/build/src/core/verbs/amend.js +3 -18
- package/build/src/core/verbs/bind.js +2 -16
- package/build/src/core/verbs/deliver.d.ts +1 -1
- package/build/src/core/verbs/deliver.js +14 -4
- package/build/src/core/verbs/placement.d.ts +1 -1
- package/build/src/core/verbs/placement.js +7 -9
- package/build/src/dispatch/index.d.ts +5 -3
- package/build/src/dispatch/index.js +30 -21
- package/build/src/duration.d.ts +10 -0
- package/build/src/duration.js +22 -0
- package/build/src/git/admission.d.ts +2 -2
- package/build/src/git/admission.js +33 -23
- package/build/src/git/hooks.d.ts +15 -0
- package/build/src/git/hooks.js +70 -18
- package/build/src/git/identity.d.ts +5 -1
- package/build/src/git/identity.js +23 -4
- package/build/src/git/integration.d.ts +48 -0
- package/build/src/git/integration.js +250 -0
- package/build/src/git/observe.d.ts +29 -15
- package/build/src/git/observe.js +185 -76
- package/build/src/git/read-observation.d.ts +41 -0
- package/build/src/git/read-observation.js +361 -0
- package/build/src/git/reconcile.d.ts +17 -5
- package/build/src/git/reconcile.js +305 -109
- package/build/src/git/repository.d.ts +41 -18
- package/build/src/git/repository.js +220 -114
- package/build/src/git/scratch.d.ts +17 -0
- package/build/src/git/scratch.js +73 -0
- package/build/src/git/target-placement.d.ts +92 -0
- package/build/src/git/target-placement.js +375 -0
- package/build/src/git/tender.d.ts +49 -0
- package/build/src/git/tender.js +63 -0
- package/build/src/git/terminal-seal.d.ts +24 -0
- package/build/src/git/terminal-seal.js +89 -0
- package/build/src/git/tree.d.ts +2 -2
- package/build/src/git/tree.js +4 -0
- package/build/src/git/workspace.d.ts +53 -0
- package/build/src/git/workspace.js +139 -0
- package/build/src/identity/selector.d.ts +6 -0
- package/build/src/identity/selector.js +19 -0
- package/build/src/index.d.ts +4 -2
- package/build/src/index.js +2 -1
- package/build/src/kanshi/index.d.ts +2 -2
- package/build/src/kanshi/index.js +1 -1
- package/build/src/kanshi/read.d.ts +7 -3
- package/build/src/kanshi/read.js +245 -45
- package/build/src/kanshi/report.d.ts +81 -6
- package/build/src/kanshi/select.d.ts +5 -0
- package/build/src/kanshi/select.js +33 -1
- package/build/src/library/address.d.ts +57 -0
- package/build/src/library/address.js +165 -0
- package/build/src/library/akuma-creation.d.ts +16 -7
- package/build/src/library/akuma-creation.js +96 -22
- package/build/src/library/audit.d.ts +18 -0
- package/build/src/library/audit.js +44 -0
- package/build/src/library/bind.d.ts +21 -0
- package/build/src/library/bind.js +56 -0
- package/build/src/library/catalog.d.ts +58 -0
- package/build/src/library/catalog.js +69 -0
- package/build/src/library/configuration.d.ts +6 -15
- package/build/src/library/configuration.js +14 -17
- package/build/src/library/contract.d.ts +23 -49
- package/build/src/library/contract.js +171 -185
- package/build/src/library/delivery.d.ts +24 -0
- package/build/src/library/delivery.js +21 -0
- package/build/src/library/fleet.d.ts +65 -0
- package/build/src/library/fleet.js +153 -0
- package/build/src/library/input.d.ts +3 -0
- package/build/src/library/input.js +19 -0
- package/build/src/library/keiyaku.d.ts +18 -3
- package/build/src/library/keiyaku.js +12 -1
- package/build/src/library/mutation.d.ts +39 -0
- package/build/src/library/mutation.js +37 -0
- package/build/src/library/reconcile.d.ts +29 -0
- package/build/src/library/reconcile.js +179 -0
- package/build/src/library/refusal.d.ts +21 -0
- package/build/src/library/refusal.js +29 -0
- package/build/src/library/region.d.ts +14 -1
- package/build/src/library/region.js +18 -4
- package/build/src/library/repo.d.ts +4 -13
- package/build/src/library/repo.js +14 -24
- package/build/src/protocol/attempt.d.ts +16 -3
- package/build/src/protocol/attempt.js +41 -10
- package/build/src/protocol/bind.d.ts +9 -2
- package/build/src/protocol/bind.js +48 -40
- package/build/src/protocol/intent.d.ts +57 -20
- package/build/src/protocol/intent.js +55 -79
- package/build/src/protocol/operations.d.ts +152 -43
- package/build/src/protocol/operations.js +482 -166
- package/build/src/protocol/outcome.d.ts +14 -3
- package/build/src/protocol/outcome.js +11 -3
- package/build/src/protocol/placement.d.ts +41 -0
- package/build/src/protocol/placement.js +147 -0
- package/build/src/protocol/read/documents.d.ts +2 -2
- package/build/src/protocol/read/documents.js +4 -4
- package/build/src/protocol/read/status.d.ts +18 -5
- package/build/src/protocol/read/status.js +73 -13
- package/build/src/protocol/run.d.ts +49 -7
- package/build/src/protocol/run.js +53 -25
- package/build/src/runtime/proc/line-rpc.d.ts +4 -8
- package/build/src/runtime/proc/line-rpc.js +22 -28
- package/build/src/runtime/proc/run.d.ts +23 -21
- package/build/src/runtime/proc/run.js +123 -89
- package/build/src/runtime/proc/stdio.d.ts +18 -0
- package/build/src/runtime/proc/stdio.js +58 -0
- package/build/src/settings.d.ts +7 -1
- package/build/src/settings.js +32 -17
- package/build/src/settlement/fence.d.ts +5 -0
- package/build/src/settlement/fence.js +14 -0
- package/build/src/settlement/holder.d.ts +35 -4
- package/build/src/settlement/holder.js +127 -28
- package/build/src/settlement/settle.d.ts +9 -1
- package/build/src/settlement/settle.js +74 -37
- package/build/src/task/board.d.ts +23 -5
- package/build/src/task/board.js +17 -10
- package/build/src/task/compose.d.ts +2 -2
- package/build/src/task/compose.js +18 -10
- package/build/src/task/context.d.ts +3 -3
- package/build/src/task/context.js +15 -20
- package/build/src/task/document.d.ts +2 -1
- package/build/src/task/document.js +15 -5
- package/build/src/task/index.d.ts +27 -15
- package/build/src/task/index.js +57 -35
- package/build/src/task/operations.d.ts +38 -13
- package/build/src/task/operations.js +80 -46
- package/build/src/task/query.d.ts +67 -0
- package/build/src/task/query.js +279 -0
- package/build/src/task/store.d.ts +5 -7
- package/build/src/task/store.js +43 -28
- package/build/src/verification/declaration.d.ts +1 -0
- package/build/src/verification/execution.d.ts +51 -0
- package/build/src/verification/execution.js +108 -0
- package/build/src/workspace-place.d.ts +41 -0
- package/build/src/workspace-place.js +386 -0
- package/build/src/world.d.ts +24 -0
- package/build/src/world.js +136 -0
- package/package.json +8 -4
- package/build/src/akuma/activity.d.ts +0 -66
- package/build/src/akuma/activity.js +0 -139
- package/build/src/akuma/providers/claude.js +0 -305
- package/build/src/context-root.d.ts +0 -4
- package/build/src/context-root.js +0 -15
- package/build/src/git/delivery.d.ts +0 -20
- package/build/src/git/delivery.js +0 -109
- package/build/src/git/verification.d.ts +0 -14
- package/build/src/git/verification.js +0 -56
- package/build/src/protocol/read/audit.d.ts +0 -25
- package/build/src/protocol/read/audit.js +0 -39
- package/build/src/verification/producer.d.ts +0 -23
- package/build/src/verification/producer.js +0 -54
|
@@ -1,33 +1,68 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dirname, join
|
|
1
|
+
import { access, mkdir } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
3
|
import { acquireSqliteTransactionLock } from "../coordination/sqlite-transaction-lock.js";
|
|
4
4
|
import { AuthorityCorruptionError } from "../core/facts/errors.js";
|
|
5
|
-
import { CANDIDATE_PIN_REF_NAMESPACE, commonGitDirectory, DELIVERY_REF_NAMESPACE, readRef, registeredWorktreePaths, runGit, worktreeGitDirectory, } from "./repository.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { CANDIDATE_PIN_REF_NAMESPACE, commonGitDirectory, DELIVERY_REF_NAMESPACE, GitPlumbingError, isKeiyakuOwnedRef, readRef, registeredWorktreePaths, runGit, worktreeGitDirectory, } from "./repository.js";
|
|
6
|
+
import { contractLocator, contractPhysicalName, gitObjectIdForSnapshot, mintSnapshotId, } from "./identity.js";
|
|
7
|
+
import { observeContractAt } from "./observe.js";
|
|
8
|
+
import { acquireTargetPlacementFence, recoverTargetPlacement, } from "./target-placement.js";
|
|
9
9
|
import { runCreateHooks, runDestroyHooks, } from "./hooks.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
import { worktreePath } from "./workspace.js";
|
|
11
|
+
import { collectableScratchWorktrees } from "./scratch.js";
|
|
12
|
+
import { terminalSealExpectations as decodeTerminalSealExpectations, terminalSealSnapshots, unsealedBytes, } from "./terminal-seal.js";
|
|
13
|
+
const pathExists = (path) => access(path).then(() => true, () => false);
|
|
14
|
+
function deliveryRefFor(contract) {
|
|
15
|
+
return `${DELIVERY_REF_NAMESPACE}/${contractPhysicalName(contract)}`;
|
|
16
|
+
}
|
|
17
|
+
function candidatePinRefFor(contract) {
|
|
18
|
+
return `${CANDIDATE_PIN_REF_NAMESPACE}/${contractPhysicalName(contract)}`;
|
|
19
|
+
}
|
|
20
|
+
function missingPlaceLag(repository) {
|
|
21
|
+
return {
|
|
22
|
+
kind: "reconcile-failed",
|
|
23
|
+
stage: "effect",
|
|
24
|
+
diagnostic: `managed Contract is unappointed: ${join(repository.commonDirectory, "keiyaku", "places.json")}`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function updateRef(repository, ref, desired) {
|
|
28
|
+
const before = await readRef(repository, ref);
|
|
17
29
|
if (before === desired)
|
|
18
30
|
return { kind: "ref", name: ref, action: "unchanged", before, after: desired };
|
|
19
|
-
runGit(repository, [
|
|
31
|
+
await runGit(repository, [
|
|
32
|
+
"update-ref",
|
|
33
|
+
"--no-deref",
|
|
34
|
+
ref,
|
|
35
|
+
gitObjectIdForSnapshot(desired),
|
|
36
|
+
before ?? "0".repeat(desired.length),
|
|
37
|
+
]);
|
|
20
38
|
return { kind: "ref", name: ref, action: before === null ? "created" : "updated", before, after: desired };
|
|
21
39
|
}
|
|
22
|
-
function removeRef(repository, ref) {
|
|
23
|
-
const before = readRef(repository, ref);
|
|
40
|
+
async function removeRef(repository, ref) {
|
|
41
|
+
const before = await readRef(repository, ref);
|
|
24
42
|
if (before === null)
|
|
25
43
|
return { kind: "ref", name: ref, action: "unchanged", before: null, after: null };
|
|
26
|
-
runGit(repository, ["update-ref", "--no-deref", "-d", ref, before]);
|
|
44
|
+
await runGit(repository, ["update-ref", "--no-deref", "-d", ref, before]);
|
|
45
|
+
return { kind: "ref", name: ref, action: "removed", before, after: null };
|
|
46
|
+
}
|
|
47
|
+
async function removeRefWithCustody(repository, ref, custodian, expectedCustodian) {
|
|
48
|
+
const before = await readRef(repository, ref);
|
|
49
|
+
if (before === null)
|
|
50
|
+
return { kind: "ref", name: ref, action: "unchanged", before: null, after: null };
|
|
51
|
+
if (await readRef(repository, custodian) !== expectedCustodian) {
|
|
52
|
+
return { kind: "ref", name: ref, action: "unchanged", before, after: before };
|
|
53
|
+
}
|
|
54
|
+
await runGit(repository, ["update-ref", "--stdin", "--no-deref"], [
|
|
55
|
+
"start",
|
|
56
|
+
`verify ${custodian} ${gitObjectIdForSnapshot(expectedCustodian)}`,
|
|
57
|
+
`delete ${ref} ${before}`,
|
|
58
|
+
"prepare",
|
|
59
|
+
"commit",
|
|
60
|
+
"",
|
|
61
|
+
].join("\n"));
|
|
27
62
|
return { kind: "ref", name: ref, action: "removed", before, after: null };
|
|
28
63
|
}
|
|
29
|
-
function acquireWorktreeTopology(repository) {
|
|
30
|
-
return { paths: new Set(registeredWorktreePaths(repository)) };
|
|
64
|
+
async function acquireWorktreeTopology(repository) {
|
|
65
|
+
return { paths: new Set(await registeredWorktreePaths(repository)) };
|
|
31
66
|
}
|
|
32
67
|
function fromPrimaryWorktree(repository) {
|
|
33
68
|
return { ...repository, effectiveCwd: repository.primaryWorktree };
|
|
@@ -47,44 +82,36 @@ function reconcileLockPath(repository, contract) {
|
|
|
47
82
|
const locator = contractLocator(contract);
|
|
48
83
|
return join(commonGitDirectory(repository), "keiyaku", "locks", "reconcile", locator.slice(0, 2), `${locator.slice(2)}.sqlite`);
|
|
49
84
|
}
|
|
50
|
-
function worktree(repository, topology, path, desired) {
|
|
85
|
+
async function worktree(repository, topology, path, desired) {
|
|
51
86
|
const registered = topology.paths.has(path);
|
|
52
|
-
if (registered &&
|
|
87
|
+
if (registered && await pathExists(path))
|
|
53
88
|
return { kind: "worktree", path, action: "unchanged" };
|
|
54
89
|
if (registered) {
|
|
55
|
-
runGit(repository, ["worktree", "remove", path]);
|
|
90
|
+
await runGit(repository, ["worktree", "remove", path]);
|
|
56
91
|
topology.paths.delete(path);
|
|
57
92
|
}
|
|
58
|
-
if (
|
|
93
|
+
if (await pathExists(path))
|
|
59
94
|
throw new Error(`delivery worktree path is occupied: ${path}`);
|
|
60
|
-
|
|
61
|
-
runGit(repository, ["worktree", "add", "--detach", path, gitObjectIdForSnapshot(desired)]);
|
|
95
|
+
await mkdir(dirname(path), { recursive: true });
|
|
96
|
+
await runGit(repository, ["worktree", "add", "--detach", path, gitObjectIdForSnapshot(desired)]);
|
|
62
97
|
topology.paths.add(path);
|
|
63
98
|
return { kind: "worktree", path, action: "created" };
|
|
64
99
|
}
|
|
65
|
-
function
|
|
66
|
-
if (runGit(repository, ["-C", path, "status", "--porcelain", "--untracked-files=all"]).length !== 0)
|
|
67
|
-
return false;
|
|
68
|
-
const [head, headTree] = runGit(repository, ["-C", path, "rev-parse", "HEAD", "HEAD^{tree}"])
|
|
69
|
-
.toString("utf8").trim().split("\n");
|
|
70
|
-
const matched = expected.find((snapshot) => head === gitObjectIdForSnapshot(snapshot));
|
|
71
|
-
if (matched === undefined)
|
|
72
|
-
return false;
|
|
73
|
-
const expectedTree = runGit(repository, ["-C", path, "rev-parse", `${gitObjectIdForSnapshot(matched)}^{tree}`])
|
|
74
|
-
.toString("utf8").trim();
|
|
75
|
-
return headTree === expectedTree;
|
|
76
|
-
}
|
|
77
|
-
function removeWorktree(repository, topology, path) {
|
|
100
|
+
async function removeWorktree(repository, topology, path, force = false) {
|
|
78
101
|
const registered = topology.paths.has(path);
|
|
79
|
-
if (!registered)
|
|
80
|
-
return {
|
|
81
|
-
|
|
82
|
-
|
|
102
|
+
if (!registered) {
|
|
103
|
+
return {
|
|
104
|
+
effect: { kind: "worktree", path, action: "unchanged" },
|
|
105
|
+
retained: await pathExists(path),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (!await pathExists(path)) {
|
|
109
|
+
await runGit(repository, ["worktree", "remove", path]);
|
|
83
110
|
topology.paths.delete(path);
|
|
84
111
|
return { effect: { kind: "worktree", path, action: "removed" }, retained: false };
|
|
85
112
|
}
|
|
86
113
|
try {
|
|
87
|
-
runGit(repository, ["worktree", "remove", path]);
|
|
114
|
+
await runGit(repository, ["worktree", "remove", ...(force ? ["--force"] : []), path]);
|
|
88
115
|
}
|
|
89
116
|
catch {
|
|
90
117
|
return { effect: { kind: "worktree", path, action: "unchanged" }, retained: true };
|
|
@@ -92,68 +119,233 @@ function removeWorktree(repository, topology, path) {
|
|
|
92
119
|
topology.paths.delete(path);
|
|
93
120
|
return { effect: { kind: "worktree", path, action: "removed" }, retained: false };
|
|
94
121
|
}
|
|
95
|
-
async function
|
|
122
|
+
async function removeCollectableScratch(repository, topology, effects, lag) {
|
|
123
|
+
for (const scratch of await collectableScratchWorktrees(topology.paths)) {
|
|
124
|
+
try {
|
|
125
|
+
const removal = await removeWorktree(repository, topology, scratch.path, true);
|
|
126
|
+
effects.push(removal.effect);
|
|
127
|
+
if (removal.retained)
|
|
128
|
+
lag.push({ kind: "worktree-retained", path: scratch.path });
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
scratch.release();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function refRows(repository) {
|
|
136
|
+
const output = (await runGit(repository, [
|
|
137
|
+
"for-each-ref",
|
|
138
|
+
"--format=%(refname)%00%(objectname)",
|
|
139
|
+
])).toString("utf8");
|
|
140
|
+
if (output.length === 0)
|
|
141
|
+
return [];
|
|
142
|
+
return output.trimEnd().split("\n").map((row) => {
|
|
143
|
+
const [ref, oid, extra] = row.split("\0");
|
|
144
|
+
if (ref === undefined || oid === undefined || extra !== undefined)
|
|
145
|
+
throw new Error("Git ref row is malformed");
|
|
146
|
+
return { ref, oid };
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async function snapshotCustodian(repository, snapshot) {
|
|
150
|
+
for (const row of await refRows(repository)) {
|
|
151
|
+
if (isKeiyakuOwnedRef(row.ref))
|
|
152
|
+
continue;
|
|
153
|
+
try {
|
|
154
|
+
await runGit(repository, ["merge-base", "--is-ancestor", gitObjectIdForSnapshot(snapshot), row.oid]);
|
|
155
|
+
return { ref: row.ref, oid: mintSnapshotId(row.oid) };
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
if (error instanceof GitPlumbingError && error.status === 1)
|
|
159
|
+
continue;
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
async function reconcileTargetCheckouts(repository, state) {
|
|
166
|
+
if (state.terminal?.kind !== "claimed" || state.coordinates.target === undefined || state.delivery === null) {
|
|
167
|
+
return complete();
|
|
168
|
+
}
|
|
169
|
+
let held;
|
|
170
|
+
try {
|
|
171
|
+
held = await acquireTargetPlacementFence(repository, state.coordinates.target);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
return failed("effect", error);
|
|
175
|
+
}
|
|
176
|
+
let result;
|
|
177
|
+
let exceptional;
|
|
178
|
+
try {
|
|
179
|
+
const recovered = await recoverTargetPlacement(repository, state);
|
|
180
|
+
result = complete(recovered.effects, recovered.lag);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
if (error instanceof AuthorityCorruptionError || error instanceof TypeError)
|
|
184
|
+
exceptional = error;
|
|
185
|
+
else
|
|
186
|
+
result = failed("effect", error);
|
|
187
|
+
}
|
|
188
|
+
let releaseFailure;
|
|
189
|
+
try {
|
|
190
|
+
held.close();
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
releaseFailure = error;
|
|
194
|
+
}
|
|
195
|
+
if (exceptional !== undefined)
|
|
196
|
+
throw exceptional;
|
|
197
|
+
if (result === undefined)
|
|
198
|
+
throw new Error("target checkout reconcile produced no result");
|
|
199
|
+
if (releaseFailure !== undefined)
|
|
200
|
+
result = failed("effect", releaseFailure, result.effects, result.lag);
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
async function reconcileHereWorkspaceRefs({ repository }, state, { effects, lag }) {
|
|
204
|
+
const pin = candidatePinRefFor(state.id);
|
|
205
|
+
if (state.terminal) {
|
|
206
|
+
if (state.delivery === null)
|
|
207
|
+
effects.push(await removeRef(repository, pin));
|
|
208
|
+
else {
|
|
209
|
+
const integration = state.delivery.data.integration.snapshot;
|
|
210
|
+
const custodian = await snapshotCustodian(repository, integration);
|
|
211
|
+
effects.push(await (custodian === null
|
|
212
|
+
? await updateRef(repository, pin, integration)
|
|
213
|
+
: await removeRefWithCustody(repository, pin, custodian.ref, custodian.oid)));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else if (state.bound) {
|
|
217
|
+
effects.push(await (state.delivery === null
|
|
218
|
+
? await removeRef(repository, pin)
|
|
219
|
+
: await updateRef(repository, pin, state.delivery.data.integration.snapshot)));
|
|
220
|
+
}
|
|
221
|
+
return complete(effects, lag);
|
|
222
|
+
}
|
|
223
|
+
function retainTerminalWorktree(path, retainedLag, { effects, lag }) {
|
|
224
|
+
effects.push({ kind: "worktree", path, action: "unchanged" });
|
|
225
|
+
lag.push(retainedLag);
|
|
226
|
+
return complete(effects, lag);
|
|
227
|
+
}
|
|
228
|
+
async function terminalSealExpectations(channel, state) {
|
|
229
|
+
const snapshots = terminalSealSnapshots(state);
|
|
230
|
+
const objects = await channel.readObjects(snapshots.map(gitObjectIdForSnapshot));
|
|
231
|
+
return decodeTerminalSealExpectations(state, objects);
|
|
232
|
+
}
|
|
233
|
+
async function removeSealedTerminalWorktree({ repository, topology, path, expected, hooks, retryHooks, acc }) {
|
|
234
|
+
if (topology.paths.has(path) && await pathExists(path)) {
|
|
235
|
+
const beforeHooks = await unsealedBytes(repository, path, expected);
|
|
236
|
+
if (beforeHooks !== null)
|
|
237
|
+
return retainTerminalWorktree(path, beforeHooks, acc);
|
|
238
|
+
const hookLag = await runDestroyHooks(path, await worktreeGitDirectory(repository, path), hooks, retryHooks);
|
|
239
|
+
if (hookLag !== null)
|
|
240
|
+
return retainTerminalWorktree(path, hookLag, acc);
|
|
241
|
+
const afterHooks = await unsealedBytes(repository, path, expected);
|
|
242
|
+
if (afterHooks !== null)
|
|
243
|
+
return retainTerminalWorktree(path, afterHooks, acc);
|
|
244
|
+
}
|
|
245
|
+
const removal = await removeWorktree(repository, topology, path, true);
|
|
246
|
+
if (removal.retained)
|
|
247
|
+
return retainTerminalWorktree(path, { kind: "worktree-retained", path }, acc);
|
|
248
|
+
acc.effects.push(removal.effect);
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
async function targetCustodyForClaimedIntegration(repository, state, integration) {
|
|
252
|
+
return state.terminal?.kind === "claimed" && state.coordinates.target !== undefined
|
|
253
|
+
&& await readRef(repository, state.coordinates.target) === integration
|
|
254
|
+
? { ref: state.coordinates.target, oid: integration }
|
|
255
|
+
: null;
|
|
256
|
+
}
|
|
257
|
+
function sealedTree(expected, snapshot) {
|
|
258
|
+
const tree = expected.treeBySnapshot.get(snapshot);
|
|
259
|
+
if (tree === undefined)
|
|
260
|
+
throw new Error(`terminal seal tree was not resolved: ${snapshot}`);
|
|
261
|
+
return tree;
|
|
262
|
+
}
|
|
263
|
+
async function releaseTerminalCustody({ repository, state, expected, ref, pin, acc: { effects } }) {
|
|
264
|
+
if (state.delivery === null) {
|
|
265
|
+
const custodian = await snapshotCustodian(repository, state.coordinates.start);
|
|
266
|
+
if (custodian !== null)
|
|
267
|
+
effects.push(await removeRefWithCustody(repository, ref, custodian.ref, custodian.oid));
|
|
268
|
+
effects.push(await removeRef(repository, pin));
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const tender = state.delivery.data.tenderSnapshot;
|
|
272
|
+
const integration = state.delivery.data.integration.snapshot;
|
|
273
|
+
const target = await targetCustodyForClaimedIntegration(repository, state, integration);
|
|
274
|
+
if (sealedTree(expected, tender) === sealedTree(expected, integration) && target !== null) {
|
|
275
|
+
effects.push(await removeRefWithCustody(repository, ref, target.ref, target.oid));
|
|
276
|
+
effects.push(await removeRefWithCustody(repository, pin, target.ref, target.oid));
|
|
277
|
+
}
|
|
278
|
+
else if (tender === integration) {
|
|
279
|
+
effects.push(await removeRefWithCustody(repository, pin, ref, tender));
|
|
280
|
+
}
|
|
281
|
+
else if (target !== null) {
|
|
282
|
+
effects.push(await removeRefWithCustody(repository, pin, target.ref, target.oid));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async function reconcileTerminalManagedWorktree({ repository, channel, hooks, retryHooks, retainTerminalWorktree, place }, state, topology, acc) {
|
|
286
|
+
const primary = fromPrimaryWorktree(repository);
|
|
287
|
+
const ref = deliveryRefFor(state.id);
|
|
288
|
+
const pin = candidatePinRefFor(state.id);
|
|
289
|
+
const path = place === undefined ? undefined : worktreePath(repository, place);
|
|
290
|
+
if (path === undefined)
|
|
291
|
+
return complete(acc.effects, acc.lag);
|
|
292
|
+
const expected = await terminalSealExpectations(channel, state);
|
|
293
|
+
acc.effects.push(await updateRef(primary, ref, state.delivery?.data.tenderSnapshot ?? state.coordinates.start));
|
|
294
|
+
if (state.delivery !== null) {
|
|
295
|
+
acc.effects.push(await updateRef(primary, pin, state.delivery.data.integration.snapshot));
|
|
296
|
+
}
|
|
297
|
+
if (retainTerminalWorktree === true)
|
|
298
|
+
return complete(acc.effects, acc.lag);
|
|
299
|
+
const retained = await removeSealedTerminalWorktree({
|
|
300
|
+
repository: primary,
|
|
301
|
+
topology,
|
|
302
|
+
path,
|
|
303
|
+
expected,
|
|
304
|
+
hooks,
|
|
305
|
+
retryHooks,
|
|
306
|
+
acc,
|
|
307
|
+
});
|
|
308
|
+
if (retained !== null)
|
|
309
|
+
return retained;
|
|
310
|
+
await releaseTerminalCustody({ repository: primary, state, expected, ref, pin, acc });
|
|
311
|
+
return complete(acc.effects, acc.lag);
|
|
312
|
+
}
|
|
313
|
+
async function reconcileActiveManagedWorktree({ repository, hooks, retryHooks, place }, state, topology, { effects, lag }) {
|
|
314
|
+
if (place === undefined)
|
|
315
|
+
return complete(effects, [...lag, missingPlaceLag(repository)]);
|
|
316
|
+
const path = worktreePath(repository, place);
|
|
317
|
+
const desired = state.delivery?.data.tenderSnapshot ?? state.coordinates.start;
|
|
318
|
+
effects.push(await updateRef(repository, deliveryRefFor(state.id), desired));
|
|
319
|
+
effects.push(await worktree(repository, topology, path, desired));
|
|
320
|
+
const hookLag = await runCreateHooks(path, await worktreeGitDirectory(repository, path), hooks, retryHooks);
|
|
321
|
+
if (hookLag !== null)
|
|
322
|
+
lag.push(hookLag);
|
|
323
|
+
effects.push(await (state.delivery
|
|
324
|
+
? await updateRef(repository, candidatePinRefFor(state.id), state.delivery.data.integration.snapshot)
|
|
325
|
+
: await removeRef(repository, candidatePinRefFor(state.id))));
|
|
326
|
+
return complete(effects, lag);
|
|
327
|
+
}
|
|
328
|
+
async function reconcileWithTopology(input, state, topology) {
|
|
329
|
+
const { repository } = input;
|
|
96
330
|
const effects = [];
|
|
97
331
|
const lag = [];
|
|
98
332
|
try {
|
|
333
|
+
await removeCollectableScratch(repository, topology, effects, lag);
|
|
99
334
|
if (!state)
|
|
100
335
|
return complete(effects, lag);
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return complete(effects, lag);
|
|
110
|
-
}
|
|
111
|
-
if (state.terminal) {
|
|
112
|
-
const expected = state.delivery === null
|
|
113
|
-
? [state.coordinates.start]
|
|
114
|
-
: [state.delivery.data.candidate, state.coordinates.start];
|
|
115
|
-
const primary = fromPrimaryWorktree(repository);
|
|
116
|
-
const retain = (retainedLag) => {
|
|
117
|
-
effects.push(updateRef(primary, ref, state.delivery?.data.candidate ?? state.coordinates.start));
|
|
118
|
-
effects.push(state.delivery === null ? removeRef(primary, pin) : updateRef(primary, pin, state.delivery.data.candidate));
|
|
119
|
-
effects.push({ kind: "worktree", path, action: "unchanged" });
|
|
120
|
-
lag.push(retainedLag);
|
|
121
|
-
return complete(effects, lag);
|
|
122
|
-
};
|
|
123
|
-
const registered = topology.paths.has(path);
|
|
124
|
-
if (registered && existsSync(path)) {
|
|
125
|
-
if (!canRemoveWorktree(primary, path, expected))
|
|
126
|
-
return retain({ kind: "worktree-retained", path });
|
|
127
|
-
const hookLag = await runDestroyHooks(path, worktreeGitDirectory(primary, path), hooks, retryHooks);
|
|
128
|
-
if (hookLag !== null)
|
|
129
|
-
return retain(hookLag);
|
|
130
|
-
}
|
|
131
|
-
const removal = removeWorktree(primary, topology, path);
|
|
132
|
-
if (removal.retained)
|
|
133
|
-
return retain({ kind: "worktree-retained", path });
|
|
134
|
-
effects.push(removal.effect);
|
|
135
|
-
effects.push(removeRef(primary, ref));
|
|
136
|
-
effects.push(removeRef(primary, pin));
|
|
137
|
-
return complete(effects, lag);
|
|
138
|
-
}
|
|
139
|
-
if (!state.bound)
|
|
140
|
-
return complete(effects, lag);
|
|
141
|
-
const desired = state.delivery?.data.candidate ?? state.coordinates.start;
|
|
142
|
-
effects.push(updateRef(repository, ref, desired));
|
|
143
|
-
effects.push(worktree(repository, topology, path, desired));
|
|
144
|
-
const hookLag = await runCreateHooks(path, worktreeGitDirectory(repository, path), hooks, retryHooks);
|
|
145
|
-
if (hookLag !== null)
|
|
146
|
-
lag.push(hookLag);
|
|
147
|
-
effects.push(state.delivery ? updateRef(repository, pin, state.delivery.data.candidate) : removeRef(repository, pin));
|
|
148
|
-
return complete(effects, lag);
|
|
336
|
+
const targetCheckouts = await reconcileTargetCheckouts(repository, state);
|
|
337
|
+
effects.push(...targetCheckouts.effects);
|
|
338
|
+
lag.push(...targetCheckouts.lag);
|
|
339
|
+
if (state.coordinates.workspace === "here")
|
|
340
|
+
return await reconcileHereWorkspaceRefs(input, state, { effects, lag });
|
|
341
|
+
if (state.terminal)
|
|
342
|
+
return await reconcileTerminalManagedWorktree(input, state, topology, { effects, lag });
|
|
343
|
+
return await reconcileActiveManagedWorktree(input, state, topology, { effects, lag });
|
|
149
344
|
}
|
|
150
345
|
catch (error) {
|
|
151
346
|
return failed("effect", error, effects, lag);
|
|
152
347
|
}
|
|
153
348
|
}
|
|
154
|
-
function needsWorktreeTopology(state) {
|
|
155
|
-
return state !== null && state.coordinates.workspace === "worktree" && (state.terminal !== null || state.bound !== null);
|
|
156
|
-
}
|
|
157
349
|
function releaseFailure(held, observation) {
|
|
158
350
|
try {
|
|
159
351
|
held.close();
|
|
@@ -181,10 +373,8 @@ export async function reconcile(input) {
|
|
|
181
373
|
let observation;
|
|
182
374
|
let exceptional;
|
|
183
375
|
try {
|
|
184
|
-
const state =
|
|
185
|
-
const topology =
|
|
186
|
-
? acquireWorktreeTopology(input.repository)
|
|
187
|
-
: { paths: new Set() };
|
|
376
|
+
const state = (await observeContractAt(input.repository, input.channel, input.contractId)).state;
|
|
377
|
+
const topology = await acquireWorktreeTopology(input.repository);
|
|
188
378
|
observation = {
|
|
189
379
|
state,
|
|
190
380
|
result: await reconcileWithTopology(input, state, topology),
|
|
@@ -206,18 +396,24 @@ export async function reconcile(input) {
|
|
|
206
396
|
export function reconcileObservationFailure(error) {
|
|
207
397
|
return failed("observation", error);
|
|
208
398
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
contract,
|
|
213
|
-
state: observation.state,
|
|
214
|
-
result: observation.result,
|
|
215
|
-
};
|
|
399
|
+
export function reconcileEffectFailure(error, prior) {
|
|
400
|
+
return failed("effect", error, prior?.effects, prior?.lag);
|
|
216
401
|
}
|
|
217
402
|
/** Reconcile each discovered Contract through its own serialized, fresh observation. */
|
|
218
|
-
export async function reconcileBatch(repository,
|
|
403
|
+
export async function reconcileBatch(repository, channel, contracts, options) {
|
|
219
404
|
const items = [];
|
|
220
|
-
for (const contract of contracts)
|
|
221
|
-
|
|
405
|
+
for (const contract of contracts) {
|
|
406
|
+
const place = options.places?.get(contract);
|
|
407
|
+
const observation = await reconcile({
|
|
408
|
+
repository,
|
|
409
|
+
channel,
|
|
410
|
+
contractId: contract,
|
|
411
|
+
hooks: options.hooks,
|
|
412
|
+
retryHooks: options.retryHooks,
|
|
413
|
+
retainTerminalWorktree: options.retainTerminalWorktree,
|
|
414
|
+
...(place === undefined ? {} : { place }),
|
|
415
|
+
});
|
|
416
|
+
items.push({ contract, state: observation.state, result: observation.result });
|
|
417
|
+
}
|
|
222
418
|
return items;
|
|
223
419
|
}
|
|
@@ -4,7 +4,7 @@ export declare const GIT_REF = "refs/heads/keiyaku-state";
|
|
|
4
4
|
export declare const DELIVERY_REF_NAMESPACE = "refs/heads/keiyaku-delivery";
|
|
5
5
|
export declare const CANDIDATE_PIN_REF_NAMESPACE = "refs/heads/keiyaku-candidate";
|
|
6
6
|
export declare const GIT_FORMAT_PATH = "meta/format.json";
|
|
7
|
-
export declare const GIT_FORMAT_BYTES = "{\"version\":
|
|
7
|
+
export declare const GIT_FORMAT_BYTES = "{\"version\":4}\n";
|
|
8
8
|
export declare function isKeiyakuOwnedRef(ref: string): boolean;
|
|
9
9
|
export type GitOid = string;
|
|
10
10
|
export type RefPublication = Readonly<{
|
|
@@ -15,11 +15,17 @@ export type RefPublication = Readonly<{
|
|
|
15
15
|
}> | Readonly<{
|
|
16
16
|
readonly kind: "unknown";
|
|
17
17
|
}>;
|
|
18
|
+
export type GitRefAssertion = Readonly<{
|
|
19
|
+
readonly ref: string;
|
|
20
|
+
readonly oid: GitOid;
|
|
21
|
+
}>;
|
|
18
22
|
export type GitRepository = Readonly<{
|
|
19
23
|
/** The invocation's effective working directory, including a caller -C worktree. */
|
|
20
24
|
readonly effectiveCwd: string;
|
|
21
25
|
/** The canonical primary worktree root for this repository. */
|
|
22
26
|
readonly primaryWorktree: string;
|
|
27
|
+
/** The canonical common Git directory pinned when this capability is created. */
|
|
28
|
+
readonly commonDirectory: string;
|
|
23
29
|
}>;
|
|
24
30
|
export type GitSnapshot = Readonly<{
|
|
25
31
|
readonly commit: GitOid | null;
|
|
@@ -31,36 +37,46 @@ export declare class NoGitWorldError extends Error {
|
|
|
31
37
|
constructor(path: string);
|
|
32
38
|
}
|
|
33
39
|
export declare class GitPlumbingError extends Error {
|
|
40
|
+
readonly stdout: Buffer;
|
|
34
41
|
readonly stderr: Buffer;
|
|
35
42
|
readonly status: number | null;
|
|
36
43
|
readonly pid: number | null;
|
|
37
44
|
constructor(input: Readonly<{
|
|
45
|
+
stdout?: string | Uint8Array;
|
|
38
46
|
stderr: string | Uint8Array;
|
|
39
47
|
status: number | null;
|
|
40
48
|
message: string;
|
|
41
49
|
pid?: number | null;
|
|
42
50
|
}>);
|
|
43
51
|
}
|
|
44
|
-
export
|
|
45
|
-
|
|
52
|
+
export type RegisteredWorktree = Readonly<{
|
|
53
|
+
path: string;
|
|
54
|
+
branch: string | null;
|
|
55
|
+
}>;
|
|
56
|
+
export declare function registeredWorktrees(repository: GitRepository): Promise<readonly RegisteredWorktree[]>;
|
|
57
|
+
export declare function registeredWorktreePaths(repository: GitRepository): Promise<readonly string[]>;
|
|
58
|
+
export declare function repositoryAt(cwd: string): Promise<GitRepository>;
|
|
46
59
|
export declare function commonGitDirectory(repository: GitRepository): string;
|
|
47
|
-
export declare function worktreeGitDirectory(repository: GitRepository, worktree: string): string
|
|
48
|
-
export declare function
|
|
49
|
-
export declare function
|
|
50
|
-
export declare function
|
|
51
|
-
export declare function
|
|
60
|
+
export declare function worktreeGitDirectory(repository: GitRepository, worktree: string): Promise<string>;
|
|
61
|
+
export declare function worktreeRoot(repository: GitRepository): Promise<string>;
|
|
62
|
+
export declare function runGit(repository: GitRepository, args: readonly string[], input?: string | Uint8Array): Promise<Buffer>;
|
|
63
|
+
export declare function consumeGitStdout(repository: GitRepository, args: readonly string[], consume: (chunk: Buffer) => void): Promise<void>;
|
|
64
|
+
export declare function runGitWithEnvironment(repository: GitRepository, args: readonly string[], input: string | Uint8Array | undefined, environment: NodeJS.ProcessEnv): Promise<Buffer>;
|
|
65
|
+
export declare function readRef(repository: GitRepository, ref: string): Promise<GitOid | null>;
|
|
66
|
+
export declare function readTreeEntries(repository: GitRepository, tree: GitOid): Promise<Map<string, TreeEntry>>;
|
|
67
|
+
export declare function readGit(repository: GitRepository): Promise<GitSnapshot>;
|
|
52
68
|
/** Read only the requested private Git paths from one immutable Git tree. */
|
|
53
|
-
export declare function readGitPaths(repository: GitRepository, requestedPaths: readonly string[]): GitSnapshot
|
|
69
|
+
export declare function readGitPaths(repository: GitRepository, requestedPaths: readonly string[]): Promise<GitSnapshot>;
|
|
54
70
|
/** Add paths from the same immutable Git tree without rereading its ref. */
|
|
55
|
-
export declare function extendGitPaths(repository: GitRepository, snapshot: GitSnapshot, requestedPaths: readonly string[]): GitSnapshot
|
|
71
|
+
export declare function extendGitPaths(repository: GitRepository, snapshot: GitSnapshot, requestedPaths: readonly string[]): Promise<GitSnapshot>;
|
|
56
72
|
/** Expand a targeted immutable snapshot to its complete already-pinned tree. */
|
|
57
|
-
export declare function expandGitSnapshot(repository: GitRepository, snapshot: GitSnapshot): GitSnapshot
|
|
58
|
-
export declare function writeBlob(repository: GitRepository, bytes: string | Uint8Array): GitOid
|
|
59
|
-
export declare function readBlob(repository: GitRepository, oid: GitOid): Buffer
|
|
60
|
-
/** Read immutable Git objects through one structured, length-delimited batch. */
|
|
61
|
-
export declare function readBlobs(repository: GitRepository, oids: readonly GitOid[]): ReadonlyMap<GitOid, Buffer>;
|
|
73
|
+
export declare function expandGitSnapshot(repository: GitRepository, snapshot: GitSnapshot): Promise<GitSnapshot>;
|
|
74
|
+
export declare function writeBlob(repository: GitRepository, bytes: string | Uint8Array): Promise<GitOid>;
|
|
75
|
+
export declare function readBlob(repository: GitRepository, oid: GitOid): Promise<Buffer>;
|
|
62
76
|
/** Copy only the changed paths' tree ancestors, preserving untouched subtrees by object ID. */
|
|
63
|
-
export declare function updateGitTree(repository: GitRepository, baseTree: GitOid | null, changes: ReadonlyMap<string, TreeChange>): GitOid
|
|
77
|
+
export declare function updateGitTree(repository: GitRepository, baseTree: GitOid | null, changes: ReadonlyMap<string, TreeChange>): Promise<GitOid>;
|
|
78
|
+
/** Write a tree update from directory entries frozen with the admitted base tree. */
|
|
79
|
+
export declare function updateGitTreeFromFrozenDirectories(repository: GitRepository, baseTree: GitOid | null, directories: ReadonlyMap<string, ReadonlyMap<string, TreeEntry>>, changes: ReadonlyMap<string, TreeChange>): Promise<GitOid>;
|
|
64
80
|
export declare function writeCommit(input: Readonly<{
|
|
65
81
|
repository: GitRepository;
|
|
66
82
|
tree: GitOid;
|
|
@@ -68,7 +84,7 @@ export declare function writeCommit(input: Readonly<{
|
|
|
68
84
|
message?: string;
|
|
69
85
|
actor?: string;
|
|
70
86
|
at?: string;
|
|
71
|
-
}>): GitOid
|
|
87
|
+
}>): Promise<GitOid>;
|
|
72
88
|
export declare function updateRefsAtomically(repository: GitRepository, updates: readonly ({
|
|
73
89
|
readonly ref: typeof GIT_REF;
|
|
74
90
|
readonly newOid: GitOid;
|
|
@@ -77,4 +93,11 @@ export declare function updateRefsAtomically(repository: GitRepository, updates:
|
|
|
77
93
|
readonly ref: string;
|
|
78
94
|
readonly newOid: GitOid;
|
|
79
95
|
readonly expectedOid: GitOid;
|
|
80
|
-
})[]): RefPublication
|
|
96
|
+
})[], assertions?: readonly GitRefAssertion[]): Promise<RefPublication>;
|
|
97
|
+
export type GitDiffStat = Readonly<{
|
|
98
|
+
filesChanged: number;
|
|
99
|
+
insertions: number;
|
|
100
|
+
deletions: number;
|
|
101
|
+
}>;
|
|
102
|
+
export declare function decodeGitNumstat(output: Buffer): GitDiffStat;
|
|
103
|
+
export declare function decodeGitNameOnly(output: Buffer): readonly string[];
|