@generacy-ai/agency-plugin-git 0.0.0-preview-20260302182740

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 (118) hide show
  1. package/LICENSE +191 -0
  2. package/dist/config.d.ts +25 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +22 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/errors/auth-error.d.ts +23 -0
  7. package/dist/errors/auth-error.d.ts.map +1 -0
  8. package/dist/errors/auth-error.js +33 -0
  9. package/dist/errors/auth-error.js.map +1 -0
  10. package/dist/errors/conflict-error.d.ts +31 -0
  11. package/dist/errors/conflict-error.d.ts.map +1 -0
  12. package/dist/errors/conflict-error.js +49 -0
  13. package/dist/errors/conflict-error.js.map +1 -0
  14. package/dist/errors/detached-head-error.d.ts +26 -0
  15. package/dist/errors/detached-head-error.d.ts.map +1 -0
  16. package/dist/errors/detached-head-error.js +32 -0
  17. package/dist/errors/detached-head-error.js.map +1 -0
  18. package/dist/errors/git-error.d.ts +25 -0
  19. package/dist/errors/git-error.d.ts.map +1 -0
  20. package/dist/errors/git-error.js +33 -0
  21. package/dist/errors/git-error.js.map +1 -0
  22. package/dist/errors/index.d.ts +9 -0
  23. package/dist/errors/index.d.ts.map +1 -0
  24. package/dist/errors/index.js +9 -0
  25. package/dist/errors/index.js.map +1 -0
  26. package/dist/errors/network-error.d.ts +30 -0
  27. package/dist/errors/network-error.d.ts.map +1 -0
  28. package/dist/errors/network-error.js +67 -0
  29. package/dist/errors/network-error.js.map +1 -0
  30. package/dist/index.d.ts +26 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +29 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/plugin.d.ts +28 -0
  35. package/dist/plugin.d.ts.map +1 -0
  36. package/dist/plugin.js +79 -0
  37. package/dist/plugin.js.map +1 -0
  38. package/dist/tools/blame.d.ts +9 -0
  39. package/dist/tools/blame.d.ts.map +1 -0
  40. package/dist/tools/blame.js +67 -0
  41. package/dist/tools/blame.js.map +1 -0
  42. package/dist/tools/branch.d.ts +9 -0
  43. package/dist/tools/branch.d.ts.map +1 -0
  44. package/dist/tools/branch.js +141 -0
  45. package/dist/tools/branch.js.map +1 -0
  46. package/dist/tools/checkout.d.ts +9 -0
  47. package/dist/tools/checkout.d.ts.map +1 -0
  48. package/dist/tools/checkout.js +94 -0
  49. package/dist/tools/checkout.js.map +1 -0
  50. package/dist/tools/commit.d.ts +9 -0
  51. package/dist/tools/commit.d.ts.map +1 -0
  52. package/dist/tools/commit.js +90 -0
  53. package/dist/tools/commit.js.map +1 -0
  54. package/dist/tools/diff.d.ts +9 -0
  55. package/dist/tools/diff.d.ts.map +1 -0
  56. package/dist/tools/diff.js +97 -0
  57. package/dist/tools/diff.js.map +1 -0
  58. package/dist/tools/index.d.ts +26 -0
  59. package/dist/tools/index.d.ts.map +1 -0
  60. package/dist/tools/index.js +55 -0
  61. package/dist/tools/index.js.map +1 -0
  62. package/dist/tools/log.d.ts +9 -0
  63. package/dist/tools/log.d.ts.map +1 -0
  64. package/dist/tools/log.js +91 -0
  65. package/dist/tools/log.js.map +1 -0
  66. package/dist/tools/merge.d.ts +9 -0
  67. package/dist/tools/merge.d.ts.map +1 -0
  68. package/dist/tools/merge.js +119 -0
  69. package/dist/tools/merge.js.map +1 -0
  70. package/dist/tools/pull.d.ts +9 -0
  71. package/dist/tools/pull.d.ts.map +1 -0
  72. package/dist/tools/pull.js +113 -0
  73. package/dist/tools/pull.js.map +1 -0
  74. package/dist/tools/push.d.ts +9 -0
  75. package/dist/tools/push.d.ts.map +1 -0
  76. package/dist/tools/push.js +116 -0
  77. package/dist/tools/push.js.map +1 -0
  78. package/dist/tools/rebase.d.ts +9 -0
  79. package/dist/tools/rebase.d.ts.map +1 -0
  80. package/dist/tools/rebase.js +147 -0
  81. package/dist/tools/rebase.js.map +1 -0
  82. package/dist/tools/stash.d.ts +9 -0
  83. package/dist/tools/stash.d.ts.map +1 -0
  84. package/dist/tools/stash.js +151 -0
  85. package/dist/tools/stash.js.map +1 -0
  86. package/dist/tools/status.d.ts +9 -0
  87. package/dist/tools/status.d.ts.map +1 -0
  88. package/dist/tools/status.js +76 -0
  89. package/dist/tools/status.js.map +1 -0
  90. package/dist/types.d.ts +297 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +7 -0
  93. package/dist/types.js.map +1 -0
  94. package/dist/utils/conflict-parser.d.ts +38 -0
  95. package/dist/utils/conflict-parser.d.ts.map +1 -0
  96. package/dist/utils/conflict-parser.js +158 -0
  97. package/dist/utils/conflict-parser.js.map +1 -0
  98. package/dist/utils/exec-git.d.ts +45 -0
  99. package/dist/utils/exec-git.d.ts.map +1 -0
  100. package/dist/utils/exec-git.js +180 -0
  101. package/dist/utils/exec-git.js.map +1 -0
  102. package/dist/utils/parse-blame.d.ts +29 -0
  103. package/dist/utils/parse-blame.d.ts.map +1 -0
  104. package/dist/utils/parse-blame.js +97 -0
  105. package/dist/utils/parse-blame.js.map +1 -0
  106. package/dist/utils/parse-diff.d.ts +25 -0
  107. package/dist/utils/parse-diff.d.ts.map +1 -0
  108. package/dist/utils/parse-diff.js +105 -0
  109. package/dist/utils/parse-diff.js.map +1 -0
  110. package/dist/utils/parse-log.d.ts +33 -0
  111. package/dist/utils/parse-log.d.ts.map +1 -0
  112. package/dist/utils/parse-log.js +90 -0
  113. package/dist/utils/parse-log.js.map +1 -0
  114. package/dist/utils/parse-status.d.ts +22 -0
  115. package/dist/utils/parse-status.d.ts.map +1 -0
  116. package/dist/utils/parse-status.js +173 -0
  117. package/dist/utils/parse-status.js.map +1 -0
  118. package/package.json +82 -0
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Git command execution wrapper
3
+ *
4
+ * Provides:
5
+ * - Spawn-based execution with timeout
6
+ * - Error classification
7
+ * - Raw output capture for parsing
8
+ */
9
+ import { spawn } from 'node:child_process';
10
+ import { GitError, AuthError, NetworkError, ConflictError, DetachedHeadError, isAuthError, isNetworkError, isConflictError, isDetachedHeadError, extractRemote, } from '../errors/index.js';
11
+ const DEFAULT_TIMEOUT = 30000; // 30 seconds
12
+ /**
13
+ * Execute a git command and return the result
14
+ *
15
+ * @param args - Git command arguments (e.g., ['status', '--porcelain'])
16
+ * @param options - Execution options
17
+ * @returns ExecGitResult with exitCode, stdout, stderr
18
+ */
19
+ export async function execGit(args, options = {}) {
20
+ const { cwd = process.cwd(), timeout = DEFAULT_TIMEOUT, env = {}, } = options;
21
+ const command = `git ${args.join(' ')}`;
22
+ return new Promise((resolve, reject) => {
23
+ const gitProcess = spawn('git', args, {
24
+ cwd,
25
+ env: { ...process.env, ...env },
26
+ stdio: ['ignore', 'pipe', 'pipe'],
27
+ });
28
+ let stdout = '';
29
+ let stderr = '';
30
+ gitProcess.stdout.on('data', (data) => {
31
+ stdout += data.toString();
32
+ });
33
+ gitProcess.stderr.on('data', (data) => {
34
+ stderr += data.toString();
35
+ });
36
+ const timeoutId = setTimeout(() => {
37
+ gitProcess.kill('SIGTERM');
38
+ reject(new GitError(`Git command timed out after ${timeout}ms`, {
39
+ command,
40
+ exitCode: -1,
41
+ stderr: 'Command timed out',
42
+ cwd,
43
+ }));
44
+ }, timeout);
45
+ gitProcess.on('error', (error) => {
46
+ clearTimeout(timeoutId);
47
+ reject(new GitError(`Failed to spawn git: ${error.message}`, {
48
+ command,
49
+ exitCode: -1,
50
+ stderr: error.message,
51
+ cwd,
52
+ }));
53
+ });
54
+ gitProcess.on('close', (code) => {
55
+ clearTimeout(timeoutId);
56
+ resolve({
57
+ exitCode: code ?? 0,
58
+ stdout: stdout.trim(),
59
+ stderr: stderr.trim(),
60
+ command,
61
+ });
62
+ });
63
+ });
64
+ }
65
+ /**
66
+ * Execute a git command and throw a classified error on failure
67
+ *
68
+ * @param args - Git command arguments
69
+ * @param options - Execution options
70
+ * @returns ExecGitResult on success
71
+ * @throws GitError (or subclass) on failure
72
+ */
73
+ export async function execGitOrThrow(args, options = {}) {
74
+ const result = await execGit(args, options);
75
+ if (result.exitCode !== 0) {
76
+ throw classifyError(result, options.cwd ?? process.cwd());
77
+ }
78
+ return result;
79
+ }
80
+ /**
81
+ * Classify a git error based on exit code and stderr
82
+ */
83
+ export function classifyError(result, cwd, conflicts = []) {
84
+ const { exitCode, stderr, stdout, command } = result;
85
+ // Check error patterns in order of specificity
86
+ // Auth errors (exit code 128 typically)
87
+ if (isAuthError(stderr)) {
88
+ return new AuthError('Authentication failed', {
89
+ command,
90
+ exitCode,
91
+ stderr,
92
+ cwd,
93
+ });
94
+ }
95
+ // Network errors
96
+ if (isNetworkError(stderr)) {
97
+ return new NetworkError('Network error', {
98
+ command,
99
+ exitCode,
100
+ stderr,
101
+ cwd,
102
+ remote: extractRemote(stderr),
103
+ });
104
+ }
105
+ // Conflict errors (exit code 1 with conflict message)
106
+ if (isConflictError(stderr, stdout)) {
107
+ return new ConflictError('Merge conflict', {
108
+ command,
109
+ exitCode,
110
+ stderr,
111
+ cwd,
112
+ conflicts,
113
+ });
114
+ }
115
+ // Detached HEAD errors
116
+ if (isDetachedHeadError(stderr)) {
117
+ return new DetachedHeadError('HEAD is detached', {
118
+ command,
119
+ exitCode,
120
+ stderr,
121
+ cwd,
122
+ headCommit: extractHeadCommit(stderr) ?? 'unknown',
123
+ });
124
+ }
125
+ // Generic git error
126
+ return new GitError(stderr || `Command exited with code ${exitCode}`, {
127
+ command,
128
+ exitCode,
129
+ stderr,
130
+ cwd,
131
+ });
132
+ }
133
+ /**
134
+ * Extract HEAD commit from error message
135
+ */
136
+ function extractHeadCommit(stderr) {
137
+ const match = stderr.match(/head detached (?:at|from) ([a-f0-9]+)/i);
138
+ return match?.[1];
139
+ }
140
+ /**
141
+ * Check if git is available
142
+ */
143
+ export async function isGitAvailable() {
144
+ try {
145
+ const result = await execGit(['--version']);
146
+ return result.exitCode === 0;
147
+ }
148
+ catch {
149
+ return false;
150
+ }
151
+ }
152
+ /**
153
+ * Get the current git version
154
+ */
155
+ export async function getGitVersion() {
156
+ try {
157
+ const result = await execGit(['--version']);
158
+ if (result.exitCode === 0) {
159
+ const match = result.stdout.match(/git version (\d+\.\d+\.\d+)/);
160
+ return match?.[1] ?? null;
161
+ }
162
+ return null;
163
+ }
164
+ catch {
165
+ return null;
166
+ }
167
+ }
168
+ /**
169
+ * Check if the current directory is a git repository
170
+ */
171
+ export async function isGitRepository(cwd) {
172
+ try {
173
+ const result = await execGit(['rev-parse', '--git-dir'], { cwd });
174
+ return result.exitCode === 0;
175
+ }
176
+ catch {
177
+ return false;
178
+ }
179
+ }
180
+ //# sourceMappingURL=exec-git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec-git.js","sourceRoot":"","sources":["../../src/utils/exec-git.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAG5B,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,aAAa;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAc,EACd,UAA0B,EAAE;IAE5B,MAAM,EACJ,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,EACnB,OAAO,GAAG,eAAe,EACzB,GAAG,GAAG,EAAE,GACT,GAAG,OAAO,CAAC;IAEZ,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAExC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE;YACpC,GAAG;YACH,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE;YAC/B,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC5C,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC5C,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3B,MAAM,CACJ,IAAI,QAAQ,CAAC,+BAA+B,OAAO,IAAI,EAAE;gBACvD,OAAO;gBACP,QAAQ,EAAE,CAAC,CAAC;gBACZ,MAAM,EAAE,mBAAmB;gBAC3B,GAAG;aACJ,CAAC,CACH,CAAC;QACJ,CAAC,EAAE,OAAO,CAAC,CAAC;QAEZ,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC/B,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,MAAM,CACJ,IAAI,QAAQ,CAAC,wBAAwB,KAAK,CAAC,OAAO,EAAE,EAAE;gBACpD,OAAO;gBACP,QAAQ,EAAE,CAAC,CAAC;gBACZ,MAAM,EAAE,KAAK,CAAC,OAAO;gBACrB,GAAG;aACJ,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC9B,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,OAAO,CAAC;gBACN,QAAQ,EAAE,IAAI,IAAI,CAAC;gBACnB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;gBACrB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;gBACrB,OAAO;aACR,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAc,EACd,UAA0B,EAAE;IAE5B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE5C,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAqB,EACrB,GAAW,EACX,YAA4B,EAAE;IAE9B,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAErD,+CAA+C;IAE/C,wCAAwC;IACxC,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,SAAS,CAAC,uBAAuB,EAAE;YAC5C,OAAO;YACP,QAAQ;YACR,MAAM;YACN,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;IAED,iBAAiB;IACjB,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,YAAY,CAAC,eAAe,EAAE;YACvC,OAAO;YACP,QAAQ;YACR,MAAM;YACN,GAAG;YACH,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,IAAI,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,aAAa,CAAC,gBAAgB,EAAE;YACzC,OAAO;YACP,QAAQ;YACR,MAAM;YACN,GAAG;YACH,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAED,uBAAuB;IACvB,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,iBAAiB,CAAC,kBAAkB,EAAE;YAC/C,OAAO;YACP,QAAQ;YACR,MAAM;YACN,GAAG;YACH,UAAU,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,SAAS;SACnD,CAAC,CAAC;IACL,CAAC;IAED,oBAAoB;IACpB,OAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,4BAA4B,QAAQ,EAAE,EAAE;QACpE,OAAO;QACP,QAAQ;QACR,MAAM;QACN,GAAG;KACJ,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,MAAc;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CACxB,wCAAwC,CACzC,CAAC;IACF,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;QAC5C,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;QAC5C,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACjE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAY;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAC1B,CAAC,WAAW,EAAE,WAAW,CAAC,EAC1B,EAAE,GAAG,EAAE,CACR,CAAC;QACF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Parse git blame --porcelain output
3
+ */
4
+ import type { BlameResult } from '../types.js';
5
+ /**
6
+ * Parse git blame --porcelain output into BlameResult
7
+ *
8
+ * Porcelain format for each line:
9
+ * <sha1> <orig-line> <final-line> [<num-lines>]
10
+ * author <author-name>
11
+ * author-mail <author-email>
12
+ * author-time <timestamp>
13
+ * author-tz <timezone>
14
+ * committer <committer-name>
15
+ * committer-mail <committer-email>
16
+ * committer-time <timestamp>
17
+ * committer-tz <timezone>
18
+ * summary <commit-summary>
19
+ * [previous <sha1> <filename>]
20
+ * [boundary]
21
+ * filename <filename>
22
+ * <tab><content>
23
+ */
24
+ export declare function parseBlame(output: string): BlameResult;
25
+ /**
26
+ * Format blame result for display
27
+ */
28
+ export declare function formatBlame(result: BlameResult, showContent?: boolean): string;
29
+ //# sourceMappingURL=parse-blame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-blame.d.ts","sourceRoot":"","sources":["../../src/utils/parse-blame.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAkEtD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,GAAE,OAAc,GAAG,MAAM,CAapF"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Parse git blame --porcelain output
3
+ */
4
+ /**
5
+ * Parse git blame --porcelain output into BlameResult
6
+ *
7
+ * Porcelain format for each line:
8
+ * <sha1> <orig-line> <final-line> [<num-lines>]
9
+ * author <author-name>
10
+ * author-mail <author-email>
11
+ * author-time <timestamp>
12
+ * author-tz <timezone>
13
+ * committer <committer-name>
14
+ * committer-mail <committer-email>
15
+ * committer-time <timestamp>
16
+ * committer-tz <timezone>
17
+ * summary <commit-summary>
18
+ * [previous <sha1> <filename>]
19
+ * [boundary]
20
+ * filename <filename>
21
+ * <tab><content>
22
+ */
23
+ export function parseBlame(output) {
24
+ const lines = output.split('\n');
25
+ const result = { lines: [] };
26
+ let currentHash = '';
27
+ let currentAuthor = '';
28
+ let currentDate = '';
29
+ let currentLineNumber = 0;
30
+ const hashInfoCache = {};
31
+ for (let i = 0; i < lines.length; i++) {
32
+ const line = lines[i];
33
+ if (!line)
34
+ continue;
35
+ // SHA line: <sha1> <orig-line> <final-line> [<num-lines>]
36
+ const shaMatch = line.match(/^([a-f0-9]{40}) (\d+) (\d+)/);
37
+ if (shaMatch) {
38
+ currentHash = shaMatch[1] ?? '';
39
+ currentLineNumber = parseInt(shaMatch[3] ?? '0', 10);
40
+ // Check cache for hash info
41
+ const cached = hashInfoCache[currentHash];
42
+ if (cached) {
43
+ currentAuthor = cached.author;
44
+ currentDate = cached.date;
45
+ }
46
+ continue;
47
+ }
48
+ // Author line
49
+ if (line.startsWith('author ')) {
50
+ currentAuthor = line.slice(7);
51
+ continue;
52
+ }
53
+ // Author time (Unix timestamp)
54
+ if (line.startsWith('author-time ')) {
55
+ const timestamp = parseInt(line.slice(12), 10);
56
+ currentDate = new Date(timestamp * 1000).toISOString();
57
+ // Cache the hash info
58
+ if (currentHash) {
59
+ hashInfoCache[currentHash] = {
60
+ author: currentAuthor,
61
+ date: currentDate,
62
+ };
63
+ }
64
+ continue;
65
+ }
66
+ // Content line (starts with tab)
67
+ if (line.startsWith('\t')) {
68
+ const content = line.slice(1);
69
+ result.lines.push({
70
+ lineNumber: currentLineNumber,
71
+ hash: currentHash,
72
+ author: currentAuthor,
73
+ date: currentDate,
74
+ content,
75
+ });
76
+ continue;
77
+ }
78
+ }
79
+ return result;
80
+ }
81
+ /**
82
+ * Format blame result for display
83
+ */
84
+ export function formatBlame(result, showContent = true) {
85
+ return result.lines
86
+ .map((line) => {
87
+ const hash = line.hash.slice(0, 7);
88
+ const author = line.author.slice(0, 20).padEnd(20);
89
+ const lineNum = line.lineNumber.toString().padStart(4);
90
+ if (showContent) {
91
+ return `${hash} ${author} ${lineNum}: ${line.content}`;
92
+ }
93
+ return `${hash} ${author} ${lineNum}`;
94
+ })
95
+ .join('\n');
96
+ }
97
+ //# sourceMappingURL=parse-blame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-blame.js","sourceRoot":"","sources":["../../src/utils/parse-blame.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Parse git diff output
3
+ */
4
+ import type { DiffResult } from '../types.js';
5
+ /**
6
+ * Parse git diff --numstat output into DiffResult
7
+ *
8
+ * numstat format: <insertions><tab><deletions><tab><path>
9
+ * Binary files show as: -<tab>-<tab><path>
10
+ */
11
+ export declare function parseDiffNumstat(output: string): DiffResult;
12
+ /**
13
+ * Parse git diff --stat output into DiffResult
14
+ *
15
+ * stat format:
16
+ * <path> | <count> <bar>
17
+ * ...
18
+ * <n> files changed, <m> insertions(+), <p> deletions(-)
19
+ */
20
+ export declare function parseDiffStat(output: string): DiffResult;
21
+ /**
22
+ * Create a summary string from DiffResult
23
+ */
24
+ export declare function formatDiffSummary(result: DiffResult): string;
25
+ //# sourceMappingURL=parse-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-diff.d.ts","sourceRoot":"","sources":["../../src/utils/parse-diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAkC3D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAiDxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAkB5D"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Parse git diff output
3
+ */
4
+ /**
5
+ * Parse git diff --numstat output into DiffResult
6
+ *
7
+ * numstat format: <insertions><tab><deletions><tab><path>
8
+ * Binary files show as: -<tab>-<tab><path>
9
+ */
10
+ export function parseDiffNumstat(output) {
11
+ const lines = output.split('\n').filter(Boolean);
12
+ const result = {
13
+ filesChanged: 0,
14
+ insertions: 0,
15
+ deletions: 0,
16
+ files: [],
17
+ };
18
+ for (const line of lines) {
19
+ const parts = line.split('\t');
20
+ if (parts.length < 3)
21
+ continue;
22
+ const insertionsStr = parts[0];
23
+ const deletionsStr = parts[1];
24
+ const path = parts.slice(2).join('\t'); // Handle paths with tabs
25
+ const binary = insertionsStr === '-' && deletionsStr === '-';
26
+ const insertions = binary ? 0 : parseInt(insertionsStr ?? '0', 10) || 0;
27
+ const deletions = binary ? 0 : parseInt(deletionsStr ?? '0', 10) || 0;
28
+ result.filesChanged++;
29
+ result.insertions += insertions;
30
+ result.deletions += deletions;
31
+ result.files?.push({
32
+ path,
33
+ insertions,
34
+ deletions,
35
+ binary: binary ? true : undefined,
36
+ });
37
+ }
38
+ return result;
39
+ }
40
+ /**
41
+ * Parse git diff --stat output into DiffResult
42
+ *
43
+ * stat format:
44
+ * <path> | <count> <bar>
45
+ * ...
46
+ * <n> files changed, <m> insertions(+), <p> deletions(-)
47
+ */
48
+ export function parseDiffStat(output) {
49
+ const lines = output.split('\n').filter(Boolean);
50
+ const result = {
51
+ filesChanged: 0,
52
+ insertions: 0,
53
+ deletions: 0,
54
+ files: [],
55
+ };
56
+ for (const line of lines) {
57
+ // Summary line at the end
58
+ const summaryMatch = line.match(/(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?/);
59
+ if (summaryMatch) {
60
+ result.filesChanged = parseInt(summaryMatch[1] ?? '0', 10) || 0;
61
+ result.insertions = parseInt(summaryMatch[2] ?? '0', 10) || 0;
62
+ result.deletions = parseInt(summaryMatch[3] ?? '0', 10) || 0;
63
+ continue;
64
+ }
65
+ // File stat line
66
+ const fileMatch = line.match(/^\s*(.+?)\s*\|\s*(\d+|Bin)/);
67
+ if (fileMatch && fileMatch[1]) {
68
+ const path = fileMatch[1].trim();
69
+ const binary = fileMatch[2] === 'Bin';
70
+ // Count + and - characters in the visual bar
71
+ const barMatch = line.match(/\|[^|]*$/);
72
+ let insertions = 0;
73
+ let deletions = 0;
74
+ if (barMatch && !binary) {
75
+ const bar = barMatch[0];
76
+ insertions = (bar.match(/\+/g) || []).length;
77
+ deletions = (bar.match(/-/g) || []).length;
78
+ }
79
+ result.files?.push({
80
+ path,
81
+ insertions,
82
+ deletions,
83
+ binary: binary ? true : undefined,
84
+ });
85
+ }
86
+ }
87
+ return result;
88
+ }
89
+ /**
90
+ * Create a summary string from DiffResult
91
+ */
92
+ export function formatDiffSummary(result) {
93
+ const parts = [];
94
+ if (result.filesChanged > 0) {
95
+ parts.push(`${result.filesChanged} file${result.filesChanged !== 1 ? 's' : ''} changed`);
96
+ }
97
+ if (result.insertions > 0) {
98
+ parts.push(`${result.insertions} insertion${result.insertions !== 1 ? 's' : ''}(+)`);
99
+ }
100
+ if (result.deletions > 0) {
101
+ parts.push(`${result.deletions} deletion${result.deletions !== 1 ? 's' : ''}(-)`);
102
+ }
103
+ return parts.join(', ') || 'No changes';
104
+ }
105
+ //# sourceMappingURL=parse-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-diff.js","sourceRoot":"","sources":["../../src/utils/parse-diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Parse git log output
3
+ */
4
+ import type { LogResult, CommitInfo } from '../types.js';
5
+ /**
6
+ * Git log format string for structured parsing
7
+ * Fields: hash, shortHash, authorName, authorEmail, date, parents, subject, body
8
+ */
9
+ export declare const LOG_FORMAT: string;
10
+ /**
11
+ * Parse git log output with custom format into LogResult
12
+ *
13
+ * @param output - Raw git log output using LOG_FORMAT
14
+ * @param limit - The limit that was used (to determine hasMore)
15
+ */
16
+ export declare function parseLog(output: string, limit?: number): LogResult;
17
+ /**
18
+ * Parse a simplified log format (one commit per line)
19
+ * Format: <hash> <subject>
20
+ */
21
+ export declare function parseSimpleLog(output: string): Array<{
22
+ hash: string;
23
+ subject: string;
24
+ }>;
25
+ /**
26
+ * Format commit info for display
27
+ */
28
+ export declare function formatCommit(commit: CommitInfo): string;
29
+ /**
30
+ * Format log result as a simple list
31
+ */
32
+ export declare function formatLogList(result: LogResult): string;
33
+ //# sourceMappingURL=parse-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-log.d.ts","sourceRoot":"","sources":["../../src/utils/parse-log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQzD;;;GAGG;AACH,eAAO,MAAM,UAAU,QASmB,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,SAAS,CAgCtE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAavF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAEvD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMvD"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Parse git log output
3
+ */
4
+ /**
5
+ * Delimiter for log format fields (unlikely to appear in commit messages)
6
+ */
7
+ const FIELD_DELIMITER = '\x1f'; // ASCII Unit Separator
8
+ const RECORD_DELIMITER = '\x1e'; // ASCII Record Separator
9
+ /**
10
+ * Git log format string for structured parsing
11
+ * Fields: hash, shortHash, authorName, authorEmail, date, parents, subject, body
12
+ */
13
+ export const LOG_FORMAT = [
14
+ '%H', // hash
15
+ '%h', // shortHash
16
+ '%an', // authorName
17
+ '%ae', // authorEmail
18
+ '%aI', // date (ISO 8601)
19
+ '%P', // parents (space-separated)
20
+ '%s', // subject
21
+ '%b', // body
22
+ ].join(FIELD_DELIMITER) + RECORD_DELIMITER;
23
+ /**
24
+ * Parse git log output with custom format into LogResult
25
+ *
26
+ * @param output - Raw git log output using LOG_FORMAT
27
+ * @param limit - The limit that was used (to determine hasMore)
28
+ */
29
+ export function parseLog(output, limit = 10) {
30
+ const records = output.split(RECORD_DELIMITER).filter(Boolean);
31
+ const commits = [];
32
+ for (const record of records) {
33
+ const fields = record.trim().split(FIELD_DELIMITER);
34
+ if (fields.length < 6)
35
+ continue;
36
+ const [hash, shortHash, authorName, authorEmail, date, parentsStr, subject, ...bodyParts] = fields;
37
+ if (!hash || !shortHash)
38
+ continue;
39
+ const parents = parentsStr ? parentsStr.split(' ').filter(Boolean) : [];
40
+ const body = bodyParts.join(FIELD_DELIMITER).trim() || undefined;
41
+ commits.push({
42
+ hash,
43
+ shortHash,
44
+ authorName: authorName ?? '',
45
+ authorEmail: authorEmail ?? '',
46
+ date: date ?? '',
47
+ parents,
48
+ subject: subject ?? '',
49
+ body,
50
+ });
51
+ }
52
+ return {
53
+ commits,
54
+ hasMore: commits.length >= limit,
55
+ };
56
+ }
57
+ /**
58
+ * Parse a simplified log format (one commit per line)
59
+ * Format: <hash> <subject>
60
+ */
61
+ export function parseSimpleLog(output) {
62
+ const lines = output.split('\n').filter(Boolean);
63
+ return lines.map((line) => {
64
+ const spaceIndex = line.indexOf(' ');
65
+ if (spaceIndex === -1) {
66
+ return { hash: line, subject: '' };
67
+ }
68
+ return {
69
+ hash: line.slice(0, spaceIndex),
70
+ subject: line.slice(spaceIndex + 1),
71
+ };
72
+ });
73
+ }
74
+ /**
75
+ * Format commit info for display
76
+ */
77
+ export function formatCommit(commit) {
78
+ return `${commit.shortHash} ${commit.subject}`;
79
+ }
80
+ /**
81
+ * Format log result as a simple list
82
+ */
83
+ export function formatLogList(result) {
84
+ const lines = result.commits.map(formatCommit);
85
+ if (result.hasMore) {
86
+ lines.push('...');
87
+ }
88
+ return lines.join('\n');
89
+ }
90
+ //# sourceMappingURL=parse-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-log.js","sourceRoot":"","sources":["../../src/utils/parse-log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,uBAAuB;AACvD,MAAM,gBAAgB,GAAG,MAAM,CAAC,CAAC,yBAAyB;AAE1D;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,aAAa;IACpB,KAAK,EAAE,cAAc;IACrB,KAAK,EAAE,kBAAkB;IACzB,IAAI,EAAE,4BAA4B;IAClC,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,OAAO;CACd,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,gBAAgB,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,QAAgB,EAAE;IACzD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE/D,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAEhC,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC;QAEnG,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS;YAAE,SAAS;QAElC,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;QAEjE,OAAO,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,SAAS;YACT,UAAU,EAAE,UAAU,IAAI,EAAE;YAC5B,WAAW,EAAE,WAAW,IAAI,EAAE;YAC9B,IAAI,EAAE,IAAI,IAAI,EAAE;YAChB,OAAO;YACP,OAAO,EAAE,OAAO,IAAI,EAAE;YACtB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,OAAO;QACP,OAAO,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;KACjC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACrC,CAAC;QACD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;YAC/B,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;SACpC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,OAAO,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAAiB;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Parse git status --porcelain=v2 output
3
+ */
4
+ import type { StatusResult } from '../types.js';
5
+ /**
6
+ * Parse git status --porcelain=v2 output into structured StatusResult
7
+ *
8
+ * Porcelain v2 format:
9
+ * - Header lines start with #
10
+ * - # branch.oid <commit>
11
+ * - # branch.head <branch>
12
+ * - # branch.upstream <upstream>
13
+ * - # branch.ab +<ahead> -<behind>
14
+ * - Changed entries:
15
+ * - 1 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <path>
16
+ * - 2 <XY> <sub> <mH> <mI> <mW> <hH> <hI> <X><score> <path><tab><origPath>
17
+ * - Untracked: ? <path>
18
+ * - Ignored: ! <path>
19
+ * - Unmerged: u <XY> <sub> <m1> <m2> <m3> <mW> <h1> <h2> <h3> <path>
20
+ */
21
+ export declare function parseStatus(output: string): StatusResult;
22
+ //# sourceMappingURL=parse-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-status.d.ts","sourceRoot":"","sources":["../../src/utils/parse-status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAmDxD"}