gutterpress 0.10.0 → 0.10.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -16
- package/dist/api/index.d.ts +10 -19
- package/dist/api/index.js +8 -64
- package/dist/{audit-cvarpa72.js → audit-7a37g51p.js} +5 -5
- package/dist/{build-6r502chw.js → build-kdaet3pd.js} +5 -5
- package/dist/checks/source/index.d.ts +1 -0
- package/dist/checks/source/merge-markers.d.ts +3 -0
- package/dist/{cli-zfcryxg8.js → cli-ak1tagkr.js} +94 -57
- package/dist/{cli-eq5naw4m.js → cli-df7gcyns.js} +370 -1249
- package/dist/{cli-149edp6b.js → cli-dx6sxj2t.js} +1 -1
- package/dist/{cli-cqtggsng.js → cli-mcb484g3.js} +2 -47
- package/dist/{cli-k1065rkg.js → cli-w692g6dx.js} +75 -29
- package/dist/cli.js +14 -15
- package/dist/{doctor-akvxbtjb.js → doctor-vajd5h45.js} +2 -2
- package/dist/{engine-b159tbns.js → engine-0nt35svz.js} +2 -2
- package/dist/{engine-ft4cr3ep.js → engine-gkcqdye5.js} +1 -1
- package/dist/{gutterpress-viewer-te8g5grx.js → gutterpress-viewer-tma1qwz2.js} +57 -15
- package/dist/{index-ge7q9xj3.js → index-6g72h2n1.js} +771 -1482
- package/dist/{index-ycpvr0am.js → index-b2rqw41a.js} +1 -1
- package/dist/{index-mdefp0y5.js → index-dtrftayr.js} +75 -27
- package/dist/{index-wq3r5pj7.js → index-kvgq4q3q.js} +94 -57
- package/dist/index.js +9 -65
- package/dist/lib/git-fs.d.ts +43 -0
- package/dist/lib/host-policy.d.ts +14 -2
- package/dist/lib/remote-auth/clone.d.ts +0 -21
- package/dist/lib/remote-auth/converge-merge.d.ts +24 -7
- package/dist/lib/remote-auth/generic-auth.d.ts +0 -22
- package/dist/lib/remote-auth/git-http.d.ts +1 -1
- package/dist/lib/remote-auth/github-auth.d.ts +2 -22
- package/dist/lib/remote-auth/operation-log.d.ts +4 -9
- package/dist/lib/remote-auth/sync-messages.d.ts +35 -12
- package/dist/lib/remote-auth/sync-types.d.ts +30 -101
- package/dist/lib/remote-auth/sync.d.ts +19 -21
- package/dist/lib/remote-auth/token-store.d.ts +0 -10
- package/dist/lib/remote-auth/transport.d.ts +42 -40
- package/dist/lib/source-provider.d.ts +12 -0
- package/dist/{lint-p2sw53d9.js → lint-p6a4bkvh.js} +5 -5
- package/dist/{new-hvq0x91q.js → new-4cdzfbsj.js} +5 -5
- package/dist/{plugin-pssmk0dx.js → plugin-a89tqspy.js} +5 -5
- package/dist/{preflight-4j00yd0g.js → preflight-r4y3f8f9.js} +5 -5
- package/dist/{preview-d4s6gk6p.js → preview-k8n2kew7.js} +5 -5
- package/dist/{publish-tkc26en7.js → publish-jnhjp2vd.js} +5 -5
- package/dist/{source-provider-3tcj6qg2.js → source-provider-2j5x2hyw.js} +1 -1
- package/dist/{source-provider-vanafrt9.js → source-provider-kn41jmbs.js} +1 -1
- package/dist/{validate-w9vfefrw.js → validate-prnybpkx.js} +5 -5
- package/package.json +1 -1
- package/dist/lib/app-heartbeat.d.ts +0 -102
- package/dist/lib/remote-auth/image-clash.d.ts +0 -17
- package/dist/lib/remote-auth/recovery/classify.d.ts +0 -97
- package/dist/lib/remote-auth/recovery/inspect.d.ts +0 -75
- package/dist/lib/remote-auth/recovery/locks.d.ts +0 -20
- package/dist/lib/remote-auth/recovery/repair.d.ts +0 -29
- package/dist/lib/remote-auth/recovery/types.d.ts +0 -39
- package/dist/repair-2va4w12t.js +0 -137
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Preflight repo health probe for the sync-recovery subsystem.
|
|
3
|
-
*
|
|
4
|
-
* inspectRepo() reads local filesystem state ONLY — no network, no git objects,
|
|
5
|
-
* never throws. It returns a RepoHealth snapshot that the classifier and policy
|
|
6
|
-
* lookup use to decide which recovery path to take.
|
|
7
|
-
*
|
|
8
|
-
* Reuses:
|
|
9
|
-
* - gitDirFor (source-provider.ts) for the .git dir path
|
|
10
|
-
* - hasPendingChanges (source-provider.ts) for local-changes detection
|
|
11
|
-
*
|
|
12
|
-
* Notes on two health facts:
|
|
13
|
-
* - hasGitDir is true whenever `.git/` EXISTS, even with a missing/corrupt
|
|
14
|
-
* HEAD (a damaged repo is still a repo — see the inline note at the check).
|
|
15
|
-
* - hasStaleLock uses the lock sweep's OWN scanner
|
|
16
|
-
* (findLockCandidates in locks.ts) — one implementation, so
|
|
17
|
-
* health and handler can never disagree about which locks exist.
|
|
18
|
-
*
|
|
19
|
-
* All probes are best-effort and throw-free (the caller must never see an
|
|
20
|
-
* exception from a preflight probe).
|
|
21
|
-
*/
|
|
22
|
-
import type { LogData } from "../operation-log.ts";
|
|
23
|
-
import type { RepairNeed } from "./classify.ts";
|
|
24
|
-
import type { RepoHealth } from "./types.ts";
|
|
25
|
-
/**
|
|
26
|
-
* Probe the local repository and return a RepoHealth snapshot.
|
|
27
|
-
* Never throws — on any error the relevant flag is set conservatively.
|
|
28
|
-
*
|
|
29
|
-
* `checkLocalChanges: false` skips the hasPendingChanges working-tree walk
|
|
30
|
-
* (the one non-trivial probe) and reports hasLocalChanges=false. Use it when
|
|
31
|
-
* only the structural flags matter — e.g. syncProject's preflight, whose
|
|
32
|
-
* pull step immediately performs the same walk anyway (sync-simplicity
|
|
33
|
-
* mandate: no redundant walks on the hot path).
|
|
34
|
-
*/
|
|
35
|
-
export declare function inspectRepo(ctx: {
|
|
36
|
-
repoDir: string;
|
|
37
|
-
source?: import("../../project-source.ts").ProjectSource;
|
|
38
|
-
}, opts?: {
|
|
39
|
-
checkLocalChanges?: boolean;
|
|
40
|
-
}): Promise<RepoHealth>;
|
|
41
|
-
/**
|
|
42
|
-
* Confirm the repo's object store is actually readable: resolve HEAD, read
|
|
43
|
-
* its commit, and read its root tree. Throws when any step fails (missing or
|
|
44
|
-
* corrupt object/ref); resolves when the repo is fully readable.
|
|
45
|
-
*
|
|
46
|
-
* Exported so the repair
|
|
47
|
-
* command's diagnosis step and any host check share ONE implementation. `inspectRepo`'s health flags are
|
|
48
|
-
* all filesystem-presence checks (no object is ever read), so they cannot
|
|
49
|
-
* detect object-store corruption on their own — callers that need to catch
|
|
50
|
-
* unreadable objects/refs must run this probe and feed a caught error through
|
|
51
|
-
* `isLikelyRepoCorruption` (classify.ts) to decide whether to repairRepo().
|
|
52
|
-
*/
|
|
53
|
-
export declare function verifyRepoReadable(dir: string): Promise<void>;
|
|
54
|
-
/**
|
|
55
|
-
* True when HEAD names a branch that simply has no commits yet — a fresh
|
|
56
|
-
* `git init` before the first snapshot. In that state `verifyRepoReadable`
|
|
57
|
-
* throws the SAME NotFoundError as a damaged ref store, but the repo is
|
|
58
|
-
* healthy, not corrupt. The distinguishing signal is the object store: a
|
|
59
|
-
* fresh repo has NO objects at all, while ref damage on a real repo leaves
|
|
60
|
-
* loose objects and/or packfiles behind.
|
|
61
|
-
*/
|
|
62
|
-
export declare function isUnbornRepo(repoDir: string): boolean;
|
|
63
|
-
/**
|
|
64
|
-
* The SINGLE health signal that drove classification. Derived from the KIND
|
|
65
|
-
* classifyFromHealth returned (a pure mapping — it cannot drift from the
|
|
66
|
-
* classifier's decision order, because it never re-implements it).
|
|
67
|
-
*/
|
|
68
|
-
export declare function preflightStructuralReason(kind: RepairNeed | null): string;
|
|
69
|
-
/**
|
|
70
|
-
* Build a flat, secret-free record of the preflight decision inputs for the
|
|
71
|
-
* operation log. Every health boolean is recorded (so support can see the FULL
|
|
72
|
-
* picture, not just the one-word kind), plus the opened dir vs repo root, the
|
|
73
|
-
* chosen kind, and the single reason that drove it.
|
|
74
|
-
*/
|
|
75
|
-
export declare function buildPreflightDiagnostics(openedDir: string, repoDir: string, health: RepoHealth, kind: RepairNeed | null): LogData;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface LockCandidate {
|
|
2
|
-
/** Absolute path to the lock file. */
|
|
3
|
-
path: string;
|
|
4
|
-
/** Age in ms relative to `now` (now - mtime). */
|
|
5
|
-
ageMs: number;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Gather every candidate lock file (top-level + refs/**) with its age.
|
|
9
|
-
* Locks that vanish between discovery and stat are simply dropped (a racing
|
|
10
|
-
* delete is fine to ignore). Never throws.
|
|
11
|
-
*/
|
|
12
|
-
export declare function findLockCandidates(gitDir: string, now: number): Promise<LockCandidate[]>;
|
|
13
|
-
/**
|
|
14
|
-
* Delete every stale lock under `gitDir` — but ONLY when every candidate is
|
|
15
|
-
* stale (one fresh lock defers the whole sweep; a live process may hold it).
|
|
16
|
-
*
|
|
17
|
-
* Returns "clean" (nothing found), "swept" (all removed), or "fresh"
|
|
18
|
-
* (deferred — the caller should retry later).
|
|
19
|
-
*/
|
|
20
|
-
export declare function sweepStaleLocks(gitDir: string, now?: number, minAgeMs?: number): Promise<"clean" | "swept" | "fresh">;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { HostCredential, TokenStore } from "../token-store.ts";
|
|
2
|
-
export interface RepairOptions {
|
|
3
|
-
projectDir: string;
|
|
4
|
-
/** Explicit credential; wins over the token store (nuclear re-clone only). */
|
|
5
|
-
credential?: HostCredential;
|
|
6
|
-
/** Host-keyed store used to resolve the credential for the remote's host. */
|
|
7
|
-
tokenStore?: TokenStore;
|
|
8
|
-
authorName?: string;
|
|
9
|
-
authorEmail?: string;
|
|
10
|
-
/** Operation log (same file sync writes to). */
|
|
11
|
-
logFile?: string;
|
|
12
|
-
}
|
|
13
|
-
export interface RepairResult {
|
|
14
|
-
status: "repaired" | "retry_later" | "failed";
|
|
15
|
-
/** One author-language sentence describing the outcome. */
|
|
16
|
-
message: string;
|
|
17
|
-
/** Author-language lines describing what was done (for the log/details). */
|
|
18
|
-
actions: string[];
|
|
19
|
-
/** Present when the re-clone ran: on-disk backup of the old `.git`. */
|
|
20
|
-
damagedGitBackupPath?: string;
|
|
21
|
-
/** Suggested delay before retrying (present on "retry_later"). */
|
|
22
|
-
retryAfterMs?: number;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Repair a damaged repository. See the module header for the pipeline and
|
|
26
|
-
* invariants. Never throws for expected outcomes — everything is reported
|
|
27
|
-
* through {@link RepairResult}.
|
|
28
|
-
*/
|
|
29
|
-
export declare function repairRepo(options: RepairOptions): Promise<RepairResult>;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared types for the repo health probe + repair pipeline.
|
|
3
|
-
*
|
|
4
|
-
* 2026-08-14 simplification (owner directive): the old handler-dispatch type
|
|
5
|
-
* surface (SyncErrorKind taxonomy, RecoveryContext, RecoveryResult,
|
|
6
|
-
* ManualGuidance, confirmation gates, fault injection) is gone — repair is
|
|
7
|
-
* one automatic pipeline (repair.ts) and needs none of it. What remains is
|
|
8
|
-
* the health snapshot inspect.ts produces.
|
|
9
|
-
*/
|
|
10
|
-
export interface RepoHealth {
|
|
11
|
-
/** True when .git/ exists and looks like a valid git dir. */
|
|
12
|
-
hasGitDir: boolean;
|
|
13
|
-
/** Current branch name, or undefined when HEAD is detached. */
|
|
14
|
-
currentBranch?: string;
|
|
15
|
-
/** True when HEAD is detached (no named branch). */
|
|
16
|
-
isDetachedHead: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* True when HEAD (or the ref store) could not even be READ — distinct from
|
|
19
|
-
* a clean detached HEAD, where HEAD resolves fine but points at a commit
|
|
20
|
-
* instead of a branch. Routes to the re-clone step of repairRepo.
|
|
21
|
-
*/
|
|
22
|
-
headUnreadable: boolean;
|
|
23
|
-
/**
|
|
24
|
-
* True when a leftover git lock file exists (a previous operation may have
|
|
25
|
-
* died). Detects any of index.lock, HEAD.lock, config.lock, packed-refs.lock,
|
|
26
|
-
* or a per-ref refs/**\/*.lock — the same set the lock sweep scans.
|
|
27
|
-
*/
|
|
28
|
-
hasStaleLock: boolean;
|
|
29
|
-
/** How old the YOUNGEST detected lock file is in milliseconds, when present. */
|
|
30
|
-
lockAgeMs?: number;
|
|
31
|
-
/** True when a MERGE_HEAD file exists (interrupted merge). */
|
|
32
|
-
hasInterruptedMerge: boolean;
|
|
33
|
-
/** True when a rebase-in-progress directory exists. */
|
|
34
|
-
hasInterruptedRebase: boolean;
|
|
35
|
-
/** True when CHERRY_PICK_HEAD exists. */
|
|
36
|
-
hasInterruptedCherryPick: boolean;
|
|
37
|
-
/** True when the working tree has uncommitted changes. */
|
|
38
|
-
hasLocalChanges: boolean;
|
|
39
|
-
}
|
package/dist/repair-2va4w12t.js
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
classifyFromHealth,
|
|
3
|
-
inspectRepo,
|
|
4
|
-
isAppHeartbeatFresh,
|
|
5
|
-
isUnbornRepo,
|
|
6
|
-
repairRepo,
|
|
7
|
-
verifyRepoReadable
|
|
8
|
-
} from "./cli-eq5naw4m.js";
|
|
9
|
-
import {
|
|
10
|
-
FileTokenStore,
|
|
11
|
-
defaultConfigDir
|
|
12
|
-
} from "./cli-cqtggsng.js";
|
|
13
|
-
import {
|
|
14
|
-
UsageError,
|
|
15
|
-
rejectExtraPositionals,
|
|
16
|
-
rejectUnknownFlags
|
|
17
|
-
} from "./cli-149edp6b.js";
|
|
18
|
-
import"./cli-zfcryxg8.js";
|
|
19
|
-
import"./cli-c41yr7he.js";
|
|
20
|
-
import"./cli-46ycxe6r.js";
|
|
21
|
-
import"./cli-k1065rkg.js";
|
|
22
|
-
import"./cli-v5mp7a6q.js";
|
|
23
|
-
import"./cli-37x76zdn.js";
|
|
24
|
-
|
|
25
|
-
// src/commands/repair.ts
|
|
26
|
-
import { defineCommand } from "citty";
|
|
27
|
-
import * as readline from "node:readline/promises";
|
|
28
|
-
import path from "node:path";
|
|
29
|
-
async function promptYesNo(question) {
|
|
30
|
-
if (!process.stdin.isTTY)
|
|
31
|
-
return false;
|
|
32
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
33
|
-
try {
|
|
34
|
-
const answer = (await rl.question(`${question} [y/N] `)).trim().toLowerCase();
|
|
35
|
-
return answer === "y" || answer === "yes";
|
|
36
|
-
} finally {
|
|
37
|
-
rl.close();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
var commandArgs = {
|
|
41
|
-
dir: {
|
|
42
|
-
type: "positional",
|
|
43
|
-
description: "Project directory (defaults to the current directory)",
|
|
44
|
-
required: false
|
|
45
|
-
},
|
|
46
|
-
check: {
|
|
47
|
-
type: "boolean",
|
|
48
|
-
description: "Diagnose only — never change anything (exit 1 when repair is needed)",
|
|
49
|
-
default: false
|
|
50
|
-
},
|
|
51
|
-
yes: {
|
|
52
|
-
type: "boolean",
|
|
53
|
-
description: "Approve the repair without prompting",
|
|
54
|
-
default: false
|
|
55
|
-
},
|
|
56
|
-
force: {
|
|
57
|
-
type: "boolean",
|
|
58
|
-
description: "Repair even if the Gutterpress app appears to have this project open",
|
|
59
|
-
default: false
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
var repair_default = defineCommand({
|
|
63
|
-
meta: {
|
|
64
|
-
name: "repair",
|
|
65
|
-
description: "Diagnose and repair the project's version history"
|
|
66
|
-
},
|
|
67
|
-
args: commandArgs,
|
|
68
|
-
async run({ args, rawArgs }) {
|
|
69
|
-
try {
|
|
70
|
-
rejectUnknownFlags(rawArgs, commandArgs, "repair");
|
|
71
|
-
rejectExtraPositionals(args._, 1, "repair");
|
|
72
|
-
} catch (error) {
|
|
73
|
-
if (error instanceof UsageError) {
|
|
74
|
-
console.error(error.message);
|
|
75
|
-
process.exitCode = error.exitCode;
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
throw error;
|
|
79
|
-
}
|
|
80
|
-
const openedDir = path.resolve(args.dir ?? ".");
|
|
81
|
-
const health = await inspectRepo({ repoDir: openedDir });
|
|
82
|
-
let needsRepair = classifyFromHealth(health, { minLockAgeMs: 0 }) !== null;
|
|
83
|
-
if (!needsRepair && health.hasGitDir) {
|
|
84
|
-
try {
|
|
85
|
-
await verifyRepoReadable(openedDir);
|
|
86
|
-
} catch {
|
|
87
|
-
if (!isUnbornRepo(openedDir))
|
|
88
|
-
needsRepair = true;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (!health.hasGitDir)
|
|
92
|
-
needsRepair = true;
|
|
93
|
-
if (!needsRepair) {
|
|
94
|
-
console.log("Your project's version history looks healthy. Nothing to repair.");
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
console.log("Found a problem with this project's version history.");
|
|
98
|
-
if (args.check) {
|
|
99
|
-
console.log("\nRun `gutterpress repair` to fix it. Your files will not be changed.");
|
|
100
|
-
process.exitCode = 1;
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (!args.force && await isAppHeartbeatFresh(openedDir)) {
|
|
104
|
-
console.log(`
|
|
105
|
-
The Gutterpress app appears to have this project open. Close it first, or re-run with --force.`);
|
|
106
|
-
process.exitCode = 1;
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
if (!args.yes) {
|
|
110
|
-
console.log(`
|
|
111
|
-
The repair never changes your project files. If history has to be rebuilt,
|
|
112
|
-
` + `the old history folder is kept on disk as a backup and your saved versions
|
|
113
|
-
` + "are brought back into it wherever they are still readable.");
|
|
114
|
-
if (!await promptYesNo("Repair now?")) {
|
|
115
|
-
console.log("Nothing was changed.");
|
|
116
|
-
process.exitCode = 1;
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
const result = await repairRepo({
|
|
121
|
-
projectDir: openedDir,
|
|
122
|
-
tokenStore: new FileTokenStore(defaultConfigDir())
|
|
123
|
-
});
|
|
124
|
-
console.log(`
|
|
125
|
-
${result.message}`);
|
|
126
|
-
for (const action of result.actions)
|
|
127
|
-
console.log(` - ${action}`);
|
|
128
|
-
if (result.damagedGitBackupPath) {
|
|
129
|
-
console.log(` - Old history kept at: ${result.damagedGitBackupPath}`);
|
|
130
|
-
}
|
|
131
|
-
if (result.status !== "repaired")
|
|
132
|
-
process.exitCode = 1;
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
export {
|
|
136
|
-
repair_default as default
|
|
137
|
-
};
|