git-it-done 1.0.3 → 1.1.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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/utils/checkGitStatus.js +39 -22
  5. package/dist/utils/checkGitStatus.js.map +1 -1
  6. package/dist/utils/diffSignals.d.ts +22 -0
  7. package/dist/utils/diffSignals.js +75 -0
  8. package/dist/utils/diffSignals.js.map +1 -0
  9. package/dist/utils/fileStaging.js +68 -22
  10. package/dist/utils/fileStaging.js.map +1 -1
  11. package/dist/utils/formatFileStatus.js +6 -0
  12. package/dist/utils/formatFileStatus.js.map +1 -1
  13. package/dist/utils/generateCommitMessage.d.ts +12 -0
  14. package/dist/utils/generateCommitMessage.js +178 -83
  15. package/dist/utils/generateCommitMessage.js.map +1 -1
  16. package/dist/utils/getFileChanges.d.ts +15 -1
  17. package/dist/utils/getFileChanges.js +59 -18
  18. package/dist/utils/getFileChanges.js.map +1 -1
  19. package/dist/utils/gitCommand.d.ts +27 -1
  20. package/dist/utils/gitCommand.js +53 -10
  21. package/dist/utils/gitCommand.js.map +1 -1
  22. package/dist/utils/performCommit.js +29 -34
  23. package/dist/utils/performCommit.js.map +1 -1
  24. package/dist/utils/process_interruption.js +22 -13
  25. package/dist/utils/process_interruption.js.map +1 -1
  26. package/dist/utils/push_to_remote.js +52 -36
  27. package/dist/utils/push_to_remote.js.map +1 -1
  28. package/dist/utils/repoRoot.d.ts +6 -0
  29. package/dist/utils/repoRoot.js +10 -0
  30. package/dist/utils/repoRoot.js.map +1 -0
  31. package/dist/utils/types/types.d.ts +11 -1
  32. package/package.json +8 -7
  33. package/readme.md +5 -5
  34. package/dist/utils/isGitrepo.d.ts +0 -1
  35. package/dist/utils/isGitrepo.js +0 -6
  36. package/dist/utils/isGitrepo.js.map +0 -1
@@ -1,105 +1,200 @@
1
1
  import path from 'path';
