@biffo/cli 0.301.4 → 0.301.5
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/dist/index.js +36 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1115,6 +1115,25 @@ var GitAdapter = class {
|
|
|
1115
1115
|
const { stdout } = await execa("git", ["status", "--porcelain"], { cwd });
|
|
1116
1116
|
return stdout.trim().length > 0;
|
|
1117
1117
|
}
|
|
1118
|
+
/**
|
|
1119
|
+
* True if `worktreePath` is currently held by biffo-fleet's own
|
|
1120
|
+
* `.fleet-worktree-claim` lock (#1833, replaces #1825) — a live session
|
|
1121
|
+
* may hold a worktree open for follow-up work after its PR has already
|
|
1122
|
+
* merged, which is invisible to every other check `doctor --fix` applies
|
|
1123
|
+
* (clean, attached, merged, HEAD contained in what shipped all pass while
|
|
1124
|
+
* this is true).
|
|
1125
|
+
*
|
|
1126
|
+
* Deliberately a plain filesystem existence check, not a shell-out to
|
|
1127
|
+
* `bin/fleet.sh worktree-claim --check` — that verb is not read-only (it
|
|
1128
|
+
* `mkdir`s the lock and only reports "held" on failure), so calling it from
|
|
1129
|
+
* here to merely ask would risk *creating* a claim on a free worktree
|
|
1130
|
+
* rather than answering the question. The lock directory's existence is a
|
|
1131
|
+
* filesystem fact this repo is allowed to read without touching
|
|
1132
|
+
* biffo-fleet's own source (#1833's own routing note).
|
|
1133
|
+
*/
|
|
1134
|
+
async hasFleetWorktreeClaim(worktreePath) {
|
|
1135
|
+
return existsSync6(join6(worktreePath, ".fleet-worktree-claim"));
|
|
1136
|
+
}
|
|
1118
1137
|
/** Best-effort fetch of the tracking remote, so the ahead/behind check below
|
|
1119
1138
|
* compares against reality rather than a stale local ref (#394). Never throws:
|
|
1120
1139
|
* offline or a missing remote must not block an upgrade on its own — the
|
|
@@ -14992,6 +15011,7 @@ function runDoctorChecks(facts) {
|
|
|
14992
15011
|
|
|
14993
15012
|
// src/lib/doctor-reaper.ts
|
|
14994
15013
|
function classifyReapCandidate(facts) {
|
|
15014
|
+
if (facts.hasFleetClaim) return { action: "keep", reason: "fleet-worktree-claimed" };
|
|
14995
15015
|
if (facts.isDetached) return { action: "keep", reason: "detached-head" };
|
|
14996
15016
|
if (facts.isDirty) return { action: "keep", reason: "uncommitted-changes" };
|
|
14997
15017
|
switch (facts.prVerdict) {
|
|
@@ -15017,12 +15037,13 @@ function findReapCandidates(branches, worktrees) {
|
|
|
15017
15037
|
}
|
|
15018
15038
|
async function reapCandidate(cwd, candidate, deps) {
|
|
15019
15039
|
const { git, github } = deps;
|
|
15020
|
-
const [current, isDirty] = await Promise.all([
|
|
15040
|
+
const [current, isDirty, hasFleetClaim] = await Promise.all([
|
|
15021
15041
|
git.currentBranch(candidate.worktreePath),
|
|
15022
|
-
git.hasUncommittedChanges(candidate.worktreePath)
|
|
15042
|
+
git.hasUncommittedChanges(candidate.worktreePath),
|
|
15043
|
+
git.hasFleetWorktreeClaim(candidate.worktreePath)
|
|
15023
15044
|
]);
|
|
15024
15045
|
const isDetached = current === "HEAD" || current === "";
|
|
15025
|
-
const prVerdict = isDetached || isDirty ? "unknown" : await github.prVerdictForBranch(cwd, candidate.branch);
|
|
15046
|
+
const prVerdict = isDetached || isDirty || hasFleetClaim ? "unknown" : await github.prVerdictForBranch(cwd, candidate.branch);
|
|
15026
15047
|
let mergeContainsHead = true;
|
|
15027
15048
|
if (prVerdict === "merged") {
|
|
15028
15049
|
const [headSha, mergedHeadSha] = await Promise.all([
|
|
@@ -15031,7 +15052,13 @@ async function reapCandidate(cwd, candidate, deps) {
|
|
|
15031
15052
|
]);
|
|
15032
15053
|
mergeContainsHead = headSha === null || mergedHeadSha === null ? null : await git.isAncestor(cwd, headSha, mergedHeadSha);
|
|
15033
15054
|
}
|
|
15034
|
-
const verdict = classifyReapCandidate({
|
|
15055
|
+
const verdict = classifyReapCandidate({
|
|
15056
|
+
isDetached,
|
|
15057
|
+
isDirty,
|
|
15058
|
+
hasFleetClaim,
|
|
15059
|
+
prVerdict,
|
|
15060
|
+
mergeContainsHead
|
|
15061
|
+
});
|
|
15035
15062
|
if (verdict.action === "keep") {
|
|
15036
15063
|
return { candidate, verdict, worktreeRemoved: null };
|
|
15037
15064
|
}
|
|
@@ -15066,6 +15093,10 @@ async function reapBareBranch(cwd, candidate, deps) {
|
|
|
15066
15093
|
const verdict = classifyReapCandidate({
|
|
15067
15094
|
isDetached: false,
|
|
15068
15095
|
isDirty: false,
|
|
15096
|
+
// A bare branch has no worktree, so there is no `.fleet-worktree-claim`
|
|
15097
|
+
// directory that could exist — trivially false, same reasoning as the
|
|
15098
|
+
// two fields above (#1833).
|
|
15099
|
+
hasFleetClaim: false,
|
|
15069
15100
|
prVerdict,
|
|
15070
15101
|
mergeContainsHead
|
|
15071
15102
|
});
|
|
@@ -15216,6 +15247,7 @@ function printFindings(findings) {
|
|
|
15216
15247
|
var KEEP_REASON_TEXT = {
|
|
15217
15248
|
"detached-head": "worktree HEAD is detached",
|
|
15218
15249
|
"uncommitted-changes": "worktree has uncommitted changes",
|
|
15250
|
+
"fleet-worktree-claimed": "worktree is held by a live biffo-fleet worktree-claim lock",
|
|
15219
15251
|
"pr-open": "PR is still open",
|
|
15220
15252
|
"pr-closed": "PR closed unmerged",
|
|
15221
15253
|
"no-pr": "no PR was ever opened from this branch",
|