@afokapu/atdd-bun 0.10.101 → 0.10.103
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/integrity.json +2 -2
- package/package.json +1 -1
- package/src/hooks.ts +7 -6
package/integrity.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.10.
|
|
2
|
+
"version": "0.10.103",
|
|
3
3
|
"files": {
|
|
4
4
|
"HOOK_AUDIT.md": "5329d840db37671b1918f688ead26865473b87db73dbc75f7c8b2a8bbe8d6d43",
|
|
5
5
|
"PLANNER_PORT.md": "fb5935bac8b7ac18994de21e43ace3a5ef8cd55f85b0e3349fca261280054f11",
|
|
@@ -1261,7 +1261,7 @@
|
|
|
1261
1261
|
"src/cli.ts": "395638ab87565bb10c2beb35988ff1acf686924d13515795156a2e8893b3da88",
|
|
1262
1262
|
"src/docs-capability.ts": "bdeeb414649049b1cd4fa8008cada3a576318be51c43bec91bfa46a8e250c270",
|
|
1263
1263
|
"src/enforce.ts": "e0c10519aeecd7080f2900ea230fad2f09482af47c1cee885d5de71573e29732",
|
|
1264
|
-
"src/hooks.ts": "
|
|
1264
|
+
"src/hooks.ts": "62a0557c5914fc56abc3ca4900a86ba333e6a92938e75a39d46ebaee0af4f0b0",
|
|
1265
1265
|
"src/index.ts": "4081f8b08d1d3ee9e15a9964143e53d9cfb94a5616ab3e58a180d24cc16dc381",
|
|
1266
1266
|
"src/integrity.ts": "f1ede7cb04924ae88e11917047277e264af6596b9759e381bd9c497cd34a797d",
|
|
1267
1267
|
"src/journey-docs.ts": "994d229376244c84212cff951032823068a76565dd2fd427b9d44e341bd14853",
|
package/package.json
CHANGED
package/src/hooks.ts
CHANGED
|
@@ -411,7 +411,7 @@ async function branchCommit(root: string, branch: string) {
|
|
|
411
411
|
|
|
412
412
|
// A delivery commit must have one unambiguous non-protected exported bookmark.
|
|
413
413
|
// Ref ordering is never used as ownership authority.
|
|
414
|
-
async function branchForCommit(root: string, commit: string, protectedBranches: string[]) {
|
|
414
|
+
async function branchForCommit(root: string, commit: string, protectedBranches: string[]): Promise<{ error: string } | { branch: string }> {
|
|
415
415
|
const refs = await git(root, ["for-each-ref", "--format=%(refname:short)", "--points-at", commit, "refs/heads/"]);
|
|
416
416
|
if (refs.code) return { error: refs.err || refs.out };
|
|
417
417
|
const candidates = refs.out.split("\n").map(line => line.trim()).filter(Boolean)
|
|
@@ -433,7 +433,7 @@ async function jjLayout(root: string, cfg: HookPolicy): Promise<Layout | { error
|
|
|
433
433
|
return { primary, worktreeRoot: resolve(primary, cfg.worktrees.root.replaceAll("{repo}", basename(primary))), current };
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
-
async function noConflicts(root: string) {
|
|
436
|
+
async function noConflicts(root: string): Promise<{ error: string } | { error?: undefined }> {
|
|
437
437
|
const result = await jj(root, ["log", "-r", "@ & conflicts()", "--no-graph", "-T", "commit_id"]);
|
|
438
438
|
return result.code ? { error: result.err || result.out } : result.out ? { error: "workspace has unresolved conflicts" } : {};
|
|
439
439
|
}
|
|
@@ -444,7 +444,7 @@ async function preflight(root: string, cfg: HookPolicy): Promise<Layout | { erro
|
|
|
444
444
|
return version ? { error: version } : jjLayout(root, cfg);
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
-
async function startTarget(root: string, branch: string, state: Layout, cfg: HookPolicy) {
|
|
447
|
+
async function startTarget(root: string, branch: string, state: Layout, cfg: HookPolicy): Promise<{ error: string } | { leaf: string; target: string }> {
|
|
448
448
|
if (state.current !== state.primary) return { error: `start must run from the primary checkout ${state.primary}` };
|
|
449
449
|
if (!branch) return { error: "branch is required: atdd-bun worktree start <branch>" };
|
|
450
450
|
if ((await git(root, ["check-ref-format", "--branch", branch])).code) return { error: `invalid branch name ${JSON.stringify(branch)}` };
|
|
@@ -471,10 +471,10 @@ async function createWorkspace(state: Layout, target: { leaf: string; target: st
|
|
|
471
471
|
return bad(bookmark.err || bookmark.out || `bookmark ${branch} was not exported to the colocated Git repository`);
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
-
async function finishCandidate(state: Layout, cfg: HookPolicy) {
|
|
474
|
+
async function finishCandidate(state: Layout, cfg: HookPolicy): Promise<{ error: string } | { branch: string; tip: string; name: string }> {
|
|
475
475
|
if (state.current === state.primary || !inside(state.worktreeRoot, state.current)) return { error: `finish must run from a linked workspace beneath ${state.worktreeRoot}` };
|
|
476
476
|
const conflict = await noConflicts(state.current);
|
|
477
|
-
if (
|
|
477
|
+
if (conflict.error !== undefined) return conflict;
|
|
478
478
|
const current = await currentCommit(state.current);
|
|
479
479
|
if (!current) return { error: "could not resolve the current Jujutsu revision" };
|
|
480
480
|
let delivery = current, found = await branchForCommit(state.current, current, cfg.protected_branches);
|
|
@@ -546,6 +546,7 @@ export async function startWorktree(root = process.cwd(), branch = "", vcs: VcsM
|
|
|
546
546
|
|
|
547
547
|
export async function worktreeStatus(root = process.cwd(), vcs: VcsMode = "git") { const { policy: cfg, source } = await primaryPolicy(root); if (!cfg.worktrees.enabled) return disabledWorktreePolicy(source); if (vcs === "jj") return statusJjWorktrees(root, cfg); const state = await layout(root, cfg.worktrees); if ("error" in state) return bad(state.error); const result = await git(state.primary, ["worktree", "list", "--porcelain"]); return result.code ? bad(result.err) : { ok: true, message: result.out }; }
|
|
548
548
|
|
|
549
|
+
const generatedHookStatusLines = new Set(["?? .githooks/", ...hookEvents.map(event => ` M .githooks/${event}`)]);
|
|
549
550
|
async function generatedHooksOnly(root: string): Promise<boolean> { const directory = join(root, ".githooks"); if (!existsSync(directory)) return false; const names = (await readdir(directory)).sort(); if (names.join("\n") !== [...hookEvents].sort().join("\n")) return false; return (await Promise.all(hookEvents.map(async event => (await readFile(join(directory, event), "utf8")) === await renderHook(event, root)))).every(Boolean); }
|
|
550
551
|
|
|
551
|
-
export async function finishWorktree(root = process.cwd(), deleteBranch = false, vcs: VcsMode = "git") { const { policy: cfg, source } = await primaryPolicy(root); if (!cfg.worktrees.enabled) return disabledWorktreePolicy(source); if (vcs === "jj") return finishJjWorktree(root, deleteBranch, cfg); const state = await layout(root, cfg.worktrees); if ("error" in state) return bad(state.error); if (state.current === state.primary || !inside(state.worktreeRoot, state.current)) return bad(`finish must run from a linked worktree beneath ${state.worktreeRoot}`); if (!state.branch || cfg.protected_branches.includes(state.branch)) return bad("finish requires a non-protected named branch"); const status = (await git(state.current, ["status", "--porcelain"])).out, generatedHooks = await generatedHooksOnly(state.current), onlyGeneratedHooks =
|
|
552
|
+
export async function finishWorktree(root = process.cwd(), deleteBranch = false, vcs: VcsMode = "git") { const { policy: cfg, source } = await primaryPolicy(root); if (!cfg.worktrees.enabled) return disabledWorktreePolicy(source); if (vcs === "jj") return finishJjWorktree(root, deleteBranch, cfg); const state = await layout(root, cfg.worktrees); if ("error" in state) return bad(state.error); if (state.current === state.primary || !inside(state.worktreeRoot, state.current)) return bad(`finish must run from a linked worktree beneath ${state.worktreeRoot}`); if (!state.branch || cfg.protected_branches.includes(state.branch)) return bad("finish requires a non-protected named branch"); const status = (await git(state.current, ["status", "--porcelain"], undefined, true)).out.split("\n").filter(Boolean), generatedHooks = await generatedHooksOnly(state.current), onlyGeneratedHooks = status.length > 0 && status.every(line => generatedHookStatusLines.has(line)); if (status.length && !onlyGeneratedHooks) return bad("worktree is dirty; commit, stash, or discard changes before finish"); const tip = (await git(state.primary, ["rev-parse", "--verify", `refs/heads/${state.branch}`])).out.trim(); if (!tip || (await git(state.primary, ["merge-base", "--is-ancestor", tip, cfg.worktrees.primary_branch])).code) return bad(`branch ${state.branch} is not merged into ${cfg.worktrees.primary_branch} in the primary checkout`); const removed = await git(state.primary, ["worktree", "remove", ...(onlyGeneratedHooks && generatedHooks ? ["--force"] : []), state.current]); if (removed.code) return bad(removed.err || removed.out); if (deleteBranch) { const now = (await git(state.primary, ["rev-parse", "--verify", `refs/heads/${state.branch}`])).out.trim(); if (now !== tip || (await git(state.primary, ["merge-base", "--is-ancestor", tip, cfg.worktrees.primary_branch])).code) return bad(`worktree removed, but branch ${state.branch} was not deleted: its tip changed or is no longer merged into ${cfg.worktrees.primary_branch}`); const deleted = await git(state.primary, ["branch", "-D", state.branch]); if (deleted.code) return bad(`worktree removed, but branch deletion failed: ${deleted.err || deleted.out}`); } return { ok: true, message: `removed merged worktree ${state.current}${deleteBranch ? ` and branch ${state.branch}` : ""}` }; }
|