@diegopetrucci/pi-git-footer 0.1.2 → 0.1.4
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/.pi-fleet-tested-version +1 -1
- package/index.ts +42 -14
- package/package.json +5 -1
package/.pi-fleet-tested-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.80.6
|
package/index.ts
CHANGED
|
@@ -31,6 +31,11 @@ type CommandRunner = (
|
|
|
31
31
|
options: { cwd: string; signal: AbortSignal },
|
|
32
32
|
) => Promise<CommandResult>;
|
|
33
33
|
|
|
34
|
+
type RunCommandSafelyResult =
|
|
35
|
+
| { kind: "ok"; result: CommandResult }
|
|
36
|
+
| { kind: "transient" }
|
|
37
|
+
| { kind: "unavailable" };
|
|
38
|
+
|
|
34
39
|
type TimerHandle = unknown;
|
|
35
40
|
|
|
36
41
|
type Clock = {
|
|
@@ -286,6 +291,10 @@ function defaultClock(): Clock {
|
|
|
286
291
|
};
|
|
287
292
|
}
|
|
288
293
|
|
|
294
|
+
function isCommandUnavailableError(error: unknown): boolean {
|
|
295
|
+
return !!error && typeof error === "object" && (error as { code?: unknown }).code === "ENOENT";
|
|
296
|
+
}
|
|
297
|
+
|
|
289
298
|
class GitFooterCache {
|
|
290
299
|
private readonly cwd: () => string;
|
|
291
300
|
private readonly runner: CommandRunner;
|
|
@@ -345,7 +354,7 @@ class GitFooterCache {
|
|
|
345
354
|
const result = await this.fetchGitStatus();
|
|
346
355
|
if (this.disposed) return;
|
|
347
356
|
if (result.kind === "transient") return;
|
|
348
|
-
if (result.kind === "not-a-repo") {
|
|
357
|
+
if (result.kind === "not-a-repo" || result.kind === "unavailable") {
|
|
349
358
|
this.statusSnapshot = undefined;
|
|
350
359
|
this.pullRequestSnapshot = undefined;
|
|
351
360
|
this.lastSeenBranch = undefined;
|
|
@@ -371,8 +380,8 @@ class GitFooterCache {
|
|
|
371
380
|
|
|
372
381
|
const pr = await this.fetchPullRequest();
|
|
373
382
|
if (this.disposed) return;
|
|
374
|
-
if (pr
|
|
375
|
-
else if (
|
|
383
|
+
if (pr.kind === "ok") this.pullRequestSnapshot = pr.pullRequest;
|
|
384
|
+
else if (pr.kind === "not-found" || pr.kind === "unavailable") this.pullRequestSnapshot = undefined;
|
|
376
385
|
|
|
377
386
|
this.emitChangeIfSnapshotsChanged(previousStatusSnapshot, previousPullRequestSnapshot);
|
|
378
387
|
}
|
|
@@ -399,32 +408,40 @@ class GitFooterCache {
|
|
|
399
408
|
| { kind: "ok"; status: GitStatusSnapshot }
|
|
400
409
|
| { kind: "not-a-repo" }
|
|
401
410
|
| { kind: "transient" }
|
|
411
|
+
| { kind: "unavailable" }
|
|
402
412
|
> {
|
|
403
413
|
const result = await this.runCommandSafely("git", GIT_STATUS_ARGS, this.gitTimeoutMs);
|
|
404
|
-
if (
|
|
405
|
-
if (result.exitCode !== 0) return { kind: "not-a-repo" };
|
|
406
|
-
return { kind: "ok", status: parseGitStatusPorcelainV2(result.stdout) };
|
|
414
|
+
if (result.kind !== "ok") return result;
|
|
415
|
+
if (result.result.exitCode !== 0) return { kind: "not-a-repo" };
|
|
416
|
+
return { kind: "ok", status: parseGitStatusPorcelainV2(result.result.stdout) };
|
|
407
417
|
}
|
|
408
418
|
|
|
409
|
-
private async fetchPullRequest(): Promise<
|
|
419
|
+
private async fetchPullRequest(): Promise<
|
|
420
|
+
| { kind: "ok"; pullRequest: PullRequestSnapshot | undefined }
|
|
421
|
+
| { kind: "not-found" }
|
|
422
|
+
| { kind: "transient" }
|
|
423
|
+
| { kind: "unavailable" }
|
|
424
|
+
> {
|
|
410
425
|
const result = await this.runCommandSafely("gh", GH_PR_VIEW_ARGS, this.ghTimeoutMs);
|
|
411
|
-
if (
|
|
412
|
-
|
|
426
|
+
if (result.kind !== "ok") return result;
|
|
427
|
+
if (result.result.exitCode !== 0) return { kind: "not-found" };
|
|
428
|
+
return { kind: "ok", pullRequest: parsePullRequestJson(result.result.stdout) };
|
|
413
429
|
}
|
|
414
430
|
|
|
415
431
|
private async runCommandSafely(
|
|
416
432
|
command: string,
|
|
417
433
|
args: readonly string[],
|
|
418
434
|
timeoutMs: number,
|
|
419
|
-
): Promise<
|
|
420
|
-
if (this.disposed) return
|
|
435
|
+
): Promise<RunCommandSafelyResult> {
|
|
436
|
+
if (this.disposed) return { kind: "transient" };
|
|
421
437
|
const controller = new AbortController();
|
|
422
438
|
this.inflightControllers.add(controller);
|
|
423
439
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
424
440
|
try {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
441
|
+
const result = await this.runner(command, args, { cwd: this.cwd(), signal: controller.signal });
|
|
442
|
+
return { kind: "ok", result };
|
|
443
|
+
} catch (error) {
|
|
444
|
+
return isCommandUnavailableError(error) ? { kind: "unavailable" } : { kind: "transient" };
|
|
428
445
|
} finally {
|
|
429
446
|
clearTimeout(timeoutId);
|
|
430
447
|
this.inflightControllers.delete(controller);
|
|
@@ -478,3 +495,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
478
495
|
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
479
496
|
});
|
|
480
497
|
}
|
|
498
|
+
|
|
499
|
+
export const __testing = {
|
|
500
|
+
GitFooterCache,
|
|
501
|
+
GIT_STATUS_ARGS,
|
|
502
|
+
GH_PR_VIEW_ARGS,
|
|
503
|
+
parseGitStatusPorcelainV2,
|
|
504
|
+
parsePullRequestJson,
|
|
505
|
+
formatGitStatusFooterSegment,
|
|
506
|
+
formatPullRequestFooterSegment,
|
|
507
|
+
formatGitFooterStatus,
|
|
508
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diegopetrucci/pi-git-footer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "A TLH-style git status add-on for pi's built-in footer.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -31,5 +31,9 @@
|
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"@earendil-works/pi-coding-agent": "*",
|
|
33
33
|
"@earendil-works/pi-tui": "*"
|
|
34
|
+
},
|
|
35
|
+
"type": "module",
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=22.19.0"
|
|
34
38
|
}
|
|
35
39
|
}
|