@spences10/pi-git-ui 0.0.1 → 0.0.2

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 CHANGED
@@ -17,13 +17,23 @@ Then run:
17
17
  Controls:
18
18
 
19
19
  - `↑`/`↓` or `j`/`k` — move file selection
20
+ - `/` — filter files by path, state, or status code
21
+ - `enter` — open contextual actions for the selected file
20
22
  - `←`/`→` or `h`/`l` — scroll the diff preview
23
+ - `n`/`p` — move between diff hunks
24
+ - `[`/`]` — move between changed lines
21
25
  - `space` — safely stage/unstage selected file; disabled for
22
26
  partial/conflicted files
23
27
  - `s` — stage selected file explicitly
24
28
  - `x` — unstage selected file explicitly
29
+ - `S` — stage selected hunk
30
+ - `X` — unstage selected hunk
31
+ - `+` — stage selected changed line
32
+ - `-` — unstage selected changed line
25
33
  - `c` — commit staged changes with a Conventional Commit helper or raw
26
34
  message
35
+ - `g` — show repository overview with branches, recent commits,
36
+ stashes, and remotes
27
37
  - `a` — safely stage all; blocked if partial/conflicted files exist
28
38
  - `A` — force stage all
29
39
  - `u` — unstage all
@@ -0,0 +1,2 @@
1
+ export declare function git(args: string[], cwd: string): Promise<string>;
2
+ export declare function git_with_input(args: string[], cwd: string, input: string): Promise<string>;
@@ -0,0 +1,35 @@
1
+ import { execFile, spawn } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ const exec_file = promisify(execFile);
4
+ export async function git(args, cwd) {
5
+ const { stdout } = await exec_file('git', args, {
6
+ cwd,
7
+ encoding: 'utf8',
8
+ maxBuffer: 1024 * 1024 * 8,
9
+ });
10
+ return stdout;
11
+ }
12
+ export async function git_with_input(args, cwd, input) {
13
+ return await new Promise((resolve, reject) => {
14
+ const child = spawn('git', args, { cwd, stdio: 'pipe' });
15
+ let stdout = '';
16
+ let stderr = '';
17
+ child.stdout.setEncoding('utf8');
18
+ child.stderr.setEncoding('utf8');
19
+ child.stdout.on('data', (chunk) => {
20
+ stdout += chunk;
21
+ });
22
+ child.stderr.on('data', (chunk) => {
23
+ stderr += chunk;
24
+ });
25
+ child.on('error', reject);
26
+ child.on('close', (code) => {
27
+ if (code === 0)
28
+ resolve(stdout);
29
+ else
30
+ reject(new Error(stderr || `git exited with status ${code}`));
31
+ });
32
+ child.stdin.end(input);
33
+ });
34
+ }
35
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/git/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,GAAG,CACxB,IAAc,EACd,GAAW;IAEX,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QAC/C,GAAG;QACH,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC;KAC1B,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,IAAc,EACd,GAAW,EACX,KAAa;IAEb,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzD,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,CAAC,MAAM,CAAC,CAAC;;gBAE/B,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,0BAA0B,IAAI,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { DiffHunk, DiffSection, DiffView, GitFile } from './types.js';
2
+ export declare function read_diff(cwd: string, file: GitFile): Promise<DiffView>;
3
+ export declare function parse_diff_hunks(raw: string, section: DiffSection): DiffHunk[];
4
+ export declare function changed_line_indexes(hunk: DiffHunk): number[];
5
+ export declare function stage_hunk(cwd: string, hunk: DiffHunk): Promise<void>;
6
+ export declare function unstage_hunk(cwd: string, hunk: DiffHunk): Promise<void>;
7
+ export declare function stage_line(cwd: string, hunk: DiffHunk, line_index: number): Promise<void>;
8
+ export declare function unstage_line(cwd: string, hunk: DiffHunk, line_index: number): Promise<void>;
9
+ export declare function build_line_patch(hunk: DiffHunk, line_index: number): string;
@@ -0,0 +1,150 @@
1
+ import { git, git_with_input } from './client.js';
2
+ import { format_git_error } from './errors.js';
3
+ import { git_path } from './operations.js';
4
+ export async function read_diff(cwd, file) {
5
+ const path = git_path(file);
6
+ if (file.state === 'untracked') {
7
+ return {
8
+ path: file.path,
9
+ lines: [
10
+ 'Untracked file',
11
+ '',
12
+ 'Press space or s to stage it.',
13
+ 'No diff is available until Git starts tracking the path.',
14
+ ],
15
+ hunks: [],
16
+ };
17
+ }
18
+ const lines = [];
19
+ const hunks = [];
20
+ const staged = await git(['diff', '--cached', '--', path], cwd).catch((error) => format_git_error(error));
21
+ const unstaged = await git(['diff', '--', path], cwd).catch((error) => format_git_error(error));
22
+ append_diff_section(lines, hunks, 'staged', staged);
23
+ if (staged.trim() && unstaged.trim())
24
+ lines.push('', '');
25
+ append_diff_section(lines, hunks, 'unstaged', unstaged);
26
+ if (lines.length === 0)
27
+ lines.push('No textual diff for this file.');
28
+ return { path: file.path, lines, hunks };
29
+ }
30
+ function append_diff_section(lines, hunks, section, raw) {
31
+ if (!raw.trim())
32
+ return;
33
+ lines.push(section.toUpperCase(), '');
34
+ const offset = lines.length;
35
+ const parsed = parse_diff_hunks(raw, section);
36
+ for (const hunk of parsed) {
37
+ hunks.push({ ...hunk, line_index: offset + hunk.line_index });
38
+ }
39
+ lines.push(...raw.split('\n'));
40
+ }
41
+ export function parse_diff_hunks(raw, section) {
42
+ const lines = raw.split('\n');
43
+ const hunks = [];
44
+ let file_header = [];
45
+ let current_hunk;
46
+ const flush_hunk = () => {
47
+ if (!current_hunk)
48
+ return;
49
+ hunks.push({
50
+ section,
51
+ line_index: current_hunk.start,
52
+ header: current_hunk.lines[0] ?? '@@',
53
+ patch: [...file_header, ...current_hunk.lines].join('\n'),
54
+ });
55
+ current_hunk = undefined;
56
+ };
57
+ for (let index = 0; index < lines.length; index++) {
58
+ const line = lines[index];
59
+ if (line.startsWith('diff --git ')) {
60
+ flush_hunk();
61
+ file_header = [line];
62
+ continue;
63
+ }
64
+ if (line.startsWith('@@')) {
65
+ flush_hunk();
66
+ current_hunk = { start: index, lines: [line] };
67
+ continue;
68
+ }
69
+ if (current_hunk)
70
+ current_hunk.lines.push(line);
71
+ else if (file_header.length > 0)
72
+ file_header.push(line);
73
+ }
74
+ flush_hunk();
75
+ return hunks;
76
+ }
77
+ export function changed_line_indexes(hunk) {
78
+ const lines = hunk.patch.split('\n');
79
+ const header_index = lines.findIndex((line) => line.startsWith('@@'));
80
+ if (header_index < 0)
81
+ return [];
82
+ return lines
83
+ .slice(header_index + 1)
84
+ .flatMap((line, index) => (line.startsWith('+') || line.startsWith('-')) &&
85
+ !line.startsWith('+++') &&
86
+ !line.startsWith('---')
87
+ ? [hunk.line_index + 1 + index]
88
+ : []);
89
+ }
90
+ export async function stage_hunk(cwd, hunk) {
91
+ if (hunk.section !== 'unstaged')
92
+ throw new Error('Selected hunk is already staged.');
93
+ await git_with_input(['apply', '--cached', '--whitespace=nowarn', '-'], cwd, `${hunk.patch}\n`);
94
+ }
95
+ export async function unstage_hunk(cwd, hunk) {
96
+ if (hunk.section !== 'staged')
97
+ throw new Error('Selected hunk is not staged.');
98
+ await git_with_input(['apply', '--cached', '--reverse', '--whitespace=nowarn', '-'], cwd, `${hunk.patch}\n`);
99
+ }
100
+ export async function stage_line(cwd, hunk, line_index) {
101
+ if (hunk.section !== 'unstaged')
102
+ throw new Error('Selected line is already staged.');
103
+ await git_with_input(['apply', '--cached', '--whitespace=nowarn', '-'], cwd, `${build_line_patch(hunk, line_index)}\n`);
104
+ }
105
+ export async function unstage_line(cwd, hunk, line_index) {
106
+ if (hunk.section !== 'staged')
107
+ throw new Error('Selected line is not staged.');
108
+ await git_with_input(['apply', '--cached', '--reverse', '--whitespace=nowarn', '-'], cwd, `${build_line_patch(hunk, line_index)}\n`);
109
+ }
110
+ export function build_line_patch(hunk, line_index) {
111
+ const lines = hunk.patch.split('\n');
112
+ const header_index = lines.findIndex((line) => line.startsWith('@@'));
113
+ if (header_index < 0)
114
+ throw new Error('Selected hunk has no header.');
115
+ const body_index = line_index - hunk.line_index - 1;
116
+ const body = lines.slice(header_index + 1);
117
+ const selected = body[body_index];
118
+ if (!selected ||
119
+ (!selected.startsWith('+') && !selected.startsWith('-'))) {
120
+ throw new Error('Selected line is not stageable.');
121
+ }
122
+ const next_body = body.flatMap((line, index) => {
123
+ if (index === body_index)
124
+ return [line];
125
+ if (line.startsWith('+'))
126
+ return [];
127
+ if (line.startsWith('-'))
128
+ return [` ${line.slice(1)}`];
129
+ return [line];
130
+ });
131
+ const header = rebuild_hunk_header(lines[header_index], next_body);
132
+ return [...lines.slice(0, header_index), header, ...next_body].join('\n');
133
+ }
134
+ function rebuild_hunk_header(header, body) {
135
+ const match = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@(.*)$/.exec(header);
136
+ if (!match)
137
+ return header;
138
+ let old_count = 0;
139
+ let new_count = 0;
140
+ for (const line of body) {
141
+ if (line.startsWith('\\'))
142
+ continue;
143
+ if (!line.startsWith('+'))
144
+ old_count++;
145
+ if (!line.startsWith('-'))
146
+ new_count++;
147
+ }
148
+ return `@@ -${match[1]},${old_count} +${match[2]},${new_count} @@${match[3]}`;
149
+ }
150
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/git/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function format_git_error(error: unknown): string;
@@ -0,0 +1,17 @@
1
+ export function format_git_error(error) {
2
+ const message = error instanceof Error ? error.message : String(error);
3
+ if (message.includes('No staged changes'))
4
+ return 'No staged changes to commit.';
5
+ if (message.includes('nothing to commit'))
6
+ return 'Nothing to commit.';
7
+ if (message.includes('patch does not apply')) {
8
+ return 'Hunk no longer applies. Refresh and try again.';
9
+ }
10
+ if (message.includes('CONFLICT')) {
11
+ return 'Git conflict detected. Resolve conflict markers, then stage the file.';
12
+ }
13
+ if (message.includes('not a git repository'))
14
+ return 'Not inside a Git repository.';
15
+ return message;
16
+ }
17
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/git/errors.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC9C,MAAM,OAAO,GACZ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACxC,OAAO,8BAA8B,CAAC;IACvC,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACxC,OAAO,oBAAoB,CAAC;IAC7B,IAAI,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;QAC9C,OAAO,gDAAgD,CAAC;IACzD,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,OAAO,uEAAuE,CAAC;IAChF,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAC3C,OAAO,8BAA8B,CAAC;IACvC,OAAO,OAAO,CAAC;AAChB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { GitFile } from './types.js';
2
+ export declare function git_path(file: GitFile): string;
3
+ export declare function stage_file(cwd: string, file: GitFile): Promise<void>;
4
+ export declare function unstage_file(cwd: string, file: GitFile): Promise<void>;
5
+ export declare function toggle_file(cwd: string, file: GitFile): Promise<void>;
6
+ export declare function stage_all(cwd: string): Promise<void>;
7
+ export declare function unstage_all(cwd: string): Promise<void>;
8
+ export declare function commit(cwd: string, message: string): Promise<void>;
@@ -0,0 +1,35 @@
1
+ import { git } from './client.js';
2
+ export function git_path(file) {
3
+ const arrow = ' → ';
4
+ return file.path.includes(arrow)
5
+ ? file.path.split(arrow).at(-1)
6
+ : file.path;
7
+ }
8
+ export async function stage_file(cwd, file) {
9
+ await git(['add', '--', git_path(file)], cwd);
10
+ }
11
+ export async function unstage_file(cwd, file) {
12
+ await git(['restore', '--staged', '--', git_path(file)], cwd);
13
+ }
14
+ export async function toggle_file(cwd, file) {
15
+ if (file.state === 'mixed') {
16
+ throw new Error('Partial file: space is disabled. Use s to stage worktree changes or x to unstage staged changes.');
17
+ }
18
+ if (file.state === 'conflicted') {
19
+ throw new Error('Conflicted file: resolve conflicts, then stage explicitly with s.');
20
+ }
21
+ if (file.state === 'staged')
22
+ await unstage_file(cwd, file);
23
+ else
24
+ await stage_file(cwd, file);
25
+ }
26
+ export async function stage_all(cwd) {
27
+ await git(['add', '--all'], cwd);
28
+ }
29
+ export async function unstage_all(cwd) {
30
+ await git(['restore', '--staged', '--', ':/'], cwd);
31
+ }
32
+ export async function commit(cwd, message) {
33
+ await git(['commit', '-m', message], cwd);
34
+ }
35
+ //# sourceMappingURL=operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/git/operations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC,MAAM,UAAU,QAAQ,CAAC,IAAa;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC;IACpB,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE;QAChC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,GAAW,EACX,IAAa;IAEb,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,GAAW,EACX,IAAa;IAEb,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,GAAW,EACX,IAAa;IAEb,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACd,kGAAkG,CAClG,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACd,mEAAmE,CACnE,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;QAAE,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;;QACtD,MAAM,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IAC1C,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC5C,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC3B,GAAW,EACX,OAAe;IAEf,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { RepoOverview } from './types.js';
2
+ export declare function read_repo_overview(cwd: string): Promise<RepoOverview>;
@@ -0,0 +1,23 @@
1
+ import { git } from './client.js';
2
+ import { format_git_error } from './errors.js';
3
+ export async function read_repo_overview(cwd) {
4
+ const [branches, log, stashes, remotes] = await Promise.all([
5
+ git(['branch', '--all', '--format=%(HEAD) %(refname:short)'], cwd).catch((error) => format_git_error(error)),
6
+ git(['log', '--oneline', '--decorate', '-n', '8'], cwd).catch((error) => format_git_error(error)),
7
+ git(['stash', 'list', '-n', '8'], cwd).catch((error) => format_git_error(error)),
8
+ git(['remote', '-v'], cwd).catch((error) => format_git_error(error)),
9
+ ]);
10
+ return {
11
+ branches: split_non_empty(branches),
12
+ log: split_non_empty(log),
13
+ stashes: split_non_empty(stashes),
14
+ remotes: split_non_empty(remotes),
15
+ };
16
+ }
17
+ function split_non_empty(raw) {
18
+ return raw
19
+ .split('\n')
20
+ .map((line) => line.trim())
21
+ .filter(Boolean);
22
+ }
23
+ //# sourceMappingURL=overview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overview.js","sourceRoot":"","sources":["../../src/git/overview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,GAAW;IAEX,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3D,GAAG,CACF,CAAC,QAAQ,EAAE,OAAO,EAAE,mCAAmC,CAAC,EACxD,GAAG,CACH,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC3C,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAC5D,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAClC;QACD,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CACtD,gBAAgB,CAAC,KAAK,CAAC,CACvB;QACD,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAC1C,gBAAgB,CAAC,KAAK,CAAC,CACvB;KACD,CAAC,CAAC;IACH,OAAO;QACN,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC;QACnC,GAAG,EAAE,eAAe,CAAC,GAAG,CAAC;QACzB,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC;QACjC,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC;KACjC,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IACnC,OAAO,GAAG;SACR,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { GitFile, GitStatus } from './types.js';
2
+ export declare function read_status(cwd: string): Promise<GitStatus>;
3
+ export declare function parse_porcelain_z(raw: string): GitFile[];
4
+ export declare function has_staged_changes(files: GitFile[]): boolean;
5
+ export declare function staged_file_count(files: GitFile[]): number;
@@ -0,0 +1,85 @@
1
+ import { git } from './client.js';
2
+ export async function read_status(cwd) {
3
+ const [branch, upstream, raw] = await Promise.all([
4
+ git(['branch', '--show-current'], cwd).catch(() => 'detached'),
5
+ git([
6
+ 'rev-parse',
7
+ '--abbrev-ref',
8
+ '--symbolic-full-name',
9
+ '@{upstream}',
10
+ ], cwd).catch(() => ''),
11
+ git(['status', '--porcelain=v1', '-z'], cwd),
12
+ ]);
13
+ const counts = upstream.trim()
14
+ ? await read_ahead_behind(cwd)
15
+ : { ahead: 0, behind: 0 };
16
+ return {
17
+ branch: branch.trim() || 'detached',
18
+ upstream: upstream.trim() || undefined,
19
+ ...counts,
20
+ files: parse_porcelain_z(raw),
21
+ };
22
+ }
23
+ async function read_ahead_behind(cwd) {
24
+ const raw = await git(['rev-list', '--left-right', '--count', '@{upstream}...HEAD'], cwd).catch(() => '');
25
+ const [behind = '0', ahead = '0'] = raw.trim().split(/\s+/);
26
+ return { ahead: Number(ahead) || 0, behind: Number(behind) || 0 };
27
+ }
28
+ export function parse_porcelain_z(raw) {
29
+ if (!raw)
30
+ return [];
31
+ const entries = raw.split('\0').filter(Boolean);
32
+ const files = [];
33
+ for (let i = 0; i < entries.length; i++) {
34
+ const entry = entries[i];
35
+ const index_status = entry[0] ?? ' ';
36
+ const worktree_status = entry[1] ?? ' ';
37
+ let path = entry.slice(3);
38
+ if (index_status === 'R' || index_status === 'C') {
39
+ const original = entries[++i];
40
+ if (original)
41
+ path = `${original} → ${path}`;
42
+ }
43
+ files.push({
44
+ path,
45
+ index_status,
46
+ worktree_status,
47
+ state: get_file_state(index_status, worktree_status),
48
+ });
49
+ }
50
+ return files.sort((a, b) => state_rank(a.state) - state_rank(b.state) ||
51
+ a.path.localeCompare(b.path));
52
+ }
53
+ function get_file_state(index_status, worktree_status) {
54
+ if (index_status === '?' && worktree_status === '?')
55
+ return 'untracked';
56
+ if (index_status === 'U' ||
57
+ worktree_status === 'U' ||
58
+ (index_status === 'A' && worktree_status === 'A') ||
59
+ (index_status === 'D' && worktree_status === 'D')) {
60
+ return 'conflicted';
61
+ }
62
+ const has_index = index_status !== ' ';
63
+ const has_worktree = worktree_status !== ' ';
64
+ if (has_index && has_worktree)
65
+ return 'mixed';
66
+ if (has_index)
67
+ return 'staged';
68
+ return 'changed';
69
+ }
70
+ function state_rank(state) {
71
+ return [
72
+ 'conflicted',
73
+ 'changed',
74
+ 'untracked',
75
+ 'mixed',
76
+ 'staged',
77
+ ].indexOf(state);
78
+ }
79
+ export function has_staged_changes(files) {
80
+ return files.some((file) => file.index_status !== ' ' && file.index_status !== '?');
81
+ }
82
+ export function staged_file_count(files) {
83
+ return files.filter((file) => file.index_status !== ' ' && file.index_status !== '?').length;
84
+ }
85
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/git/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export type FileState = 'staged' | 'changed' | 'mixed' | 'untracked' | 'conflicted';
2
+ export interface GitFile {
3
+ path: string;
4
+ index_status: string;
5
+ worktree_status: string;
6
+ state: FileState;
7
+ }
8
+ export interface GitStatus {
9
+ branch: string;
10
+ upstream?: string;
11
+ ahead: number;
12
+ behind: number;
13
+ files: GitFile[];
14
+ }
15
+ export type DiffSection = 'staged' | 'unstaged';
16
+ export interface DiffHunk {
17
+ section: DiffSection;
18
+ line_index: number;
19
+ header: string;
20
+ patch: string;
21
+ }
22
+ export interface DiffView {
23
+ path: string;
24
+ lines: string[];
25
+ hunks: DiffHunk[];
26
+ }
27
+ export interface RepoOverview {
28
+ branches: string[];
29
+ log: string[];
30
+ stashes: string[];
31
+ remotes: string[];
32
+ }
33
+ export declare const EMPTY_STATUS: GitStatus;
@@ -0,0 +1,7 @@
1
+ export const EMPTY_STATUS = {
2
+ branch: 'unknown',
3
+ ahead: 0,
4
+ behind: 0,
5
+ files: [],
6
+ };
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/git/types.ts"],"names":[],"mappings":"AA4CA,MAAM,CAAC,MAAM,YAAY,GAAc;IACtC,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,EAAE;CACT,CAAC"}
package/dist/git.d.ts CHANGED
@@ -1,31 +1,7 @@
1
- export type FileState = 'staged' | 'changed' | 'mixed' | 'untracked' | 'conflicted';
2
- export interface GitFile {
3
- path: string;
4
- index_status: string;
5
- worktree_status: string;
6
- state: FileState;
7
- }
8
- export interface GitStatus {
9
- branch: string;
10
- upstream?: string;
11
- ahead: number;
12
- behind: number;
13
- files: GitFile[];
14
- }
15
- export interface DiffView {
16
- path: string;
17
- lines: string[];
18
- }
19
- export declare const EMPTY_STATUS: GitStatus;
20
- export declare function read_status(cwd: string): Promise<GitStatus>;
21
- export declare function parse_porcelain_z(raw: string): GitFile[];
22
- export declare function stage_file(cwd: string, file: GitFile): Promise<void>;
23
- export declare function unstage_file(cwd: string, file: GitFile): Promise<void>;
24
- export declare function toggle_file(cwd: string, file: GitFile): Promise<void>;
25
- export declare function stage_all(cwd: string): Promise<void>;
26
- export declare function unstage_all(cwd: string): Promise<void>;
27
- export declare function commit(cwd: string, message: string): Promise<void>;
28
- export declare function read_diff(cwd: string, file: GitFile): Promise<DiffView>;
29
- export declare function format_git_error(error: unknown): string;
30
- export declare function has_staged_changes(files: GitFile[]): boolean;
31
- export declare function staged_file_count(files: GitFile[]): number;
1
+ export { build_line_patch, changed_line_indexes, parse_diff_hunks, read_diff, stage_hunk, stage_line, unstage_hunk, unstage_line, } from './git/diff.js';
2
+ export { format_git_error } from './git/errors.js';
3
+ export { commit, git_path, stage_all, stage_file, toggle_file, unstage_all, unstage_file, } from './git/operations.js';
4
+ export { read_repo_overview } from './git/overview.js';
5
+ export { has_staged_changes, parse_porcelain_z, read_status, staged_file_count, } from './git/status.js';
6
+ export { EMPTY_STATUS } from './git/types.js';
7
+ export type { DiffHunk, DiffSection, DiffView, FileState, GitFile, GitStatus, RepoOverview, } from './git/types.js';