@procedures/git 0.0.0-stage → 0.2.0
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/CHANGELOG.md +35 -0
- package/LICENSE +21 -0
- package/README.md +1130 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +22 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +514 -0
- package/dist/module.js.map +1 -0
- package/dist/procedures/git/add.d.ts +12 -0
- package/dist/procedures/git/add.d.ts.map +1 -0
- package/dist/procedures/git/add.js +26 -0
- package/dist/procedures/git/add.js.map +1 -0
- package/dist/procedures/git/args.d.ts +15 -0
- package/dist/procedures/git/args.d.ts.map +1 -0
- package/dist/procedures/git/args.js +20 -0
- package/dist/procedures/git/args.js.map +1 -0
- package/dist/procedures/git/branch.d.ts +12 -0
- package/dist/procedures/git/branch.d.ts.map +1 -0
- package/dist/procedures/git/branch.js +54 -0
- package/dist/procedures/git/branch.js.map +1 -0
- package/dist/procedures/git/checkout.d.ts +12 -0
- package/dist/procedures/git/checkout.d.ts.map +1 -0
- package/dist/procedures/git/checkout.js +23 -0
- package/dist/procedures/git/checkout.js.map +1 -0
- package/dist/procedures/git/clone.d.ts +12 -0
- package/dist/procedures/git/clone.d.ts.map +1 -0
- package/dist/procedures/git/clone.js +28 -0
- package/dist/procedures/git/clone.js.map +1 -0
- package/dist/procedures/git/commit.d.ts +12 -0
- package/dist/procedures/git/commit.d.ts.map +1 -0
- package/dist/procedures/git/commit.js +41 -0
- package/dist/procedures/git/commit.js.map +1 -0
- package/dist/procedures/git/diff.d.ts +18 -0
- package/dist/procedures/git/diff.d.ts.map +1 -0
- package/dist/procedures/git/diff.js +58 -0
- package/dist/procedures/git/diff.js.map +1 -0
- package/dist/procedures/git/fetch.d.ts +12 -0
- package/dist/procedures/git/fetch.d.ts.map +1 -0
- package/dist/procedures/git/fetch.js +29 -0
- package/dist/procedures/git/fetch.js.map +1 -0
- package/dist/procedures/git/index.d.ts +15 -0
- package/dist/procedures/git/index.d.ts.map +1 -0
- package/dist/procedures/git/index.js +15 -0
- package/dist/procedures/git/index.js.map +1 -0
- package/dist/procedures/git/init.d.ts +12 -0
- package/dist/procedures/git/init.d.ts.map +1 -0
- package/dist/procedures/git/init.js +32 -0
- package/dist/procedures/git/init.js.map +1 -0
- package/dist/procedures/git/log.d.ts +12 -0
- package/dist/procedures/git/log.d.ts.map +1 -0
- package/dist/procedures/git/log.js +35 -0
- package/dist/procedures/git/log.js.map +1 -0
- package/dist/procedures/git/predicates.d.ts +40 -0
- package/dist/procedures/git/predicates.d.ts.map +1 -0
- package/dist/procedures/git/predicates.js +76 -0
- package/dist/procedures/git/predicates.js.map +1 -0
- package/dist/procedures/git/pull.d.ts +12 -0
- package/dist/procedures/git/pull.d.ts.map +1 -0
- package/dist/procedures/git/pull.js +36 -0
- package/dist/procedures/git/pull.js.map +1 -0
- package/dist/procedures/git/push.d.ts +12 -0
- package/dist/procedures/git/push.d.ts.map +1 -0
- package/dist/procedures/git/push.js +39 -0
- package/dist/procedures/git/push.js.map +1 -0
- package/dist/procedures/git/remote.d.ts +13 -0
- package/dist/procedures/git/remote.d.ts.map +1 -0
- package/dist/procedures/git/remote.js +30 -0
- package/dist/procedures/git/remote.js.map +1 -0
- package/dist/procedures/git/run.d.ts +32 -0
- package/dist/procedures/git/run.d.ts.map +1 -0
- package/dist/procedures/git/run.js +60 -0
- package/dist/procedures/git/run.js.map +1 -0
- package/dist/procedures/git/stash.d.ts +38 -0
- package/dist/procedures/git/stash.d.ts.map +1 -0
- package/dist/procedures/git/stash.js +211 -0
- package/dist/procedures/git/stash.js.map +1 -0
- package/dist/procedures/git/status.d.ts +17 -0
- package/dist/procedures/git/status.d.ts.map +1 -0
- package/dist/procedures/git/status.js +107 -0
- package/dist/procedures/git/status.js.map +1 -0
- package/dist/procedures/git.d.ts +5 -0
- package/dist/procedures/git.d.ts.map +1 -0
- package/dist/procedures/git.js +5 -0
- package/dist/procedures/git.js.map +1 -0
- package/dist/register.d.ts +7 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +9 -0
- package/dist/register.js.map +1 -0
- package/dist/types.d.ts +350 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +397 -0
- package/dist/types.js.map +1 -0
- package/package.json +77 -3
- package/src/index.ts +20 -0
- package/src/module.ts +656 -0
- package/src/procedures/git/add.ts +29 -0
- package/src/procedures/git/args.ts +21 -0
- package/src/procedures/git/branch.ts +61 -0
- package/src/procedures/git/checkout.ts +27 -0
- package/src/procedures/git/clone.ts +33 -0
- package/src/procedures/git/commit.ts +46 -0
- package/src/procedures/git/diff.ts +62 -0
- package/src/procedures/git/fetch.ts +32 -0
- package/src/procedures/git/index.ts +22 -0
- package/src/procedures/git/init.ts +43 -0
- package/src/procedures/git/log.ts +40 -0
- package/src/procedures/git/predicates.ts +90 -0
- package/src/procedures/git/pull.ts +45 -0
- package/src/procedures/git/push.ts +42 -0
- package/src/procedures/git/remote.ts +31 -0
- package/src/procedures/git/run.ts +70 -0
- package/src/procedures/git/stash.ts +255 -0
- package/src/procedures/git/status.ts +98 -0
- package/src/procedures/git.ts +5 -0
- package/src/register.ts +11 -0
- package/src/types.ts +815 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* git.stash.* procedures
|
|
3
|
+
*
|
|
4
|
+
* Stash operations for saving and restoring work in progress.
|
|
5
|
+
* Includes export/import for snapshot storage.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { gitArg } from "./args.js";
|
|
9
|
+
import { git, GitError, type GitContext } from "./run.js";
|
|
10
|
+
import type {
|
|
11
|
+
GitStashListInput,
|
|
12
|
+
GitStashListOutput,
|
|
13
|
+
GitStashPushInput,
|
|
14
|
+
GitStashPushOutput,
|
|
15
|
+
GitStashPopInput,
|
|
16
|
+
GitStashPopOutput,
|
|
17
|
+
GitStashApplyInput,
|
|
18
|
+
GitStashApplyOutput,
|
|
19
|
+
GitStashDropInput,
|
|
20
|
+
GitStashDropOutput,
|
|
21
|
+
GitStashExportInput,
|
|
22
|
+
GitStashExportOutput,
|
|
23
|
+
GitStashImportInput,
|
|
24
|
+
GitStashImportOutput,
|
|
25
|
+
GitStashEntry,
|
|
26
|
+
} from "../../types.js";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* True when git stopped on a merge conflict. Git writes "CONFLICT (content): ..." to stdout,
|
|
30
|
+
* so the message alone (which has stderr) does not show it. (Before, the procedures examined
|
|
31
|
+
* only the message, and never reported a conflict.)
|
|
32
|
+
*/
|
|
33
|
+
function isConflict(error: unknown): boolean {
|
|
34
|
+
return error instanceof GitError && /conflict/i.test(`${error.stdout}\n${error.stderr}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The message of a git failure. An abort is not a git failure: it throws again. */
|
|
38
|
+
function failure(error: unknown): string {
|
|
39
|
+
if (!(error instanceof GitError)) throw error;
|
|
40
|
+
return error.message;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function stashRef(index: number | undefined): string {
|
|
44
|
+
return index !== undefined ? `stash@{${index}}` : "stash@{0}";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* List all stashes
|
|
49
|
+
*/
|
|
50
|
+
export async function gitStashList(input: GitStashListInput, ctx: GitContext = {}): Promise<GitStashListOutput> {
|
|
51
|
+
const cwd = input.cwd || process.cwd();
|
|
52
|
+
|
|
53
|
+
let output: string;
|
|
54
|
+
try {
|
|
55
|
+
// Get stash list with format: stash@{n}: WIP on branch: message
|
|
56
|
+
output = await git(["stash", "list", "--format=%H%x00%gd%x00%gs"], { cwd, signal: ctx.signal });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
// No stashes or not a git repo
|
|
59
|
+
failure(error);
|
|
60
|
+
return { stashes: [], count: 0 };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const stashes: GitStashEntry[] = [];
|
|
64
|
+
for (const line of output.split("\n").filter(Boolean)) {
|
|
65
|
+
const parts = line.split("\0");
|
|
66
|
+
const hash = parts[0] || "";
|
|
67
|
+
const ref = parts[1] || "";
|
|
68
|
+
const message = parts[2] || "";
|
|
69
|
+
// Extract index from stash@{n}
|
|
70
|
+
const indexMatch = ref.match(/stash@\{(\d+)\}/);
|
|
71
|
+
const index = indexMatch && indexMatch[1] ? parseInt(indexMatch[1], 10) : 0;
|
|
72
|
+
|
|
73
|
+
stashes.push({
|
|
74
|
+
index,
|
|
75
|
+
ref,
|
|
76
|
+
hash,
|
|
77
|
+
message,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return { stashes, count: stashes.length };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Push changes to stash
|
|
86
|
+
*/
|
|
87
|
+
export async function gitStashPush(input: GitStashPushInput, ctx: GitContext = {}): Promise<GitStashPushOutput> {
|
|
88
|
+
const cwd = input.cwd || process.cwd();
|
|
89
|
+
const run = { cwd, signal: ctx.signal };
|
|
90
|
+
|
|
91
|
+
const args: string[] = ["stash", "push"];
|
|
92
|
+
|
|
93
|
+
if (input.message) {
|
|
94
|
+
args.push("-m", input.message);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (input.includeUntracked) {
|
|
98
|
+
args.push("--include-untracked");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (input.keepIndex) {
|
|
102
|
+
args.push("--keep-index");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (input.paths && input.paths.length > 0) {
|
|
106
|
+
args.push("--");
|
|
107
|
+
args.push(...input.paths);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const output = await git(args, run);
|
|
112
|
+
|
|
113
|
+
// Check if anything was stashed
|
|
114
|
+
if (output.includes("No local changes to save")) {
|
|
115
|
+
return { stashed: false, message: "No local changes to save" };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Get the ref of the new stash
|
|
119
|
+
const refOutput = (await git(["stash", "list", "-1", "--format=%gd"], run)).trim();
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
stashed: true,
|
|
123
|
+
ref: refOutput || "stash@{0}",
|
|
124
|
+
message: input.message || "WIP",
|
|
125
|
+
};
|
|
126
|
+
} catch (error) {
|
|
127
|
+
return { stashed: false, message: failure(error) || "Failed to stash" };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Pop stash (apply and remove)
|
|
133
|
+
*/
|
|
134
|
+
export async function gitStashPop(input: GitStashPopInput, ctx: GitContext = {}): Promise<GitStashPopOutput> {
|
|
135
|
+
const cwd = input.cwd || process.cwd();
|
|
136
|
+
const ref = stashRef(input.index);
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
await git(["stash", "pop", gitArg("ref", ref)], { cwd, signal: ctx.signal });
|
|
140
|
+
return { applied: true, ref, dropped: true };
|
|
141
|
+
} catch (error) {
|
|
142
|
+
// Check if it's a conflict
|
|
143
|
+
if (isConflict(error)) {
|
|
144
|
+
return { applied: false, ref, dropped: false, conflict: true };
|
|
145
|
+
}
|
|
146
|
+
failure(error);
|
|
147
|
+
return { applied: false, ref, dropped: false };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Apply stash without removing
|
|
153
|
+
*/
|
|
154
|
+
export async function gitStashApply(input: GitStashApplyInput, ctx: GitContext = {}): Promise<GitStashApplyOutput> {
|
|
155
|
+
const cwd = input.cwd || process.cwd();
|
|
156
|
+
const ref = stashRef(input.index);
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
await git(["stash", "apply", gitArg("ref", ref)], { cwd, signal: ctx.signal });
|
|
160
|
+
return { applied: true, ref };
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (isConflict(error)) {
|
|
163
|
+
return { applied: false, ref, conflict: true };
|
|
164
|
+
}
|
|
165
|
+
failure(error);
|
|
166
|
+
return { applied: false, ref };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Drop a stash
|
|
172
|
+
*/
|
|
173
|
+
export async function gitStashDrop(input: GitStashDropInput, ctx: GitContext = {}): Promise<GitStashDropOutput> {
|
|
174
|
+
const cwd = input.cwd || process.cwd();
|
|
175
|
+
const ref = stashRef(input.index);
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
await git(["stash", "drop", gitArg("ref", ref)], { cwd, signal: ctx.signal });
|
|
179
|
+
return { dropped: true, ref };
|
|
180
|
+
} catch (error) {
|
|
181
|
+
failure(error);
|
|
182
|
+
return { dropped: false, ref };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Export a stash as a patch (for snapshot storage)
|
|
188
|
+
*/
|
|
189
|
+
export async function gitStashExport(input: GitStashExportInput, ctx: GitContext = {}): Promise<GitStashExportOutput> {
|
|
190
|
+
const cwd = input.cwd || process.cwd();
|
|
191
|
+
const run = { cwd, signal: ctx.signal };
|
|
192
|
+
const ref = stashRef(input.index);
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
// Get the stash as a patch
|
|
196
|
+
const patch = await git(["stash", "show", "-p", gitArg("ref", ref)], run);
|
|
197
|
+
|
|
198
|
+
// Get metadata
|
|
199
|
+
const metadata = (await git(["stash", "list", "-1", "--format=%H%x00%gs", ref], run)).trim();
|
|
200
|
+
const metaParts = metadata.split("\0");
|
|
201
|
+
const hash = metaParts[0] || "";
|
|
202
|
+
const message = metaParts[1] || "";
|
|
203
|
+
|
|
204
|
+
// Get untracked files if present (stash^3 contains untracked files if any)
|
|
205
|
+
let untrackedPatch = "";
|
|
206
|
+
try {
|
|
207
|
+
untrackedPatch = await git(["show", `${ref}^3`, "--format=", "--name-only"], run);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
// No untracked files in this stash
|
|
210
|
+
failure(error);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
ref,
|
|
215
|
+
hash,
|
|
216
|
+
message,
|
|
217
|
+
patch,
|
|
218
|
+
hasUntracked: untrackedPatch.length > 0,
|
|
219
|
+
untrackedPatch: untrackedPatch || undefined,
|
|
220
|
+
};
|
|
221
|
+
} catch (error) {
|
|
222
|
+
throw new Error(`Failed to export stash ${ref}: ${failure(error)}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Import a stash from a patch (for snapshot restore)
|
|
228
|
+
* Note: This creates a new stash, it doesn't recreate the exact stash state
|
|
229
|
+
*/
|
|
230
|
+
export async function gitStashImport(input: GitStashImportInput, ctx: GitContext = {}): Promise<GitStashImportOutput> {
|
|
231
|
+
const cwd = input.cwd || process.cwd();
|
|
232
|
+
const run = { cwd, signal: ctx.signal };
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
// Apply the patch to working directory
|
|
236
|
+
await git(["apply", "--3way"], { ...run, input: input.patch });
|
|
237
|
+
|
|
238
|
+
// Stash the changes with the original message
|
|
239
|
+
const message = input.message || "Imported stash";
|
|
240
|
+
const args = ["stash", "push", "-m", message];
|
|
241
|
+
|
|
242
|
+
if (input.includeUntracked) {
|
|
243
|
+
args.push("--include-untracked");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
await git(args, run);
|
|
247
|
+
|
|
248
|
+
// Get the new stash ref
|
|
249
|
+
const ref = (await git(["stash", "list", "-1", "--format=%gd"], run)).trim();
|
|
250
|
+
|
|
251
|
+
return { imported: true, ref: ref || "stash@{0}" };
|
|
252
|
+
} catch (error) {
|
|
253
|
+
return { imported: false, error: failure(error) || "Failed to import stash" };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* git.status procedure
|
|
3
|
+
*
|
|
4
|
+
* Get git status
|
|
5
|
+
*
|
|
6
|
+
* One call of `git status --porcelain=v2 --branch -z` gives the branch, the ahead and behind
|
|
7
|
+
* counts and the files. With `-z`, git writes each path as it is: no quotes, and a rename gives
|
|
8
|
+
* its old path in a separate field (deep dive WRP-7). Before, the procedure read the quoted form,
|
|
9
|
+
* so a path with a space kept its quotes, and a rename gave the text "old -> new" as the path.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { git, zFields, type GitContext } from "./run.js";
|
|
13
|
+
import type { GitStatusInput, GitStatusOutput, GitStatusFile } from "../../types.js";
|
|
14
|
+
|
|
15
|
+
/** The status of one entry, from its two status letters (index, then work tree). */
|
|
16
|
+
function classify(xy: string): Pick<GitStatusFile, "status" | "staged"> {
|
|
17
|
+
const index = xy[0];
|
|
18
|
+
const worktree = xy[1];
|
|
19
|
+
if (index === "A") return { status: "added", staged: true };
|
|
20
|
+
if (index === "D") return { status: "deleted", staged: true };
|
|
21
|
+
if (index === "R") return { status: "renamed", staged: true };
|
|
22
|
+
if (index === "C") return { status: "copied", staged: true };
|
|
23
|
+
if (index === "M" || index === "T") return { status: "modified", staged: true };
|
|
24
|
+
if (worktree === "D") return { status: "deleted", staged: false };
|
|
25
|
+
if (worktree === "A") return { status: "added", staged: false };
|
|
26
|
+
if (worktree === "R") return { status: "renamed", staged: false };
|
|
27
|
+
return { status: "modified", staged: false };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The text after the first `count` space-separated fields of a line. */
|
|
31
|
+
function afterFields(line: string, count: number): string {
|
|
32
|
+
let at = 0;
|
|
33
|
+
for (let i = 0; i < count; i++) at = line.indexOf(" ", at) + 1;
|
|
34
|
+
return line.slice(at);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get git status
|
|
39
|
+
*/
|
|
40
|
+
export async function gitStatus(input: GitStatusInput, ctx: GitContext = {}): Promise<GitStatusOutput> {
|
|
41
|
+
const output = await git(["status", "--porcelain=v2", "--branch", "-z"], { cwd: input.cwd, signal: ctx.signal });
|
|
42
|
+
|
|
43
|
+
let branch = "HEAD";
|
|
44
|
+
let ahead = 0;
|
|
45
|
+
let behind = 0;
|
|
46
|
+
const files: GitStatusFile[] = [];
|
|
47
|
+
const lines: string[] = [];
|
|
48
|
+
|
|
49
|
+
const fields = zFields(output);
|
|
50
|
+
for (let i = 0; i < fields.length; i++) {
|
|
51
|
+
const field = fields[i]!;
|
|
52
|
+
if (field.startsWith("# branch.head ")) {
|
|
53
|
+
const head = field.slice("# branch.head ".length);
|
|
54
|
+
branch = head === "(detached)" ? "HEAD" : head;
|
|
55
|
+
} else if (field.startsWith("# branch.ab ")) {
|
|
56
|
+
const match = /\+(\d+) -(\d+)/.exec(field);
|
|
57
|
+
ahead = Number(match?.[1] ?? 0);
|
|
58
|
+
behind = Number(match?.[2] ?? 0);
|
|
59
|
+
} else if (field.startsWith("1 ")) {
|
|
60
|
+
// 1 XY sub mH mI mW hH hI path
|
|
61
|
+
const xy = field.slice(2, 4);
|
|
62
|
+
const path = afterFields(field, 8);
|
|
63
|
+
files.push({ path, ...classify(xy) });
|
|
64
|
+
lines.push(`${xy.replace(/\./g, " ")} ${path}`);
|
|
65
|
+
} else if (field.startsWith("2 ")) {
|
|
66
|
+
// 2 XY sub mH mI mW hH hI Xscore path, then the old path in the next field
|
|
67
|
+
const xy = field.slice(2, 4);
|
|
68
|
+
const path = afterFields(field, 9);
|
|
69
|
+
const from = fields[++i] ?? "";
|
|
70
|
+
files.push({ path, from, ...classify(xy) });
|
|
71
|
+
lines.push(`${xy.replace(/\./g, " ")} ${from} -> ${path}`);
|
|
72
|
+
} else if (field.startsWith("u ")) {
|
|
73
|
+
// An unmerged path: u XY sub m1 m2 m3 mW h1 h2 h3 path
|
|
74
|
+
const xy = field.slice(2, 4);
|
|
75
|
+
const path = afterFields(field, 10);
|
|
76
|
+
files.push({ path, status: "modified", staged: false });
|
|
77
|
+
lines.push(`${xy} ${path}`);
|
|
78
|
+
} else if (field.startsWith("? ")) {
|
|
79
|
+
const path = field.slice(2);
|
|
80
|
+
files.push({ path, status: "untracked", staged: false });
|
|
81
|
+
lines.push(`?? ${path}`);
|
|
82
|
+
} else if (field.startsWith("! ")) {
|
|
83
|
+
const path = field.slice(2);
|
|
84
|
+
files.push({ path, status: "ignored", staged: false });
|
|
85
|
+
lines.push(`!! ${path}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const result: GitStatusOutput = {
|
|
90
|
+
branch,
|
|
91
|
+
ahead,
|
|
92
|
+
behind,
|
|
93
|
+
files,
|
|
94
|
+
clean: files.length === 0,
|
|
95
|
+
};
|
|
96
|
+
if (input.short) result.lines = lines;
|
|
97
|
+
return result;
|
|
98
|
+
}
|
package/src/register.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Importing this file registers the procedures of @procedures/git, and of the modules that it
|
|
3
|
+
* requires, in the global registry: `import "@procedures/git/register"`. The package root and the
|
|
4
|
+
* `./module` entry register nothing (ARCHITECTURE-PROPOSALS-2026-10, P9).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { registerGitProcedures } from "./module.js";
|
|
8
|
+
|
|
9
|
+
export * from "./module.js";
|
|
10
|
+
|
|
11
|
+
registerGitProcedures();
|