@caupulican/pi-adaptative 0.76.1 → 0.77.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 +55 -0
- package/README.md +9 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +4 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +25 -4
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts +2 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +26 -0
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +8 -2
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +7 -5
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +65 -13
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +9 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +134 -11
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/sdk.d.ts +2 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -5
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +42 -17
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +0 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +175 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -0
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-encoding-policy.d.ts +19 -0
- package/dist/core/tools/file-encoding-policy.d.ts.map +1 -0
- package/dist/core/tools/file-encoding-policy.js +54 -0
- package/dist/core/tools/file-encoding-policy.js.map +1 -0
- package/dist/core/tools/find.d.ts +1 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +77 -60
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/git-filter.d.ts +41 -0
- package/dist/core/tools/git-filter.d.ts.map +1 -0
- package/dist/core/tools/git-filter.js +660 -0
- package/dist/core/tools/git-filter.js.map +1 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +28 -3
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts +7 -5
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +39 -5
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +3 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +98 -13
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +2 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +23 -3
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +15 -2
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +118 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +1 -3
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +2 -4
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +51 -6
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +10 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/docs/custom-provider.md +13 -10
- package/docs/extensions.md +12 -6
- package/docs/models.md +25 -12
- package/docs/providers.md +13 -5
- package/docs/quickstart.md +1 -0
- package/docs/rpc.md +2 -1
- package/docs/sdk.md +6 -0
- package/docs/session-format.md +1 -1
- package/docs/sessions.md +8 -0
- package/docs/usage.md +9 -0
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +56 -56
- package/package.json +5 -5
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { waitForChildProcess } from "../../utils/child-process.js";
|
|
5
|
+
import { killProcessTree, trackDetachedChildPid, untrackDetachedChildPid } from "../../utils/shell.js";
|
|
6
|
+
const SUPPORTED_SUBCOMMANDS = new Set([
|
|
7
|
+
"status",
|
|
8
|
+
"log",
|
|
9
|
+
"diff",
|
|
10
|
+
"show",
|
|
11
|
+
"add",
|
|
12
|
+
"commit",
|
|
13
|
+
"push",
|
|
14
|
+
"pull",
|
|
15
|
+
"branch",
|
|
16
|
+
"fetch",
|
|
17
|
+
"stash",
|
|
18
|
+
"worktree",
|
|
19
|
+
]);
|
|
20
|
+
export function unicodeTruncate(str, maxLength) {
|
|
21
|
+
const chars = Array.from(str);
|
|
22
|
+
if (chars.length <= maxLength)
|
|
23
|
+
return str;
|
|
24
|
+
return `${chars.slice(0, maxLength).join("")}...`;
|
|
25
|
+
}
|
|
26
|
+
export function tokenizeCommand(command) {
|
|
27
|
+
const args = [];
|
|
28
|
+
let current = "";
|
|
29
|
+
let inDoubleQuotes = false;
|
|
30
|
+
let inSingleQuotes = false;
|
|
31
|
+
let escapeNext = false;
|
|
32
|
+
for (let i = 0; i < command.length; i++) {
|
|
33
|
+
const char = command[i];
|
|
34
|
+
if (escapeNext) {
|
|
35
|
+
current += char;
|
|
36
|
+
escapeNext = false;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (char === "\\" && !inSingleQuotes) {
|
|
40
|
+
escapeNext = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (char === '"' && !inSingleQuotes) {
|
|
44
|
+
inDoubleQuotes = !inDoubleQuotes;
|
|
45
|
+
}
|
|
46
|
+
else if (char === "'" && !inDoubleQuotes) {
|
|
47
|
+
inSingleQuotes = !inSingleQuotes;
|
|
48
|
+
}
|
|
49
|
+
else if (/\s/.test(char) && !inDoubleQuotes && !inSingleQuotes) {
|
|
50
|
+
if (current) {
|
|
51
|
+
args.push(current);
|
|
52
|
+
current = "";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
current += char;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (inDoubleQuotes || inSingleQuotes || escapeNext)
|
|
60
|
+
return null;
|
|
61
|
+
if (current)
|
|
62
|
+
args.push(current);
|
|
63
|
+
return args;
|
|
64
|
+
}
|
|
65
|
+
export function parseCommandPrefixes(command) {
|
|
66
|
+
const tokens = tokenizeCommand(command);
|
|
67
|
+
if (!tokens || tokens.length === 0)
|
|
68
|
+
return null;
|
|
69
|
+
const envVars = {};
|
|
70
|
+
let i = 0;
|
|
71
|
+
const envPattern = /^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/;
|
|
72
|
+
while (i < tokens.length) {
|
|
73
|
+
const token = tokens[i];
|
|
74
|
+
const match = token.match(envPattern);
|
|
75
|
+
if (!match)
|
|
76
|
+
break;
|
|
77
|
+
let value = match[2];
|
|
78
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
79
|
+
value = value.slice(1, -1);
|
|
80
|
+
}
|
|
81
|
+
envVars[match[1]] = value;
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
return { envVars, coreCommandTokens: tokens.slice(i) };
|
|
85
|
+
}
|
|
86
|
+
export function isComplexShellCommand(command) {
|
|
87
|
+
return /[|><&;\n\r$`()*?[\]#]/.test(command);
|
|
88
|
+
}
|
|
89
|
+
function quoteForShell(arg) {
|
|
90
|
+
if (/^[A-Za-z0-9_./:=+-]+$/.test(arg))
|
|
91
|
+
return arg;
|
|
92
|
+
return `'${arg.replace(/'/g, `'"'"'`)}'`;
|
|
93
|
+
}
|
|
94
|
+
function gitCommand(globalOptions, args) {
|
|
95
|
+
return ["git", ...globalOptions, ...args].map(quoteForShell).join(" ");
|
|
96
|
+
}
|
|
97
|
+
function rawText(res, combine = false) {
|
|
98
|
+
if (combine)
|
|
99
|
+
return `${res.stderr}${res.stderr && res.stdout ? "\n" : ""}${res.stdout}`;
|
|
100
|
+
return res.stderr || res.stdout;
|
|
101
|
+
}
|
|
102
|
+
function resultFromQuery(res, output, exitCode = res.status ?? 0) {
|
|
103
|
+
return { output, exitCode, rawOut: rawText(res), rawBytes: res.rawBytes };
|
|
104
|
+
}
|
|
105
|
+
export async function runGitQuery(cwd, globalOptions, args, options) {
|
|
106
|
+
if (options?.signal?.aborted)
|
|
107
|
+
throw new Error("aborted");
|
|
108
|
+
const child = spawn("git", [...globalOptions, ...args], {
|
|
109
|
+
cwd,
|
|
110
|
+
detached: process.platform !== "win32",
|
|
111
|
+
env: { ...process.env, LC_ALL: "C" },
|
|
112
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
113
|
+
windowsHide: true,
|
|
114
|
+
});
|
|
115
|
+
if (child.pid)
|
|
116
|
+
trackDetachedChildPid(child.pid);
|
|
117
|
+
const stdoutChunks = [];
|
|
118
|
+
const stderrChunks = [];
|
|
119
|
+
let timedOut = false;
|
|
120
|
+
const timeoutSeconds = options?.timeout;
|
|
121
|
+
let timeoutHandle;
|
|
122
|
+
const killChild = () => {
|
|
123
|
+
if (child.pid)
|
|
124
|
+
killProcessTree(child.pid);
|
|
125
|
+
};
|
|
126
|
+
try {
|
|
127
|
+
if (timeoutSeconds !== undefined && timeoutSeconds > 0) {
|
|
128
|
+
timeoutHandle = setTimeout(() => {
|
|
129
|
+
timedOut = true;
|
|
130
|
+
killChild();
|
|
131
|
+
}, timeoutSeconds * 1000);
|
|
132
|
+
}
|
|
133
|
+
if (options?.signal) {
|
|
134
|
+
if (options.signal.aborted)
|
|
135
|
+
killChild();
|
|
136
|
+
else
|
|
137
|
+
options.signal.addEventListener("abort", killChild, { once: true });
|
|
138
|
+
}
|
|
139
|
+
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
140
|
+
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
141
|
+
const status = await waitForChildProcess(child);
|
|
142
|
+
if (options?.signal?.aborted)
|
|
143
|
+
throw new Error("aborted");
|
|
144
|
+
if (timedOut)
|
|
145
|
+
throw new Error(`timeout:${timeoutSeconds}`);
|
|
146
|
+
const stdoutBuffer = Buffer.concat(stdoutChunks);
|
|
147
|
+
const stderrBuffer = Buffer.concat(stderrChunks);
|
|
148
|
+
const rawBytes = Buffer.concat([stderrBuffer, stdoutBuffer]);
|
|
149
|
+
return {
|
|
150
|
+
stdout: stdoutBuffer.toString("utf-8"),
|
|
151
|
+
stderr: stderrBuffer.toString("utf-8"),
|
|
152
|
+
status,
|
|
153
|
+
rawBytes,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
if (child.pid)
|
|
158
|
+
untrackDetachedChildPid(child.pid);
|
|
159
|
+
if (timeoutHandle)
|
|
160
|
+
clearTimeout(timeoutHandle);
|
|
161
|
+
if (options?.signal)
|
|
162
|
+
options.signal.removeEventListener("abort", killChild);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
export function classifyGitCommand(command, parentEnv) {
|
|
166
|
+
if (isComplexShellCommand(command))
|
|
167
|
+
return { eligible: false };
|
|
168
|
+
const parsed = parseCommandPrefixes(command);
|
|
169
|
+
if (!parsed || parsed.coreCommandTokens.length === 0)
|
|
170
|
+
return { eligible: false };
|
|
171
|
+
const { envVars, coreCommandTokens } = parsed;
|
|
172
|
+
const toolFilterDisabled = process.env.PI_TOOL_FILTER_DISABLED === "1" ||
|
|
173
|
+
parentEnv?.PI_TOOL_FILTER_DISABLED === "1" ||
|
|
174
|
+
envVars.PI_TOOL_FILTER_DISABLED === "1";
|
|
175
|
+
const gitFilterDisabled = process.env.PI_GIT_FILTER_DISABLED === "1" ||
|
|
176
|
+
parentEnv?.PI_GIT_FILTER_DISABLED === "1" ||
|
|
177
|
+
envVars.PI_GIT_FILTER_DISABLED === "1";
|
|
178
|
+
if (toolFilterDisabled || gitFilterDisabled)
|
|
179
|
+
return { eligible: false };
|
|
180
|
+
const envKeys = Object.keys(envVars).filter((key) => key !== "PI_TOOL_FILTER_DISABLED" && key !== "PI_GIT_FILTER_DISABLED");
|
|
181
|
+
if (envKeys.length > 0)
|
|
182
|
+
return { eligible: false };
|
|
183
|
+
const cmdName = coreCommandTokens[0];
|
|
184
|
+
if (cmdName !== "git" && cmdName !== "yadm")
|
|
185
|
+
return { eligible: false };
|
|
186
|
+
let idx = 1;
|
|
187
|
+
const globalOptions = [];
|
|
188
|
+
while (idx < coreCommandTokens.length) {
|
|
189
|
+
const token = coreCommandTokens[idx];
|
|
190
|
+
if (token === "-C" || token === "-c" || token === "--git-dir" || token === "--work-tree") {
|
|
191
|
+
if (idx + 1 >= coreCommandTokens.length)
|
|
192
|
+
return { eligible: false };
|
|
193
|
+
globalOptions.push(token, coreCommandTokens[idx + 1]);
|
|
194
|
+
idx += 2;
|
|
195
|
+
}
|
|
196
|
+
else if (token.startsWith("--git-dir=") || token.startsWith("--work-tree=")) {
|
|
197
|
+
globalOptions.push(token);
|
|
198
|
+
idx++;
|
|
199
|
+
}
|
|
200
|
+
else if (token === "--no-pager" ||
|
|
201
|
+
token === "--no-optional-locks" ||
|
|
202
|
+
token === "--bare" ||
|
|
203
|
+
token === "--literal-pathspecs") {
|
|
204
|
+
globalOptions.push(token);
|
|
205
|
+
idx++;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (idx === coreCommandTokens.length)
|
|
212
|
+
return { eligible: false };
|
|
213
|
+
const subcommand = coreCommandTokens[idx];
|
|
214
|
+
if (!SUPPORTED_SUBCOMMANDS.has(subcommand))
|
|
215
|
+
return { eligible: false };
|
|
216
|
+
return {
|
|
217
|
+
eligible: true,
|
|
218
|
+
subcommand,
|
|
219
|
+
globalOptions,
|
|
220
|
+
subcommandArgs: coreCommandTokens.slice(idx + 1),
|
|
221
|
+
localEnv: envVars,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
export function detectGitState(gitDir) {
|
|
225
|
+
const states = [];
|
|
226
|
+
if (!gitDir)
|
|
227
|
+
return states;
|
|
228
|
+
if (existsSync(join(gitDir, "rebase-merge")) || existsSync(join(gitDir, "rebase-apply"))) {
|
|
229
|
+
states.push("rebase in progress");
|
|
230
|
+
}
|
|
231
|
+
if (existsSync(join(gitDir, "MERGE_HEAD")))
|
|
232
|
+
states.push("merge in progress");
|
|
233
|
+
if (existsSync(join(gitDir, "CHERRY_PICK_HEAD")))
|
|
234
|
+
states.push("cherry-pick in progress");
|
|
235
|
+
if (existsSync(join(gitDir, "REVERT_HEAD")))
|
|
236
|
+
states.push("revert in progress");
|
|
237
|
+
if (existsSync(join(gitDir, "BISECT_LOG")))
|
|
238
|
+
states.push("bisect in progress");
|
|
239
|
+
if (existsSync(join(gitDir, "applying")))
|
|
240
|
+
states.push("am in progress");
|
|
241
|
+
return states;
|
|
242
|
+
}
|
|
243
|
+
async function handleStatus(cwd, globalOptions, args, options) {
|
|
244
|
+
const isSimple = args.length === 0 || args.every((arg) => arg === "-s" || arg === "--short" || arg === "-b" || arg === "--branch");
|
|
245
|
+
if (!isSimple) {
|
|
246
|
+
const res = await runGitQuery(cwd, globalOptions, ["status", ...args], options);
|
|
247
|
+
const rawOut = rawText(res);
|
|
248
|
+
if (res.status !== 0)
|
|
249
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
250
|
+
const cleanedLines = res.stdout
|
|
251
|
+
.split("\n")
|
|
252
|
+
.map((line) => line.trimEnd())
|
|
253
|
+
.filter((line) => line.length > 0 && !line.trim().startsWith("(use "));
|
|
254
|
+
const output = cleanedLines.join("\n");
|
|
255
|
+
return resultFromQuery(res, output || "success", 0);
|
|
256
|
+
}
|
|
257
|
+
const res = await runGitQuery(cwd, globalOptions, ["status", "--porcelain=v1", "-b"], options);
|
|
258
|
+
let rawOut = rawText(res);
|
|
259
|
+
if (res.status !== 0) {
|
|
260
|
+
if (rawOut.includes("not a git repository"))
|
|
261
|
+
rawOut = "fatal: not a git repository";
|
|
262
|
+
return { output: rawOut.trim(), exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
263
|
+
}
|
|
264
|
+
const lines = res.stdout.split("\n").filter((line) => line.trim().length > 0);
|
|
265
|
+
let branchLine = "";
|
|
266
|
+
const fileLines = [];
|
|
267
|
+
for (const line of lines) {
|
|
268
|
+
if (line.startsWith("##"))
|
|
269
|
+
branchLine = line;
|
|
270
|
+
else
|
|
271
|
+
fileLines.push(line);
|
|
272
|
+
}
|
|
273
|
+
let statePrefix = "";
|
|
274
|
+
const gitDirRes = await runGitQuery(cwd, globalOptions, ["rev-parse", "--git-dir"], options);
|
|
275
|
+
if (gitDirRes.status === 0) {
|
|
276
|
+
const gitDir = resolve(cwd, gitDirRes.stdout.trim());
|
|
277
|
+
const states = detectGitState(gitDir);
|
|
278
|
+
if (states.length > 0)
|
|
279
|
+
statePrefix = `[${states.join(", ")}]\n`;
|
|
280
|
+
}
|
|
281
|
+
if (branchLine.includes("HEAD (no branch)")) {
|
|
282
|
+
const headHashRes = await runGitQuery(cwd, globalOptions, ["rev-parse", "--short", "HEAD"], options);
|
|
283
|
+
const hash = headHashRes.status === 0 ? headHashRes.stdout.trim() : "unknown";
|
|
284
|
+
branchLine = `## HEAD (detached at ${hash})`;
|
|
285
|
+
}
|
|
286
|
+
if (fileLines.length === 0) {
|
|
287
|
+
return resultFromQuery(res, `${statePrefix}${branchLine}\nnothing to commit, working tree clean`, 0);
|
|
288
|
+
}
|
|
289
|
+
return resultFromQuery(res, `${statePrefix}${branchLine}\n${fileLines.join("\n")}`, 0);
|
|
290
|
+
}
|
|
291
|
+
async function handleLog(cwd, globalOptions, args, options) {
|
|
292
|
+
const hasLimit = args.some((arg) => /^-n\d+$/.test(arg) || arg === "-n" || /^-?\d+$/.test(arg) || arg.startsWith("--max-count"));
|
|
293
|
+
const hasPretty = args.some((arg) => arg.startsWith("--pretty") || arg.startsWith("--format") || arg === "--oneline");
|
|
294
|
+
if (hasLimit || hasPretty) {
|
|
295
|
+
const res = await runGitQuery(cwd, globalOptions, ["log", ...args], options);
|
|
296
|
+
return resultFromQuery(res, rawText(res), res.status ?? 0);
|
|
297
|
+
}
|
|
298
|
+
const res = await runGitQuery(cwd, globalOptions, ["log", "-n", "10", "--no-merges"], options);
|
|
299
|
+
const rawOut = rawText(res);
|
|
300
|
+
if (res.status !== 0)
|
|
301
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
302
|
+
const commits = res.stdout.split(/(?=^commit [0-9a-f]{7,40})/m).filter((commit) => commit.trim().length > 0);
|
|
303
|
+
const compactedCommits = [];
|
|
304
|
+
const trailerPrefixes = [
|
|
305
|
+
"Signed-off-by:",
|
|
306
|
+
"Co-authored-by:",
|
|
307
|
+
"Reported-by:",
|
|
308
|
+
"Reviewed-by:",
|
|
309
|
+
"Tested-by:",
|
|
310
|
+
"Suggested-by:",
|
|
311
|
+
"CC:",
|
|
312
|
+
];
|
|
313
|
+
for (const commit of commits) {
|
|
314
|
+
const lines = commit.split("\n");
|
|
315
|
+
const commitLine = lines[0];
|
|
316
|
+
if (!commitLine)
|
|
317
|
+
continue;
|
|
318
|
+
const shortCommitLine = commitLine.replace(/^commit ([0-9a-f]{7})[0-9a-f]+/, "commit $1");
|
|
319
|
+
const bodyLines = [];
|
|
320
|
+
for (let i = 1; i < lines.length; i++) {
|
|
321
|
+
const line = lines[i];
|
|
322
|
+
const trimmed = line.trim();
|
|
323
|
+
if (!trimmed)
|
|
324
|
+
continue;
|
|
325
|
+
if (line.startsWith("Author:") || line.startsWith("Date:") || line.startsWith("Merge:"))
|
|
326
|
+
continue;
|
|
327
|
+
if (trailerPrefixes.some((prefix) => trimmed.startsWith(prefix)))
|
|
328
|
+
continue;
|
|
329
|
+
bodyLines.push(line);
|
|
330
|
+
}
|
|
331
|
+
const displayBody = bodyLines.slice(0, 3).map((line) => unicodeTruncate(line, 160));
|
|
332
|
+
const omitted = bodyLines.length - displayBody.length;
|
|
333
|
+
if (omitted > 0)
|
|
334
|
+
displayBody.push(` ... (${omitted} lines omitted)`);
|
|
335
|
+
compactedCommits.push(`${shortCommitLine}\n${displayBody.join("\n")}`);
|
|
336
|
+
}
|
|
337
|
+
return resultFromQuery(res, compactedCommits.join("\n\n"), 0);
|
|
338
|
+
}
|
|
339
|
+
export function compactDiff(diffOutput, maxLines = 150) {
|
|
340
|
+
const lines = diffOutput.split("\n");
|
|
341
|
+
const output = [];
|
|
342
|
+
let linesCount = 0;
|
|
343
|
+
let truncated = false;
|
|
344
|
+
let contextBuffer = [];
|
|
345
|
+
let trailingContextRemaining = 0;
|
|
346
|
+
for (const line of lines) {
|
|
347
|
+
if (linesCount >= maxLines) {
|
|
348
|
+
truncated = true;
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
if (line.startsWith("diff --git") ||
|
|
352
|
+
line.startsWith("--- ") ||
|
|
353
|
+
line.startsWith("+++ ") ||
|
|
354
|
+
line.startsWith("index ")) {
|
|
355
|
+
contextBuffer = [];
|
|
356
|
+
trailingContextRemaining = 0;
|
|
357
|
+
output.push(line);
|
|
358
|
+
linesCount++;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (line.startsWith("@@ ")) {
|
|
362
|
+
contextBuffer = [];
|
|
363
|
+
trailingContextRemaining = 0;
|
|
364
|
+
output.push(line);
|
|
365
|
+
linesCount++;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (line.startsWith("+") || line.startsWith("-")) {
|
|
369
|
+
for (const ctx of contextBuffer) {
|
|
370
|
+
if (linesCount >= maxLines) {
|
|
371
|
+
truncated = true;
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
output.push(ctx);
|
|
375
|
+
linesCount++;
|
|
376
|
+
}
|
|
377
|
+
contextBuffer = [];
|
|
378
|
+
if (truncated)
|
|
379
|
+
break;
|
|
380
|
+
output.push(line);
|
|
381
|
+
linesCount++;
|
|
382
|
+
trailingContextRemaining = 3;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
if (line.startsWith(" ")) {
|
|
386
|
+
if (trailingContextRemaining > 0) {
|
|
387
|
+
output.push(line);
|
|
388
|
+
linesCount++;
|
|
389
|
+
trailingContextRemaining--;
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
contextBuffer.push(line);
|
|
393
|
+
if (contextBuffer.length > 3)
|
|
394
|
+
contextBuffer.shift();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
output.push(line);
|
|
399
|
+
linesCount++;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return { compacted: output.join("\n"), truncated };
|
|
403
|
+
}
|
|
404
|
+
async function handleDiff(cwd, globalOptions, args, options) {
|
|
405
|
+
const cleanArgs = [...args];
|
|
406
|
+
const noCompactIndex = cleanArgs.indexOf("--no-compact");
|
|
407
|
+
const optOut = noCompactIndex !== -1;
|
|
408
|
+
if (optOut)
|
|
409
|
+
cleanArgs.splice(noCompactIndex, 1);
|
|
410
|
+
const statFlags = ["--stat", "--numstat", "--shortstat", "--summary", "--name-only", "--name-status", "--check"];
|
|
411
|
+
const isStatOnly = cleanArgs.some((arg) => statFlags.includes(arg));
|
|
412
|
+
if (optOut || isStatOnly) {
|
|
413
|
+
const res = await runGitQuery(cwd, globalOptions, ["diff", ...cleanArgs], options);
|
|
414
|
+
return resultFromQuery(res, rawText(res), res.status ?? 0);
|
|
415
|
+
}
|
|
416
|
+
const hasDoubleDash = cleanArgs.includes("--");
|
|
417
|
+
if (!hasDoubleDash) {
|
|
418
|
+
const pathIdx = cleanArgs.findIndex((arg) => {
|
|
419
|
+
if (arg.startsWith("-"))
|
|
420
|
+
return false;
|
|
421
|
+
if (!(arg.includes("/") || arg.includes(".") || existsSync(join(cwd, arg))))
|
|
422
|
+
return false;
|
|
423
|
+
return existsSync(resolve(cwd, arg));
|
|
424
|
+
});
|
|
425
|
+
if (pathIdx !== -1)
|
|
426
|
+
cleanArgs.splice(pathIdx, 0, "--");
|
|
427
|
+
}
|
|
428
|
+
const statRes = await runGitQuery(cwd, globalOptions, ["diff", "--stat", ...cleanArgs], options);
|
|
429
|
+
if (statRes.status !== 0)
|
|
430
|
+
return resultFromQuery(statRes, rawText(statRes), statRes.status ?? 1);
|
|
431
|
+
const diffRes = await runGitQuery(cwd, globalOptions, ["diff", ...cleanArgs], options);
|
|
432
|
+
if (diffRes.status !== 0)
|
|
433
|
+
return resultFromQuery(diffRes, rawText(diffRes), diffRes.status ?? 1);
|
|
434
|
+
const { compacted, truncated } = compactDiff(diffRes.stdout);
|
|
435
|
+
let output = `${statRes.stdout.trimEnd()}\n\n${compacted}`.trim();
|
|
436
|
+
if (truncated)
|
|
437
|
+
output += "\n\n[Diff truncated. Re-run with: git diff --no-compact]";
|
|
438
|
+
return { output, exitCode: 0, rawOut: diffRes.stdout, rawBytes: diffRes.rawBytes };
|
|
439
|
+
}
|
|
440
|
+
async function handleShow(cwd, globalOptions, args, options) {
|
|
441
|
+
const statFlags = ["--stat", "--numstat", "--shortstat", "--summary", "--name-only", "--name-status", "--check"];
|
|
442
|
+
const hasStatOnly = args.some((arg) => statFlags.includes(arg));
|
|
443
|
+
const hasPretty = args.some((arg) => arg.startsWith("--pretty") || arg.startsWith("--format") || arg === "--oneline");
|
|
444
|
+
const hasBlob = args.some((arg) => !arg.startsWith("-") && arg.includes(":"));
|
|
445
|
+
if (hasStatOnly || hasPretty || hasBlob) {
|
|
446
|
+
const res = await runGitQuery(cwd, globalOptions, ["show", ...args], options);
|
|
447
|
+
return resultFromQuery(res, rawText(res), res.status ?? 0);
|
|
448
|
+
}
|
|
449
|
+
const showRes = await runGitQuery(cwd, globalOptions, ["show", ...args], options);
|
|
450
|
+
const rawOut = rawText(showRes);
|
|
451
|
+
if (showRes.status !== 0)
|
|
452
|
+
return { output: rawOut, exitCode: showRes.status ?? 1, rawOut, rawBytes: showRes.rawBytes };
|
|
453
|
+
const lines = showRes.stdout.split("\n");
|
|
454
|
+
const diffStart = lines.findIndex((line) => line.startsWith("diff --git"));
|
|
455
|
+
const headerLines = diffStart === -1 ? lines : lines.slice(0, diffStart);
|
|
456
|
+
const diffLines = diffStart === -1 ? [] : lines.slice(diffStart);
|
|
457
|
+
const summaryLines = headerLines.filter((line) => {
|
|
458
|
+
const trimmed = line.trim();
|
|
459
|
+
if (!trimmed)
|
|
460
|
+
return false;
|
|
461
|
+
if (line.startsWith("Author:") || line.startsWith("Date:") || line.startsWith("Merge:"))
|
|
462
|
+
return false;
|
|
463
|
+
return true;
|
|
464
|
+
});
|
|
465
|
+
const shortSummary = summaryLines
|
|
466
|
+
.slice(0, 4)
|
|
467
|
+
.map((line) => unicodeTruncate(line.replace(/^commit ([0-9a-f]{7})[0-9a-f]+/, "commit $1"), 160));
|
|
468
|
+
const { compacted, truncated } = compactDiff(diffLines.join("\n"));
|
|
469
|
+
let output = shortSummary.join("\n");
|
|
470
|
+
if (compacted.trim())
|
|
471
|
+
output += `\n\n${compacted}`;
|
|
472
|
+
if (truncated)
|
|
473
|
+
output += "\n\n[Diff truncated.]";
|
|
474
|
+
return resultFromQuery(showRes, output.trim(), 0);
|
|
475
|
+
}
|
|
476
|
+
async function handlePassthroughGit(cwd, globalOptions, args, options) {
|
|
477
|
+
const res = await runGitQuery(cwd, globalOptions, args, options);
|
|
478
|
+
return resultFromQuery(res, rawText(res, true).trim(), res.status ?? 0);
|
|
479
|
+
}
|
|
480
|
+
async function handleAdd(cwd, globalOptions, args, options) {
|
|
481
|
+
if (args.length === 0)
|
|
482
|
+
return handlePassthroughGit(cwd, globalOptions, ["add"], options);
|
|
483
|
+
const addRes = await runGitQuery(cwd, globalOptions, ["add", ...args], options);
|
|
484
|
+
const rawOut = rawText(addRes);
|
|
485
|
+
if (addRes.status !== 0)
|
|
486
|
+
return { output: rawOut, exitCode: addRes.status ?? 1, rawOut, rawBytes: addRes.rawBytes };
|
|
487
|
+
const statRes = await runGitQuery(cwd, globalOptions, ["diff", "--cached", "--stat"], options);
|
|
488
|
+
if (statRes.status === 0 && statRes.stdout.trim().length > 0) {
|
|
489
|
+
return { output: `Staged changes:\n${statRes.stdout.trim()}`, exitCode: 0, rawOut, rawBytes: addRes.rawBytes };
|
|
490
|
+
}
|
|
491
|
+
return { output: rawOut.trim() || "Successfully staged.", exitCode: 0, rawOut, rawBytes: addRes.rawBytes };
|
|
492
|
+
}
|
|
493
|
+
async function handleCommit(cwd, globalOptions, args, options) {
|
|
494
|
+
const hasMsg = args.some((arg) => arg === "-m" || arg === "-F" || arg.startsWith("--message") || arg.startsWith("--file"));
|
|
495
|
+
if (!hasMsg)
|
|
496
|
+
return { output: "", exitCode: -100, rawOut: "" };
|
|
497
|
+
const res = await runGitQuery(cwd, globalOptions, ["commit", ...args], options);
|
|
498
|
+
const rawOut = rawText(res, true);
|
|
499
|
+
if (res.status !== 0)
|
|
500
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
501
|
+
if (rawOut.includes("nothing to commit") || rawOut.includes("working tree clean")) {
|
|
502
|
+
return { output: "nothing to commit, working tree clean", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
503
|
+
}
|
|
504
|
+
const firstLine = rawOut
|
|
505
|
+
.split("\n")
|
|
506
|
+
.find((line) => line.trim().length > 0)
|
|
507
|
+
?.trim();
|
|
508
|
+
return { output: firstLine || "Committed successfully.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
509
|
+
}
|
|
510
|
+
async function handlePush(cwd, globalOptions, args, options) {
|
|
511
|
+
const res = await runGitQuery(cwd, globalOptions, ["push", ...args], options);
|
|
512
|
+
const rawOut = rawText(res, true);
|
|
513
|
+
const outputLines = rawOut
|
|
514
|
+
.split("\n")
|
|
515
|
+
.map((line) => line.trimEnd())
|
|
516
|
+
.filter((line) => {
|
|
517
|
+
const trimmed = line.trim();
|
|
518
|
+
if (!trimmed)
|
|
519
|
+
return false;
|
|
520
|
+
return !["Writing objects:", "Counting objects:", "Delta compression", "Compressing objects:", "Total "].some((prefix) => trimmed.startsWith(prefix));
|
|
521
|
+
});
|
|
522
|
+
if (res.status !== 0)
|
|
523
|
+
return { output: outputLines.join("\n"), exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
524
|
+
if (outputLines.some((line) => line.includes("Everything up-to-date"))) {
|
|
525
|
+
return { output: "Everything up-to-date.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
526
|
+
}
|
|
527
|
+
const remoteMessages = outputLines.filter((line) => line.trim().startsWith("remote:"));
|
|
528
|
+
const pushDetail = outputLines.find((line) => line.includes("->"));
|
|
529
|
+
const summary = pushDetail ? `Pushed: ${pushDetail.trim()}` : "Push successful.";
|
|
530
|
+
return { output: [...remoteMessages, summary].join("\n"), exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
531
|
+
}
|
|
532
|
+
async function handlePull(cwd, globalOptions, args, options) {
|
|
533
|
+
const res = await runGitQuery(cwd, globalOptions, ["pull", ...args], options);
|
|
534
|
+
const rawOut = rawText(res, true);
|
|
535
|
+
if (res.status !== 0)
|
|
536
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
537
|
+
if (rawOut.includes("Already up to date."))
|
|
538
|
+
return { output: "Already up to date.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
539
|
+
const lines = rawOut.split("\n");
|
|
540
|
+
const summary = lines.filter((line) => line.includes("Fast-forward") || line.includes("file changed") || line.includes("files changed"));
|
|
541
|
+
return { output: summary.join("\n") || "Pull successful.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
542
|
+
}
|
|
543
|
+
async function handleFetch(cwd, globalOptions, args, options) {
|
|
544
|
+
const res = await runGitQuery(cwd, globalOptions, ["fetch", ...args], options);
|
|
545
|
+
const rawOut = rawText(res, true);
|
|
546
|
+
if (res.status !== 0)
|
|
547
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
548
|
+
const refs = rawOut
|
|
549
|
+
.split("\n")
|
|
550
|
+
.filter((line) => line.includes("[new branch]") || line.includes("[new tag]") || line.includes("->"));
|
|
551
|
+
return {
|
|
552
|
+
output: refs.length
|
|
553
|
+
? `Fetched:\n${refs.map((line) => line.trim()).join("\n")}`
|
|
554
|
+
: "Fetch successful (no new refs).",
|
|
555
|
+
exitCode: 0,
|
|
556
|
+
rawOut,
|
|
557
|
+
rawBytes: res.rawBytes,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
async function handleBranch(cwd, globalOptions, args, options) {
|
|
561
|
+
if (args.includes("--show-current")) {
|
|
562
|
+
const res = await runGitQuery(cwd, globalOptions, ["branch", "--show-current"], options);
|
|
563
|
+
return { output: res.stdout.trim(), exitCode: res.status ?? 0, rawOut: rawText(res), rawBytes: res.rawBytes };
|
|
564
|
+
}
|
|
565
|
+
const isWrite = args.some((arg) => arg === "-d" || arg === "-D" || arg === "-m" || arg === "-M" || (!arg.startsWith("-") && args.length === 1));
|
|
566
|
+
if (isWrite) {
|
|
567
|
+
const res = await runGitQuery(cwd, globalOptions, ["branch", ...args], options);
|
|
568
|
+
const rawOut = rawText(res);
|
|
569
|
+
if (res.status !== 0)
|
|
570
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
571
|
+
return { output: rawOut.trim() || "Branch updated successfully.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
572
|
+
}
|
|
573
|
+
const res = await runGitQuery(cwd, globalOptions, ["branch", "--no-color", ...args], options);
|
|
574
|
+
const rawOut = rawText(res);
|
|
575
|
+
if (res.status !== 0)
|
|
576
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
577
|
+
const lines = res.stdout.split("\n").filter((line) => line.trim().length > 0);
|
|
578
|
+
const remoteBranches = lines.filter((line) => line.includes("remotes/"));
|
|
579
|
+
const localBranches = lines.filter((line) => !line.includes("remotes/"));
|
|
580
|
+
const remoteDisplay = remoteBranches.slice(0, 5);
|
|
581
|
+
const omitted = remoteBranches.length - remoteDisplay.length;
|
|
582
|
+
if (omitted > 0)
|
|
583
|
+
remoteDisplay.push(` remotes/... (${omitted} more remote branches)`);
|
|
584
|
+
return { output: [...localBranches, ...remoteDisplay].join("\n"), exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
585
|
+
}
|
|
586
|
+
async function handleStash(cwd, globalOptions, args, options) {
|
|
587
|
+
const sub = args[0] || "push";
|
|
588
|
+
const res = await runGitQuery(cwd, globalOptions, ["stash", ...args], options);
|
|
589
|
+
const rawOut = rawText(res);
|
|
590
|
+
if (res.status !== 0)
|
|
591
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
592
|
+
if (sub === "list")
|
|
593
|
+
return { output: res.stdout.trim() || "No stashes found.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
594
|
+
if (sub === "show") {
|
|
595
|
+
const { compacted, truncated } = compactDiff(res.stdout);
|
|
596
|
+
return {
|
|
597
|
+
output: `${compacted.trim()}${truncated ? "\n\n[Diff truncated.]" : ""}`,
|
|
598
|
+
exitCode: 0,
|
|
599
|
+
rawOut,
|
|
600
|
+
rawBytes: res.rawBytes,
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
if (res.stdout.includes("No local changes to save"))
|
|
604
|
+
return { output: "No local changes to save.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
605
|
+
const firstLine = res.stdout
|
|
606
|
+
.split("\n")
|
|
607
|
+
.find((line) => line.trim().length > 0)
|
|
608
|
+
?.trim();
|
|
609
|
+
return { output: firstLine || "Stash successful.", exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
610
|
+
}
|
|
611
|
+
async function handleWorktree(cwd, globalOptions, args, options) {
|
|
612
|
+
const sub = args[0] || "list";
|
|
613
|
+
const res = await runGitQuery(cwd, globalOptions, ["worktree", ...(sub === "list" ? ["list"] : args)], options);
|
|
614
|
+
const rawOut = rawText(res, true);
|
|
615
|
+
if (res.status !== 0)
|
|
616
|
+
return { output: rawOut, exitCode: res.status ?? 1, rawOut, rawBytes: res.rawBytes };
|
|
617
|
+
if (sub !== "list")
|
|
618
|
+
return { output: rawOut.trim(), exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
619
|
+
const home = process.env.HOME || "";
|
|
620
|
+
const output = res.stdout
|
|
621
|
+
.split("\n")
|
|
622
|
+
.map((line) => (home && line.startsWith(home) ? `~${line.slice(home.length)}` : line))
|
|
623
|
+
.join("\n")
|
|
624
|
+
.trim();
|
|
625
|
+
return { output, exitCode: 0, rawOut, rawBytes: res.rawBytes };
|
|
626
|
+
}
|
|
627
|
+
export async function executeFilteredGit(cwd, subcommand, globalOptions, subcommandArgs, options) {
|
|
628
|
+
switch (subcommand) {
|
|
629
|
+
case "status":
|
|
630
|
+
return handleStatus(cwd, globalOptions, subcommandArgs, options);
|
|
631
|
+
case "log":
|
|
632
|
+
return handleLog(cwd, globalOptions, subcommandArgs, options);
|
|
633
|
+
case "diff":
|
|
634
|
+
return handleDiff(cwd, globalOptions, subcommandArgs, options);
|
|
635
|
+
case "show":
|
|
636
|
+
return handleShow(cwd, globalOptions, subcommandArgs, options);
|
|
637
|
+
case "add":
|
|
638
|
+
return handleAdd(cwd, globalOptions, subcommandArgs, options);
|
|
639
|
+
case "commit":
|
|
640
|
+
return handleCommit(cwd, globalOptions, subcommandArgs, options);
|
|
641
|
+
case "push":
|
|
642
|
+
return handlePush(cwd, globalOptions, subcommandArgs, options);
|
|
643
|
+
case "pull":
|
|
644
|
+
return handlePull(cwd, globalOptions, subcommandArgs, options);
|
|
645
|
+
case "branch":
|
|
646
|
+
return handleBranch(cwd, globalOptions, subcommandArgs, options);
|
|
647
|
+
case "fetch":
|
|
648
|
+
return handleFetch(cwd, globalOptions, subcommandArgs, options);
|
|
649
|
+
case "stash":
|
|
650
|
+
return handleStash(cwd, globalOptions, subcommandArgs, options);
|
|
651
|
+
case "worktree":
|
|
652
|
+
return handleWorktree(cwd, globalOptions, subcommandArgs, options);
|
|
653
|
+
default:
|
|
654
|
+
return { output: "", exitCode: -100, rawOut: "" };
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
export function makeGitCommandForDisplay(globalOptions, subcommand, args) {
|
|
658
|
+
return gitCommand(globalOptions, [subcommand, ...args]);
|
|
659
|
+
}
|
|
660
|
+
//# sourceMappingURL=git-filter.js.map
|