2
- import { gitCommand } from './gitCommand.js';
3
- // Generate commit message based on changes
4
- export function generateCommitMessage(files) {
5
- var _a, _b, _c;
6
- const fileTypes = new Map();
2
+ import chalk from 'chalk';
3
+ import { readStagedDiffSignals } from './diffSignals.js';
4
+ /** Checked in this order, so the more specific category always wins a tie. */
5
+ const CATEGORY_ORDER = ['deps', 'test', 'docs', 'config', 'style', 'source'];
6
+ const DEPS_FILE = /^(package(-lock)?\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|requirements(-[\w.]+)?\.txt|Pipfile(\.lock)?|poetry\.lock|Gemfile(\.lock)?|go\.(mod|sum)|Cargo\.(toml|lock)|composer\.(json|lock))$/i;
7
+ const TEST_DIR = /(^|\/)(tests?|__tests__|__mocks__|spec|e2e|cypress)\//i;
8
+ const TEST_FILE = /(\.(test|spec)\.[cm]?[jt]sx?|_test\.(go|py|rb)|^test_[^/]+\.py)$/i;
9
+ const DOCS_DIR = /(^|\/)docs?\//i;
10
+ const DOCS_FILE = /(\.(md|mdx|rst|adoc)|^(readme|changelog|contributing|authors|license)(\.[a-z]+)?)$/i;
11
+ const STYLE_FILE = /\.(css|scss|sass|less|styl)$/i;
12
+ /** Real configuration files — not "anything ending in .json". */
13
+ const CONFIG_FILE = /^(tsconfig(\.[\w-]+)?\.json|jsconfig\.json|\.editorconfig|\.gitignore|\.gitattributes|\.npmrc|\.npmignore|\.nvmrc|\.node-version|\.eslintrc(\.[\w-]+)?|\.eslintignore|\.prettierrc(\.[\w-]+)?|\.prettierignore|\.babelrc(\.[\w-]+)?|\.dockerignore|\.env(\.[\w-]+)?|Dockerfile(\.[\w-]+)?|docker-compose(\.[\w-]+)?\.ya?ml|Makefile|renovate\.json|netlify\.toml|vercel\.json)$/i;
14
+ const CONFIG_SUFFIX = /\.config\.([cm]?[jt]s|json|ya?ml|toml)$/i;
15
+ const CONFIG_DIR = /^\.(github|circleci|vscode|husky|idea)\//i;
16
+ /** Monorepo container directories whose child directory is the useful scope. */
17
+ const CONTAINER_DIRS = new Set(['packages', 'apps', 'libs', 'services', 'crates', 'modules']);
18
+ export function categorizeFile(file) {
19
+ var _a;
20
+ const base = (_a = file.split('/').pop()) !== null && _a !== void 0 ? _a : file;
21
+ if (DEPS_FILE.test(base))
22
+ return 'deps';
23
+ if (TEST_DIR.test(file) || TEST_FILE.test(base))
24
+ return 'test';
25
+ if (DOCS_DIR.test(file) || DOCS_FILE.test(base))
26
+ return 'docs';
27
+ if (CONFIG_FILE.test(base) || CONFIG_SUFFIX.test(base) || CONFIG_DIR.test(file))
28
+ return 'config';
29
+ if (STYLE_FILE.test(base))
30
+ return 'style';
31
+ return 'source';
32
+ }
33
+ /** The category the majority of the changed files belong to. */
34
+ export function dominantCategory(files) {
35
+ var _a, _b;
36
+ const counts = new Map();
37
+ for (const { file } of files) {
38
+ const category = categorizeFile(file);
39
+ counts.set(category, ((_a = counts.get(category)) !== null && _a !== void 0 ? _a : 0) + 1);
40
+ }
41
+ let winner = 'source';
42
+ let best = 0;
43
+ for (const category of CATEGORY_ORDER) {
44
+ const count = (_b = counts.get(category)) !== null && _b !== void 0 ? _b : 0;
45
+ if (count > best) {
46
+ winner = category;
47
+ best = count;
48
+ }
49
+ }
50
+ return winner;
51
+ }
52
+ /**
53
+ * Most common directory across the changed files. `packages/x/...` and
54
+ * `apps/x/...` resolve to `x` so a monorepo commit is not scoped `packages`.
55
+ */
56
+ export function deriveScope(files) {
57
+ var _a;
58
+ const counts = new Map();
59
+ for (const { file } of files) {
60
+ const segments = file.split('/').filter(Boolean);
61
+ if (segments.length < 2)
62
+ continue;
63
+ let scope = segments[0];
64
+ if (CONTAINER_DIRS.has(scope.toLowerCase()) && segments.length > 2) {
65
+ scope = segments[1];
66
+ }
67
+ scope = scope.replace(/[()\s]/g, '');
68
+ if (!scope)
69
+ continue;
70
+ counts.set(scope, ((_a = counts.get(scope)) !== null && _a !== void 0 ? _a : 0) + 1);
71
+ }
72
+ let winner = '';
73
+ let best = 0;
74
+ for (const [scope, count] of counts) {
75
+ if (count > best) {
76
+ winner = scope;
77
+ best = count;
78
+ }
79
+ }
80
+ return winner;
81
+ }
82
+ function countOperations(files) {
7
83
  const operations = { added: 0, modified: 0, deleted: 0, renamed: 0 };
8
- let scope = '';
9
- // Analyze files
10
- for (const { status, file } of files) {
11
- const ext = path.extname(file);
12
- fileTypes.set(ext, (fileTypes.get(ext) || 0) + 1);
84
+ for (const { status } of files) {
13
85
  switch (status) {
14
86
  case 'A':
87
+ case '??':
15
88
  operations.added++;
16
89
  break;
17
90
  case 'M':
91
+ case 'T':
18
92
  operations.modified++;
19
93
  break;
20
94
  case 'D':
21
95
  operations.deleted++;
22
96
  break;
23
97
  case 'R':
98
+ case 'C':
24
99
  operations.renamed++;
25
100
  break;
26
101
  }
27
- // Determine scope from top-level directory
28
- if (!scope) {
29
- const dir = file.split('/')[0];
30
- if (dir && dir !== file) {
31
- scope = dir;
32
- }
33
- }
34
102
  }
35
- // Detect content types
36
- const hasPattern = (regex) => files.some(f => regex.test(f.file));
37
- const hasTests = hasPattern(/test|spec/i);
38
- const hasDocs = hasPattern(/readme|doc|\.md$/i);
39
- const hasConfig = hasPattern(/config|\.json$|\.ya?ml$|package\.json/i);
40
- const hasStyles = hasPattern(/\.(css|scss|sass|less)$/i);
41
- const hasDeps = hasPattern(/package(-lock)?\.json|yarn\.lock|requirements\.txt/i);
42
- // Determine type and description
43
- let type = 'chore';
44
- let description = '';
45
- if (hasDeps) {
46
- type = 'deps';
47
- description = 'update dependencies';
48
- }
49
- else if (hasTests) {
50
- type = 'test';
51
- description = 'update tests';
52
- }
53
- else if (hasDocs) {
54
- type = 'docs';
55
- description = 'update documentation';
56
- }
57
- else if (hasConfig) {
58
- type = 'config';
59
- description = 'update configuration';
60
- }
61
- else if (hasStyles) {
62
- type = 'style';
63
- description = 'update styles';
64
- }
65
- else if (operations.added > 0 && operations.modified === 0 && operations.deleted === 0) {
66
- type = 'feat';
67
- description = operations.added === 1
68
- ? `add ${path.basename(((_a = files.find(f => f.status === 'A')) === null || _a === void 0 ? void 0 : _a.file) || '')}`
69
- : 'add new files';
70
- }
71
- else if (operations.deleted > 0 && operations.added === 0 && operations.modified === 0) {
72
- type = 'remove';
73
- description = operations.deleted === 1
74
- ? `remove ${path.basename(((_b = files.find(f => f.status === 'D')) === null || _b === void 0 ? void 0 : _b.file) || '')}`
75
- : 'remove files';
76
- }
77
- else if (operations.modified > 0) {
78
- type = 'fix';
79
- description = operations.modified === 1 && operations.added === 0 && operations.deleted === 0
80
- ? `update ${path.basename(((_c = files.find(f => f.status === 'M')) === null || _c === void 0 ? void 0 : _c.file) || '')}`
81
- : 'update and improve code';
82
- }
83
- // Refine with diff content
84
- try {
85
- const diff = gitCommand('diff --cached') || '';
86
- if (/bug|fix|error|issue/i.test(diff)) {
87
- type = 'fix';
88
- description = 'resolve issues and bugs';
89
- }
90
- else if (/refactor|restructure/i.test(diff)) {
91
- type = 'refactor';
92
- description = 'refactor code structure';
93
- }
94
- else if (/function|def|class|interface/i.test(diff) && type === 'fix') {
95
- type = 'feat';
96
- description = 'implement new functionality';
97
- }
103
+ return operations;
104
+ }
105
+ function firstNameWithStatus(files, statuses) {
106
+ const match = files.find(file => statuses.includes(file.status));
107
+ return match ? path.basename(match.file) : '';
108
+ }
109
+ function classifySource(files, operations) {
110
+ const { added, modified, deleted, renamed } = operations;
111
+ if (added > 0 && modified === 0 && deleted === 0 && renamed === 0) {
112
+ return {
113
+ type: 'feat',
114
+ description: added === 1 ? `add ${firstNameWithStatus(files, ['A', '??'])}` : `add ${added} new files`
115
+ };
116
+ }
117
+ if (deleted > 0 && added === 0 && modified === 0 && renamed === 0) {
118
+ return {
119
+ type: 'refactor',
120
+ description: deleted === 1 ? `remove ${firstNameWithStatus(files, ['D'])}` : `remove ${deleted} files`
121
+ };
122
+ }
123
+ if (renamed > 0 && added === 0 && modified === 0 && deleted === 0) {
124
+ return {
125
+ type: 'refactor',
126
+ description: renamed === 1 ? `rename ${firstNameWithStatus(files, ['R', 'C'])}` : `rename ${renamed} files`
127
+ };
128
+ }
129
+ if (added > 0 && added >= modified + deleted + renamed) {
130
+ return { type: 'feat', description: 'add new functionality' };
131
+ }
132
+ if (modified === 1 && added === 0 && deleted === 0 && renamed === 0) {
133
+ return { type: 'chore', description: `update ${firstNameWithStatus(files, ['M', 'T'])}` };
134
+ }
135
+ return { type: 'chore', description: 'update and improve code' };
136
+ }
137
+ function classifyByCategory(category, files, operations) {
138
+ switch (category) {
139
+ case 'deps':
140
+ // `deps` is not a Conventional Commits type; dependency bumps are `build`.
141
+ return { type: 'build', description: 'update dependencies' };
142
+ case 'test':
143
+ return {
144
+ type: 'test',
145
+ description: operations.modified === 0 && operations.added > 0 ? 'add tests' : 'update tests'
146
+ };
147
+ case 'docs':
148
+ return { type: 'docs', description: 'update documentation' };
149
+ case 'config':
150
+ // `config` is not a Conventional Commits type either.
151
+ return { type: 'chore', description: 'update configuration' };
152
+ case 'style':
153
+ return { type: 'style', description: 'update styles' };
154
+ default:
155
+ return classifySource(files, operations);
156
+ }
157
+ }
158
+ /**
159
+ * Diff hints only ever break a tie: they refine the vague `chore: update ...`
160
+ * fallback and are never allowed to override a confident classification such as
161
+ * "40 files were added" or "this commit only touches docs".
162
+ */
163
+ function refine(base, signals) {
164
+ if (!signals || signals.oversized || base.type !== 'chore') {
165
+ return base;
166
+ }
167
+ if (signals.fixIntent) {
168
+ return { type: 'fix', description: 'correct faulty behavior' };
169
+ }
170
+ if (signals.newApi) {
171
+ return { type: 'feat', description: 'implement new functionality' };
172
+ }
173
+ if (signals.refactorIntent) {
174
+ return { type: 'refactor', description: 'restructure code' };
98
175
  }
99
- catch (_d) {
100
- // Ignore diff errors
176
+ if (signals.conditionalChurn) {
177
+ return { type: 'fix', description: 'correct conditional handling' };
101
178
  }
179
+ return base;
180
+ }
181
+ /** Pure, testable core: no git access, all inputs explicit. */
182
+ export function buildCommitMessage(files, signals = null) {
183
+ const operations = countOperations(files);
184
+ const category = dominantCategory(files);
185
+ const base = classifyByCategory(category, files, operations);
186
+ const { type, description } = category === 'source' ? refine(base, signals) : base;
187
+ // Renames-only commits used to produce an empty description ("chore(src): ").
188
+ const safeDescription = description.trim() || 'update files';
189
+ const scope = deriveScope(files);
102
190
  const scopeStr = scope ? `(${scope})` : '';
103
- return `${type}${scopeStr}: ${description}`;
191
+ return `${type}${scopeStr}: ${safeDescription}`;
192
+ }
193
+ export function generateCommitMessage(files) {
194
+ const signals = readStagedDiffSignals();
195
+ if (signals === null || signals === void 0 ? void 0 : signals.oversized) {
196
+ console.log(chalk.yellow('⚠️ Staged diff is too large to analyse — the message is based on file names only.'));
197
+ }
198
+ return buildCommitMessage(files, signals);
104
199
  }
105
200
  //# sourceMappingURL=generateCommitMessage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateCommitMessage.js","sourceRoot":"","sources":["../../src/utils/generateCommitMessage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generateCommitMessage.js","sourceRoot":"","sources":["../../src/utils/generateCommitMessage.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,16 @@
1
- import { GitChanges } from "./types/types.js";
1
+ import { FileChange, GitChanges } from './types/types.js';
2
+ /**
3
+ * Parse `git diff --name-status -z` output.
4
+ *
5
+ * With `-z` every field is its own NUL-terminated record:
6
+ * `M\0path\0` for ordinary changes
7
+ * `R100\0oldPath\0newPath\0` for renames (and `C###` for copies)
8
+ *
9
+ * The similarity score is stripped from the status and the destination path is
10
+ * used for renames/copies, so downstream code never sees `R100` or a bogus
11
+ * `old\tnew` path.
12
+ */
13
+ export declare function parseNameStatusZ(output: string): FileChange[];
14
+ /** Parse a NUL-separated list of paths (e.g. `git ls-files -z`). */
15
+ export declare function parseNulList(output: string, status: string): FileChange[];
2
16
  export declare function getChanges(): GitChanges;
@@ -1,25 +1,66 @@
1
- import { gitCommand } from "./gitCommand.js";
2
- // Get file changes
3
- function parseGitStatus(output, defaultStatus = '') {
4
- return output
5
- .split('\n')
6
- .filter(Boolean)
7
- .map(line => {
8
- if (defaultStatus) {
9
- return { status: defaultStatus, file: line };
1
+ import { gitCommand } from './gitCommand.js';
2
+ /**
3
+ * Parse `git diff --name-status -z` output.
4
+ *
5
+ * With `-z` every field is its own NUL-terminated record:
6
+ * `M\0path\0` for ordinary changes
7
+ * `R100\0oldPath\0newPath\0` for renames (and `C###` for copies)
8
+ *
9
+ * The similarity score is stripped from the status and the destination path is
10
+ * used for renames/copies, so downstream code never sees `R100` or a bogus
11
+ * `old\tnew` path.
12
+ */
13
+ export function parseNameStatusZ(output) {
14
+ const tokens = output.split('\0').filter(token => token.length > 0);
15
+ const changes = [];
16
+ for (let i = 0; i < tokens.length;) {
17
+ const raw = tokens[i++];
18
+ const status = raw.charAt(0).toUpperCase();
19
+ if (status === 'R' || status === 'C') {
20
+ const from = tokens[i++];
21
+ const to = tokens[i++];
22
+ if (from === undefined || to === undefined)
23
+ break;
24
+ changes.push({ status, file: to, from });
25
+ }
26
+ else {
27
+ const file = tokens[i++];
28
+ if (file === undefined)
29
+ break;
30
+ changes.push({ status, file });
10
31
  }
11
- const [status, ...fileParts] = line.split('\t');
12
- return { status, file: fileParts.join('\t') };
13
- });
32
+ }
33
+ return changes;
34
+ }
35
+ /** Parse a NUL-separated list of paths (e.g. `git ls-files -z`). */
36
+ export function parseNulList(output, status) {
37
+ return output
38
+ .split('\0')
39
+ .filter(file => file.length > 0)
40
+ .map(file => ({ status, file }));
41
+ }
42
+ function nameStatus(args) {
43
+ const result = gitCommand(args);
44
+ return result.ok ? parseNameStatusZ(result.stdout) : [];
14
45
  }
15
46
  export function getChanges() {
16
- const stagedOutput = gitCommand('diff --cached --name-status') || '';
17
- const unstagedOutput = gitCommand('diff --name-status') || '';
18
- const untrackedOutput = gitCommand('ls-files --others --exclude-standard') || '';
47
+ const staged = nameStatus(['diff', '--cached', '--name-status', '--find-renames', '-z']);
48
+ const unstaged = nameStatus(['diff', '--name-status', '--find-renames', '-z']);
49
+ // `--full-name` + `:/` keep untracked paths repo-root-relative like the diff
50
+ // output above, even when the tool is invoked from a subdirectory.
51
+ const untrackedResult = gitCommand([
52
+ 'ls-files',
53
+ '--others',
54
+ '--exclude-standard',
55
+ '--full-name',
56
+ '-z',
57
+ '--',
58
+ ':/'
59
+ ]);
19
60
  return {
20
- staged: parseGitStatus(stagedOutput),
21
- unstaged: parseGitStatus(unstagedOutput),
22
- untracked: parseGitStatus(untrackedOutput, '??')
61
+ staged,
62
+ unstaged,
63
+ untracked: untrackedResult.ok ? parseNulList(untrackedResult.stdout, '??') : []
23
64
  };
24
65
  }
25
66
  //# sourceMappingURL=getFileChanges.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getFileChanges.js","sourceRoot":"","sources":["../../src/utils/getFileChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,mBAAmB;AACnB,SAAS,cAAc,CAAC,MAAc,EAAE,aAAa,GAAG,EAAE;IACxD,OAAO,MAAM;SACV,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,IAAI,CAAC,EAAE;QACV,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC/C,CAAC;QACD,MAAM,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,YAAY,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,EAAE,CAAC;IACrE,MAAM,cAAc,GAAG,UAAU,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC;IAC9D,MAAM,eAAe,GAAG,UAAU,CAAC,sCAAsC,CAAC,IAAI,EAAE,CAAC;IAEjF,OAAO;QACL,MAAM,EAAE,cAAc,CAAC,YAAY,CAAC;QACpC,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC;QACxC,SAAS,EAAE,cAAc,CAAC,eAAe,EAAE,IAAI,CAAC;KACjD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"getFileChanges.js","sourceRoot":"","sources":["../../src/utils/getFileChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACpE,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAI,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAE3C,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;YACzB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;YACvB,IAAI,IAAI,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS;gBAAE,MAAM;YAClD,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;YACzB,IAAI,IAAI,KAAK,SAAS;gBAAE,MAAM;YAC9B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,MAAc;IACzD,OAAO,MAAM;SACV,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,UAAU,CAAC,IAAc;IAChC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC,CAAC;IACzF,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC,CAAC;IAE/E,6EAA6E;IAC7E,mEAAmE;IACnE,MAAM,eAAe,GAAG,UAAU,CAAC;QACjC,UAAU;QACV,UAAU;QACV,oBAAoB;QACpB,aAAa;QACb,IAAI;QACJ,IAAI;QACJ,IAAI;KACL,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,QAAQ;QACR,SAAS,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;KAChF,CAAC;AACJ,CAAC"}
@@ -1 +1,27 @@
1
- export declare function gitCommand(command: string): string | null;
1
+ export interface GitResult {
2
+ /** True when git exited with status 0. */
3
+ ok: boolean;
4
+ stdout: string;
5
+ stderr: string;
6
+ status: number | null;
7
+ /** True when the output exceeded `maxBuffer` and was therefore truncated. */
8
+ oversized: boolean;
9
+ }
10
+ export interface GitOptions {
11
+ /** Defaults to 64 MiB (Node's default of 1 MiB truncates large diffs). */
12
+ maxBuffer?: number;
13
+ cwd?: string;
14
+ input?: string;
15
+ }
16
+ /** 64 MiB — big enough for realistic diffs, small enough to stay a guard rail. */
17
+ export declare const DEFAULT_MAX_BUFFER: number;
18
+ /**
19
+ * Run git with an argv array. Never goes through a shell, so file names and
20
+ * commit messages containing `$`, backticks, `!`, quotes or newlines are passed
21
+ * through verbatim instead of being interpreted by /bin/sh.
22
+ */
23
+ export declare function gitCommand(args: string[], options?: GitOptions): GitResult;
24
+ /** Convenience wrapper for the common "give me the trimmed stdout" case. */
25
+ export declare function gitOutput(args: string[], options?: GitOptions): string | null;
26
+ /** Best-effort explanation of a failed git invocation, for display to the user. */
27
+ export declare function gitErrorText(result: GitResult): string;
@@ -1,14 +1,57 @@
1
- import { execSync } from 'child_process';
2
- // Utility function to execute git commands with better error handling
3
- export function gitCommand(command) {
4
- try {
5
- return execSync(`git ${command}`, {
6
- encoding: 'utf-8',
7
- stdio: 'pipe'
8
- }).trim();
1
+ import { spawnSync } from 'child_process';
2
+ /** 64 MiB — big enough for realistic diffs, small enough to stay a guard rail. */
3
+ export const DEFAULT_MAX_BUFFER = 64 * 1024 * 1024;
4
+ /**
5
+ * Run git with an argv array. Never goes through a shell, so file names and
6
+ * commit messages containing `$`, backticks, `!`, quotes or newlines are passed
7
+ * through verbatim instead of being interpreted by /bin/sh.
8
+ */
9
+ export function gitCommand(args, options = {}) {
10
+ var _a, _b, _c;
11
+ const result = spawnSync('git', args, {
12
+ encoding: 'utf-8',
13
+ maxBuffer: (_a = options.maxBuffer) !== null && _a !== void 0 ? _a : DEFAULT_MAX_BUFFER,
14
+ cwd: options.cwd,
15
+ input: options.input
16
+ });
17
+ const stdout = (_b = result.stdout) !== null && _b !== void 0 ? _b : '';
18
+ const stderr = (_c = result.stderr) !== null && _c !== void 0 ? _c : '';
19
+ if (result.error) {
20
+ const code = result.error.code;
21
+ return {
22
+ ok: false,
23
+ stdout,
24
+ stderr: stderr || result.error.message,
25
+ status: result.status,
26
+ oversized: code === 'ENOBUFS'
27
+ };
9
28
  }
10
- catch (_a) {
11
- return null;
29
+ return {
30
+ ok: result.status === 0,
31
+ stdout,
32
+ stderr,
33
+ status: result.status,
34
+ oversized: false
35
+ };
36
+ }
37
+ /** Convenience wrapper for the common "give me the trimmed stdout" case. */
38
+ export function gitOutput(args, options = {}) {
39
+ const result = gitCommand(args, options);
40
+ return result.ok ? result.stdout.trim() : null;
41
+ }
42
+ /** Best-effort explanation of a failed git invocation, for display to the user. */
43
+ export function gitErrorText(result) {
44
+ var _a;
45
+ const text = [result.stderr, result.stdout]
46
+ .map(part => part.trim())
47
+ .filter(Boolean)
48
+ .join('\n');
49
+ if (text) {
50
+ return text;
51
+ }
52
+ if (result.oversized) {
53
+ return 'git produced more output than could be buffered';
12
54
  }
55
+ return `git exited with status ${(_a = result.status) !== null && _a !== void 0 ? _a : 'unknown'}`;
13
56
  }
14
57
  //# sourceMappingURL=gitCommand.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitCommand.js","sourceRoot":"","sources":["../../src/utils/gitCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,sEAAsE;AACtE,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,OAAO,OAAO,EAAE,EAAE;YAChC,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;SACd,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"gitCommand.js","sourceRoot":"","sources":["../../src/utils/gitCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAmB1C,kFAAkF;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,UAAsB,EAAE;;IACjE,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QACpC,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,MAAA,OAAO,CAAC,SAAS,mCAAI,kBAAkB;QAClD,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAA,MAAM,CAAC,MAAM,mCAAI,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,MAAA,MAAM,CAAC,MAAM,mCAAI,EAAE,CAAC;IAEnC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,GAAI,MAAM,CAAC,KAA+B,CAAC,IAAI,CAAC;QAC1D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM;YACN,MAAM,EAAE,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO;YACtC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,IAAI,KAAK,SAAS;SAC9B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QACvB,MAAM;QACN,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,SAAS,EAAE,KAAK;KACjB,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,UAAsB,EAAE;IAChE,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,MAAiB;;IAC5C,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;SACxC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SACxB,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO,iDAAiD,CAAC;IAC3D,CAAC;IACD,OAAO,0BAA0B,MAAA,MAAM,CAAC,MAAM,mCAAI,SAAS,EAAE,CAAC;AAChE,CAAC"}