@lumpcode/core 0.0.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/LICENSE +202 -0
- package/README.md +489 -0
- package/dist/helpers/collectPromptStepsForContext/index.d.ts +2 -0
- package/dist/helpers/collectPromptStepsForContext/index.d.ts.map +1 -0
- package/dist/helpers/collectPromptStepsForContext/main.d.ts +24 -0
- package/dist/helpers/collectPromptStepsForContext/main.d.ts.map +1 -0
- package/dist/helpers/collectStepsForContext/index.d.ts +2 -0
- package/dist/helpers/collectStepsForContext/index.d.ts.map +1 -0
- package/dist/helpers/collectStepsForContext/main.d.ts +24 -0
- package/dist/helpers/collectStepsForContext/main.d.ts.map +1 -0
- package/dist/helpers/execAsync/index.d.ts +2 -0
- package/dist/helpers/execAsync/index.d.ts.map +1 -0
- package/dist/helpers/execAsync/main.d.ts +14 -0
- package/dist/helpers/execAsync/main.d.ts.map +1 -0
- package/dist/helpers/execBinary/index.d.ts +2 -0
- package/dist/helpers/execBinary/index.d.ts.map +1 -0
- package/dist/helpers/execBinary/main.d.ts +15 -0
- package/dist/helpers/execBinary/main.d.ts.map +1 -0
- package/dist/helpers/executePromptsForContextList/index.d.ts +2 -0
- package/dist/helpers/executePromptsForContextList/index.d.ts.map +1 -0
- package/dist/helpers/executePromptsForContextList/main.d.ts +15 -0
- package/dist/helpers/executePromptsForContextList/main.d.ts.map +1 -0
- package/dist/helpers/executePromptsForContextListOld/main.d.ts +1 -0
- package/dist/helpers/executePromptsForContextListOld/main.d.ts.map +1 -0
- package/dist/helpers/executeStepsForContextList/index.d.ts +2 -0
- package/dist/helpers/executeStepsForContextList/index.d.ts.map +1 -0
- package/dist/helpers/executeStepsForContextList/main.d.ts +15 -0
- package/dist/helpers/executeStepsForContextList/main.d.ts.map +1 -0
- package/dist/helpers/getCodeBasePaths/index.d.ts +2 -0
- package/dist/helpers/getCodeBasePaths/index.d.ts.map +1 -0
- package/dist/helpers/getCodeBasePaths/main.d.ts +7 -0
- package/dist/helpers/getCodeBasePaths/main.d.ts.map +1 -0
- package/dist/helpers/getContextStatus/index.d.ts +2 -0
- package/dist/helpers/getContextStatus/index.d.ts.map +1 -0
- package/dist/helpers/getContextStatus/main.d.ts +13 -0
- package/dist/helpers/getContextStatus/main.d.ts.map +1 -0
- package/dist/helpers/getToDoContextList/index.d.ts +2 -0
- package/dist/helpers/getToDoContextList/index.d.ts.map +1 -0
- package/dist/helpers/getToDoContextList/main.d.ts +12 -0
- package/dist/helpers/getToDoContextList/main.d.ts.map +1 -0
- package/dist/helpers/index.d.ts +9 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/isRemoteBranchExistant/index.d.ts +2 -0
- package/dist/helpers/isRemoteBranchExistant/index.d.ts.map +1 -0
- package/dist/helpers/isRemoteBranchExistant/main.d.ts +14 -0
- package/dist/helpers/isRemoteBranchExistant/main.d.ts.map +1 -0
- package/dist/helpers/updateContextStatusRecord/index.d.ts +2 -0
- package/dist/helpers/updateContextStatusRecord/index.d.ts.map +1 -0
- package/dist/helpers/updateContextStatusRecord/main.d.ts +7 -0
- package/dist/helpers/updateContextStatusRecord/main.d.ts.map +1 -0
- package/dist/helpers/validateContextListNames/index.d.ts +2 -0
- package/dist/helpers/validateContextListNames/index.d.ts.map +1 -0
- package/dist/helpers/validateContextListNames/main.d.ts +3 -0
- package/dist/helpers/validateContextListNames/main.d.ts.map +1 -0
- package/dist/helpers/workspaceExecCwd/index.d.ts +2 -0
- package/dist/helpers/workspaceExecCwd/index.d.ts.map +1 -0
- package/dist/helpers/workspaceExecCwd/main.d.ts +5 -0
- package/dist/helpers/workspaceExecCwd/main.d.ts.map +1 -0
- package/dist/index.cjs +769 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +723 -0
- package/dist/index.js.map +1 -0
- package/dist/types/ArrayPaths.d.ts +10 -0
- package/dist/types/ArrayPaths.d.ts.map +1 -0
- package/dist/types/AsyncFnSuccess.d.ts +3 -0
- package/dist/types/AsyncFnSuccess.d.ts.map +1 -0
- package/dist/types/BranchFn.d.ts +10 -0
- package/dist/types/BranchFn.d.ts.map +1 -0
- package/dist/types/CodeBasePath.d.ts +5 -0
- package/dist/types/CodeBasePath.d.ts.map +1 -0
- package/dist/types/CommandFn.d.ts +22 -0
- package/dist/types/CommandFn.d.ts.map +1 -0
- package/dist/types/CommandResultInfos.d.ts +5 -0
- package/dist/types/CommandResultInfos.d.ts.map +1 -0
- package/dist/types/Context.d.ts +9 -0
- package/dist/types/Context.d.ts.map +1 -0
- package/dist/types/ContextList.d.ts +3 -0
- package/dist/types/ContextList.d.ts.map +1 -0
- package/dist/types/ContextRunState.d.ts +2 -0
- package/dist/types/ContextRunState.d.ts.map +1 -0
- package/dist/types/ContextStatus.d.ts +9 -0
- package/dist/types/ContextStatus.d.ts.map +1 -0
- package/dist/types/ExtractSuccess.d.ts +3 -0
- package/dist/types/ExtractSuccess.d.ts.map +1 -0
- package/dist/types/Failure.d.ts +5 -0
- package/dist/types/Failure.d.ts.map +1 -0
- package/dist/types/GetContextListFn.d.ts +11 -0
- package/dist/types/GetContextListFn.d.ts.map +1 -0
- package/dist/types/GitAddCommandFn.d.ts +6 -0
- package/dist/types/GitAddCommandFn.d.ts.map +1 -0
- package/dist/types/GitAndWorkspaceFnsInput.d.ts +8 -0
- package/dist/types/GitAndWorkspaceFnsInput.d.ts.map +1 -0
- package/dist/types/GitCommitCommandFn.d.ts +7 -0
- package/dist/types/GitCommitCommandFn.d.ts.map +1 -0
- package/dist/types/GitCommitMessageFn.d.ts +9 -0
- package/dist/types/GitCommitMessageFn.d.ts.map +1 -0
- package/dist/types/GitContextTagNameFn.d.ts +2 -0
- package/dist/types/GitContextTagNameFn.d.ts.map +1 -0
- package/dist/types/GitPushCommandFn.d.ts +3 -0
- package/dist/types/GitPushCommandFn.d.ts.map +1 -0
- package/dist/types/LumpConfig.d.ts +25 -0
- package/dist/types/LumpConfig.d.ts.map +1 -0
- package/dist/types/LumpConfigPromptItem.d.ts +8 -0
- package/dist/types/LumpConfigPromptItem.d.ts.map +1 -0
- package/dist/types/LumpConfigVariables.d.ts +2 -0
- package/dist/types/LumpConfigVariables.d.ts.map +1 -0
- package/dist/types/LumpContextStatusRecord.d.ts +2 -0
- package/dist/types/LumpContextStatusRecord.d.ts.map +1 -0
- package/dist/types/LumpVariables.d.ts +2 -0
- package/dist/types/LumpVariables.d.ts.map +1 -0
- package/dist/types/Maybe.d.ts +2 -0
- package/dist/types/Maybe.d.ts.map +1 -0
- package/dist/types/MaybePromise.d.ts +2 -0
- package/dist/types/MaybePromise.d.ts.map +1 -0
- package/dist/types/PostCommandExecFn.d.ts +16 -0
- package/dist/types/PostCommandExecFn.d.ts.map +1 -0
- package/dist/types/PromptFn.d.ts +15 -0
- package/dist/types/PromptFn.d.ts.map +1 -0
- package/dist/types/PromptItem.d.ts +12 -0
- package/dist/types/PromptItem.d.ts.map +1 -0
- package/dist/types/PromptItemVariables.d.ts +2 -0
- package/dist/types/PromptItemVariables.d.ts.map +1 -0
- package/dist/types/PromptItems.d.ts +5 -0
- package/dist/types/PromptItems.d.ts.map +1 -0
- package/dist/types/SetupFn.d.ts +13 -0
- package/dist/types/SetupFn.d.ts.map +1 -0
- package/dist/types/SetupWorkspaceCommand.d.ts +6 -0
- package/dist/types/SetupWorkspaceCommand.d.ts.map +1 -0
- package/dist/types/SetupWorkspaceFn.d.ts +6 -0
- package/dist/types/SetupWorkspaceFn.d.ts.map +1 -0
- package/dist/types/Step.d.ts +12 -0
- package/dist/types/Step.d.ts.map +1 -0
- package/dist/types/StepVariables.d.ts +2 -0
- package/dist/types/StepVariables.d.ts.map +1 -0
- package/dist/types/Steps.d.ts +5 -0
- package/dist/types/Steps.d.ts.map +1 -0
- package/dist/types/Success.d.ts +5 -0
- package/dist/types/Success.d.ts.map +1 -0
- package/dist/types/TeardownFn.d.ts +11 -0
- package/dist/types/TeardownFn.d.ts.map +1 -0
- package/dist/types/TeardownWorkspaceCommand.d.ts +3 -0
- package/dist/types/TeardownWorkspaceCommand.d.ts.map +1 -0
- package/dist/types/TeardownWorkspaceFn.d.ts +3 -0
- package/dist/types/TeardownWorkspaceFn.d.ts.map +1 -0
- package/dist/types/index.d.ts +30 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/usages/executePromptsForContextList/index.d.ts +2 -0
- package/dist/usages/executePromptsForContextList/index.d.ts.map +1 -0
- package/dist/usages/executePromptsForContextList/main.d.ts +45 -0
- package/dist/usages/executePromptsForContextList/main.d.ts.map +1 -0
- package/dist/usages/getToDoContextList/index.d.ts +2 -0
- package/dist/usages/getToDoContextList/index.d.ts.map +1 -0
- package/dist/usages/getToDoContextList/main.d.ts +10 -0
- package/dist/usages/getToDoContextList/main.d.ts.map +1 -0
- package/dist/usages/index.d.ts +2 -0
- package/dist/usages/index.d.ts.map +1 -0
- package/dist/usages/refreshContextStatusRecord/index.d.ts +1 -0
- package/dist/usages/refreshContextStatusRecord/index.d.ts.map +1 -0
- package/dist/usages/refreshContextStatusRecord/main.d.ts +1 -0
- package/dist/usages/refreshContextStatusRecord/main.d.ts.map +1 -0
- package/dist/usages/runLump/defaultInjectedFns.d.ts +10 -0
- package/dist/usages/runLump/defaultInjectedFns.d.ts.map +1 -0
- package/dist/usages/runLump/index.d.ts +3 -0
- package/dist/usages/runLump/index.d.ts.map +1 -0
- package/dist/usages/runLump/main.d.ts +28 -0
- package/dist/usages/runLump/main.d.ts.map +1 -0
- package/dist/usages/updateContextStatusRecord/index.d.ts +2 -0
- package/dist/usages/updateContextStatusRecord/index.d.ts.map +1 -0
- package/dist/usages/updateContextStatusRecord/main.d.ts +7 -0
- package/dist/usages/updateContextStatusRecord/main.d.ts.map +1 -0
- package/dist/utils/decision/index.d.ts +2 -0
- package/dist/utils/decision/index.d.ts.map +1 -0
- package/dist/utils/decision/main.d.ts +2 -0
- package/dist/utils/decision/main.d.ts.map +1 -0
- package/dist/utils/failure/index.d.ts +2 -0
- package/dist/utils/failure/index.d.ts.map +1 -0
- package/dist/utils/failure/main.d.ts +3 -0
- package/dist/utils/failure/main.d.ts.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/set/index.d.ts +2 -0
- package/dist/utils/set/index.d.ts.map +1 -0
- package/dist/utils/set/main.d.ts +4 -0
- package/dist/utils/set/main.d.ts.map +1 -0
- package/dist/utils/shellBestEffort/index.d.ts +2 -0
- package/dist/utils/shellBestEffort/index.d.ts.map +1 -0
- package/dist/utils/shellBestEffort/main.d.ts +7 -0
- package/dist/utils/shellBestEffort/main.d.ts.map +1 -0
- package/dist/utils/shellSingleQuote/index.d.ts +2 -0
- package/dist/utils/shellSingleQuote/index.d.ts.map +1 -0
- package/dist/utils/shellSingleQuote/main.d.ts +9 -0
- package/dist/utils/shellSingleQuote/main.d.ts.map +1 -0
- package/dist/utils/success/index.d.ts +2 -0
- package/dist/utils/success/index.d.ts.map +1 -0
- package/dist/utils/success/main.d.ts +3 -0
- package/dist/utils/success/main.d.ts.map +1 -0
- package/package.json +48 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
import { exec, spawn } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import fs$1 from 'fs/promises';
|
|
4
|
+
import { dirname } from 'path';
|
|
5
|
+
import * as fs from 'node:fs/promises';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import ignore from 'ignore';
|
|
8
|
+
import z from 'zod';
|
|
9
|
+
|
|
10
|
+
function set(object, path, value) {
|
|
11
|
+
const keys = Array.isArray(path) ? path : [path];
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
let current = object;
|
|
14
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
15
|
+
const key = keys[i];
|
|
16
|
+
if (!(key in current)) {
|
|
17
|
+
current[key] = typeof keys[i + 1] === "number" ? [] : {};
|
|
18
|
+
}
|
|
19
|
+
current = current[key];
|
|
20
|
+
}
|
|
21
|
+
const lastKey = keys[keys.length - 1];
|
|
22
|
+
current[lastKey] = value;
|
|
23
|
+
return object;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function success(data) {
|
|
27
|
+
return {
|
|
28
|
+
success: true,
|
|
29
|
+
data,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function failure(data) {
|
|
34
|
+
return {
|
|
35
|
+
success: false,
|
|
36
|
+
data,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function decision(possibilities, defaultValue) {
|
|
41
|
+
for (const [condition, result] of possibilities) {
|
|
42
|
+
if (condition()) {
|
|
43
|
+
return result();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (defaultValue) {
|
|
47
|
+
return defaultValue;
|
|
48
|
+
}
|
|
49
|
+
throw new Error('No value found in decision');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Wrap an arbitrary string in quotes so it can be safely embedded in
|
|
54
|
+
* a shell command (e.g. the command string passed to `execAsync`).
|
|
55
|
+
*
|
|
56
|
+
* On Unix uses single quotes (no expansion). On Windows uses cmd.exe
|
|
57
|
+
* double-quote rules (`""` for a literal `"`).
|
|
58
|
+
*/
|
|
59
|
+
function shellSingleQuote(value) {
|
|
60
|
+
if (process.platform === 'win32') {
|
|
61
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
62
|
+
}
|
|
63
|
+
return `'${value.split("'").join(`'\\''`)}'`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Wrap a shell fragment so failure does not break a surrounding `&&` chain.
|
|
68
|
+
*
|
|
69
|
+
* Unix: `cmd || true`. Windows cmd.exe: `(cmd || cd .)`.
|
|
70
|
+
*/
|
|
71
|
+
function shellBestEffort(command) {
|
|
72
|
+
if (process.platform === 'win32') {
|
|
73
|
+
return `(${command} || cd .)`;
|
|
74
|
+
}
|
|
75
|
+
return `${command} || true`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const execAsyncBase = promisify(exec);
|
|
79
|
+
async function execAsync(command, options) {
|
|
80
|
+
const { stdout, stderr, hasErrored } = await execAsyncBase(command, { cwd: options?.cwd })
|
|
81
|
+
.then(result => ({
|
|
82
|
+
stdout: result.stdout,
|
|
83
|
+
stderr: result.stderr,
|
|
84
|
+
hasErrored: false,
|
|
85
|
+
}))
|
|
86
|
+
.catch(e => ({
|
|
87
|
+
stderr: e,
|
|
88
|
+
stdout: e,
|
|
89
|
+
hasErrored: true,
|
|
90
|
+
}));
|
|
91
|
+
if (hasErrored) {
|
|
92
|
+
return failure({
|
|
93
|
+
message: `Command ${command} failed with error: ${stderr}`,
|
|
94
|
+
info: {
|
|
95
|
+
command,
|
|
96
|
+
stdout,
|
|
97
|
+
stderr,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return success({
|
|
102
|
+
stdout,
|
|
103
|
+
stderr,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function execBinary(binaryPath, args, timeoutMillis = 1000 * 60 * 10, options) {
|
|
108
|
+
return new Promise((resolve) => {
|
|
109
|
+
let settled = false;
|
|
110
|
+
const finish = (result) => {
|
|
111
|
+
if (settled)
|
|
112
|
+
return;
|
|
113
|
+
settled = true;
|
|
114
|
+
clearTimeout(timeout);
|
|
115
|
+
resolve(result);
|
|
116
|
+
};
|
|
117
|
+
const timeout = setTimeout(() => {
|
|
118
|
+
finish(failure({
|
|
119
|
+
message: `Process timed out after ${timeoutMillis} milliseconds`,
|
|
120
|
+
binaryPath,
|
|
121
|
+
args,
|
|
122
|
+
}));
|
|
123
|
+
}, timeoutMillis);
|
|
124
|
+
const child = spawn(binaryPath, args, options || {});
|
|
125
|
+
let stdout = '', stderr = '';
|
|
126
|
+
child.stdout?.on('data', (data) => { stdout += data; });
|
|
127
|
+
child.stderr?.on('data', (data) => { stderr += data; });
|
|
128
|
+
child.on('error', (err) => {
|
|
129
|
+
finish(failure({
|
|
130
|
+
message: err.message,
|
|
131
|
+
binaryPath,
|
|
132
|
+
args,
|
|
133
|
+
stdout,
|
|
134
|
+
stderr,
|
|
135
|
+
}));
|
|
136
|
+
});
|
|
137
|
+
child.on('close', (code) => {
|
|
138
|
+
if (code === 0) {
|
|
139
|
+
finish(success({ stdout, stderr }));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
finish(failure({
|
|
143
|
+
message: `Process exited with code ${code}: ${stderr}`,
|
|
144
|
+
binaryPath,
|
|
145
|
+
args,
|
|
146
|
+
code: code ?? undefined,
|
|
147
|
+
stdout,
|
|
148
|
+
stderr,
|
|
149
|
+
}));
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function collectStepsForContext(params) {
|
|
155
|
+
const { context, contextList, currentContextIndex, lumpVariables, steps: stepsToCollect, setupFn, projectRoot, workspacePath, } = params;
|
|
156
|
+
const setupResult = await setupFn({
|
|
157
|
+
contextList,
|
|
158
|
+
lumpVariables,
|
|
159
|
+
currentContextIndex,
|
|
160
|
+
});
|
|
161
|
+
const contextRunState = setupResult?.contextRunState ?? {};
|
|
162
|
+
const collectedSteps = [];
|
|
163
|
+
async function walk(stepsToExec, currStepIndex) {
|
|
164
|
+
for (let stepIndex = 0; stepIndex < stepsToExec.length; stepIndex++) {
|
|
165
|
+
const step = stepsToExec[stepIndex];
|
|
166
|
+
const nextCallHeadIndex = [...currStepIndex, stepIndex];
|
|
167
|
+
const compositeStepIndex = nextCallHeadIndex.length === 1 ? nextCallHeadIndex[0] : nextCallHeadIndex;
|
|
168
|
+
if (typeof step === 'function' || Array.isArray(step)) {
|
|
169
|
+
let subSteps = [];
|
|
170
|
+
if (typeof step === 'function') {
|
|
171
|
+
subSteps = await step({
|
|
172
|
+
context,
|
|
173
|
+
stepIndex: compositeStepIndex,
|
|
174
|
+
contextRunState,
|
|
175
|
+
lumpVariables,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
subSteps = step;
|
|
180
|
+
}
|
|
181
|
+
await walk(subSteps, nextCallHeadIndex);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const { commandFn, stepVariables, promptFn, postCommandExecFn, timeoutMillis, } = step;
|
|
185
|
+
const prompt = promptFn
|
|
186
|
+
? await promptFn({
|
|
187
|
+
context,
|
|
188
|
+
stepIndex: compositeStepIndex,
|
|
189
|
+
contextRunState,
|
|
190
|
+
lumpVariables,
|
|
191
|
+
stepVariables,
|
|
192
|
+
})
|
|
193
|
+
: '';
|
|
194
|
+
const command = await commandFn({
|
|
195
|
+
context,
|
|
196
|
+
prompt,
|
|
197
|
+
stepIndex: compositeStepIndex,
|
|
198
|
+
contextRunState,
|
|
199
|
+
lumpVariables,
|
|
200
|
+
stepVariables,
|
|
201
|
+
projectRoot,
|
|
202
|
+
workspacePath,
|
|
203
|
+
});
|
|
204
|
+
collectedSteps.push({
|
|
205
|
+
stepIndex: compositeStepIndex,
|
|
206
|
+
...(prompt.length > 0 && { prompt }),
|
|
207
|
+
command: command != null
|
|
208
|
+
? { executable: command.executable, args: command.args }
|
|
209
|
+
: null,
|
|
210
|
+
postCommandExecFn,
|
|
211
|
+
stepVariables,
|
|
212
|
+
timeoutMillis,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
await walk(stepsToCollect, []);
|
|
217
|
+
return collectedSteps;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables, contextList, gitAddCommandFn, gitCommitCommandFn, gitPushCommandFn, gitCommitMessageFn, projectRoot, steps, setupFn, setupWorkspaceFn, teardownFn, teardownWorkspaceFn, getKeepHistoryFilePathFn, verbose, }) {
|
|
221
|
+
const contextNames = contextList.map(context => context.name);
|
|
222
|
+
log('contextNames', contextNames);
|
|
223
|
+
const contextRunStateList = [];
|
|
224
|
+
const branchName = await branchFn({
|
|
225
|
+
contextList,
|
|
226
|
+
contextRunStateList,
|
|
227
|
+
lumpVariables,
|
|
228
|
+
});
|
|
229
|
+
log('branchName', branchName);
|
|
230
|
+
const injectedGitAndWorkspaceFnsInput = {
|
|
231
|
+
baseBranch,
|
|
232
|
+
branchName,
|
|
233
|
+
contextList,
|
|
234
|
+
workspacePath: '.',
|
|
235
|
+
};
|
|
236
|
+
const { command: setupWorkspaceCommand, workspacePath } = await setupWorkspaceFn(injectedGitAndWorkspaceFnsInput);
|
|
237
|
+
log('setupWorkspaceCommand', setupWorkspaceCommand);
|
|
238
|
+
log('workspacePath', workspacePath);
|
|
239
|
+
if (setupWorkspaceCommand) {
|
|
240
|
+
const setupWorkspaceCommandExec = await execAsync(setupWorkspaceCommand, {
|
|
241
|
+
cwd: projectRoot,
|
|
242
|
+
});
|
|
243
|
+
log('setupWorkspaceCommandExec', setupWorkspaceCommandExec);
|
|
244
|
+
if (!setupWorkspaceCommandExec.success) {
|
|
245
|
+
return set(setupWorkspaceCommandExec, ['data', 'message'], `Failed to setup the workspace: ${setupWorkspaceCommandExec.data.message}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const gitStatusCommand = await execAsync(`git status`, { cwd: workspacePath });
|
|
249
|
+
log('gitStatusCommand', gitStatusCommand.data);
|
|
250
|
+
injectedGitAndWorkspaceFnsInput.workspacePath = workspacePath;
|
|
251
|
+
for (let i = 0; i < contextList.length; i++) {
|
|
252
|
+
const context = contextList[i];
|
|
253
|
+
const setupResult = await setupFn({
|
|
254
|
+
contextList,
|
|
255
|
+
lumpVariables,
|
|
256
|
+
currentContextIndex: i,
|
|
257
|
+
});
|
|
258
|
+
const contextRunState = setupResult?.contextRunState || {};
|
|
259
|
+
let stepWalkFailure;
|
|
260
|
+
async function walkAndExecuteSteps(stepsToExec, currStepIndex) {
|
|
261
|
+
for (let stepIndex = 0; stepIndex < stepsToExec.length; stepIndex++) {
|
|
262
|
+
if (stepWalkFailure) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const step = stepsToExec[stepIndex];
|
|
266
|
+
const nextCallHeadIndex = [...currStepIndex, stepIndex];
|
|
267
|
+
const compositeStepIndex = nextCallHeadIndex.length === 1 ? nextCallHeadIndex[0] : nextCallHeadIndex;
|
|
268
|
+
if (typeof step === 'function' || Array.isArray(step)) {
|
|
269
|
+
let subSteps = [];
|
|
270
|
+
if (typeof step === 'function') {
|
|
271
|
+
subSteps = await step({
|
|
272
|
+
context,
|
|
273
|
+
stepIndex: compositeStepIndex,
|
|
274
|
+
contextRunState,
|
|
275
|
+
lumpVariables,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
subSteps = step;
|
|
280
|
+
}
|
|
281
|
+
await walkAndExecuteSteps(subSteps, nextCallHeadIndex);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
log('step', step);
|
|
285
|
+
const { commandFn, stepVariables, promptFn, postCommandExecFn, timeoutMillis = 1000 * 60 * 30, } = step;
|
|
286
|
+
const prompt = promptFn
|
|
287
|
+
? await promptFn({
|
|
288
|
+
context,
|
|
289
|
+
stepIndex: compositeStepIndex,
|
|
290
|
+
contextRunState,
|
|
291
|
+
lumpVariables,
|
|
292
|
+
stepVariables,
|
|
293
|
+
})
|
|
294
|
+
: '';
|
|
295
|
+
const command = await commandFn({
|
|
296
|
+
context,
|
|
297
|
+
prompt,
|
|
298
|
+
stepIndex: compositeStepIndex,
|
|
299
|
+
contextRunState,
|
|
300
|
+
lumpVariables,
|
|
301
|
+
stepVariables,
|
|
302
|
+
projectRoot,
|
|
303
|
+
workspacePath,
|
|
304
|
+
});
|
|
305
|
+
let commandResult = '';
|
|
306
|
+
if (command != null) {
|
|
307
|
+
const { executable, args } = command;
|
|
308
|
+
log('command for prompt', executable, args);
|
|
309
|
+
log('workspacePath', workspacePath);
|
|
310
|
+
const commandExec = await execBinary(executable, args, timeoutMillis, {
|
|
311
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
312
|
+
cwd: workspacePath,
|
|
313
|
+
});
|
|
314
|
+
log('commandExec', commandExec);
|
|
315
|
+
if (!commandExec.success) {
|
|
316
|
+
stepWalkFailure = set(commandExec, ['data', 'message'], `Failed to run the command: ${commandExec.data.message}. Command: ${executable} ${args.join(' ')}`);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
commandResult = (commandExec.data.stdout || commandExec.data.stderr || '').toString();
|
|
320
|
+
log('commandResult', commandResult);
|
|
321
|
+
const gitStatusCommand = await execAsync(`git status`, { cwd: workspacePath });
|
|
322
|
+
log('gitStatusCommand', gitStatusCommand.data);
|
|
323
|
+
}
|
|
324
|
+
const postCommandExecFnInput = {
|
|
325
|
+
commandResult,
|
|
326
|
+
context,
|
|
327
|
+
prompt,
|
|
328
|
+
stepIndex: compositeStepIndex,
|
|
329
|
+
contextRunState,
|
|
330
|
+
lumpVariables,
|
|
331
|
+
stepVariables,
|
|
332
|
+
projectRoot,
|
|
333
|
+
};
|
|
334
|
+
log('context is', context);
|
|
335
|
+
const keepHistoryFilePath = getKeepHistoryFilePathFn(context) || '';
|
|
336
|
+
log('keepHistoryFilePath', keepHistoryFilePath);
|
|
337
|
+
if (!!command && keepHistoryFilePath.length > 0) {
|
|
338
|
+
const makeHistoryFileIfNotExists = async () => {
|
|
339
|
+
if (await fs$1.stat(keepHistoryFilePath).then(() => true).catch(() => false))
|
|
340
|
+
return;
|
|
341
|
+
await fs$1.mkdir(dirname(keepHistoryFilePath), { recursive: true });
|
|
342
|
+
await fs$1.writeFile(keepHistoryFilePath, "[]", 'utf-8');
|
|
343
|
+
};
|
|
344
|
+
await makeHistoryFileIfNotExists();
|
|
345
|
+
const historyFileContent = await fs$1.readFile(keepHistoryFilePath, 'utf-8');
|
|
346
|
+
log('historyFileContent', historyFileContent);
|
|
347
|
+
const history = JSON.parse(historyFileContent);
|
|
348
|
+
log('history', history);
|
|
349
|
+
history.push({
|
|
350
|
+
...postCommandExecFnInput,
|
|
351
|
+
});
|
|
352
|
+
log('history after push', history);
|
|
353
|
+
await fs$1.writeFile(keepHistoryFilePath, JSON.stringify(history, null, 2), 'utf-8');
|
|
354
|
+
}
|
|
355
|
+
if (postCommandExecFn) {
|
|
356
|
+
await postCommandExecFn(postCommandExecFnInput);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
await walkAndExecuteSteps(steps, []);
|
|
361
|
+
if (stepWalkFailure) {
|
|
362
|
+
return stepWalkFailure;
|
|
363
|
+
}
|
|
364
|
+
await teardownFn({
|
|
365
|
+
lumpVariables,
|
|
366
|
+
contextList,
|
|
367
|
+
currentContextIndex: i,
|
|
368
|
+
contextRunState,
|
|
369
|
+
});
|
|
370
|
+
const perContextInput = {
|
|
371
|
+
...injectedGitAndWorkspaceFnsInput,
|
|
372
|
+
context,
|
|
373
|
+
};
|
|
374
|
+
const gitAddCommand = await execAsync(gitAddCommandFn(perContextInput), { cwd: workspacePath });
|
|
375
|
+
log('gitAddCommand', gitAddCommand);
|
|
376
|
+
if (!gitAddCommand.success) {
|
|
377
|
+
return set(gitAddCommand, ['data', 'message'], `Failed to add the changes for context ${context.name}: ${gitAddCommand.data.message}`);
|
|
378
|
+
}
|
|
379
|
+
const commitMessage = gitCommitMessageFn({ context, lumpVariables, baseBranch });
|
|
380
|
+
const commitCommand = await execAsync(gitCommitCommandFn({
|
|
381
|
+
...perContextInput,
|
|
382
|
+
commitMessage,
|
|
383
|
+
}), { cwd: workspacePath });
|
|
384
|
+
log('commitCommand', commitCommand);
|
|
385
|
+
if (!commitCommand.success) {
|
|
386
|
+
log(`Failed to commit the changes for context ${context.name}:`, commitCommand.data);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
const pushCommand = await execAsync(gitPushCommandFn(injectedGitAndWorkspaceFnsInput), { cwd: workspacePath });
|
|
390
|
+
log('pushCommand', pushCommand);
|
|
391
|
+
if (!pushCommand.success) {
|
|
392
|
+
log(`Failed to push the changes on branch ${branchName}: ${pushCommand.data.message}`);
|
|
393
|
+
}
|
|
394
|
+
const teardownWorkspaceCommand = await teardownWorkspaceFn(injectedGitAndWorkspaceFnsInput);
|
|
395
|
+
console.log('teardownWorkspaceCommand', teardownWorkspaceCommand);
|
|
396
|
+
if (teardownWorkspaceCommand) {
|
|
397
|
+
const teardownWorkspaceCommandExec = await execAsync(teardownWorkspaceCommand, { cwd: workspacePath });
|
|
398
|
+
console.log('teardownWorkspaceCommandExec', teardownWorkspaceCommandExec);
|
|
399
|
+
if (!teardownWorkspaceCommandExec.success) {
|
|
400
|
+
return set(teardownWorkspaceCommandExec, ['data', 'message'], `Failed to teardown the workspace: ${teardownWorkspaceCommandExec.data.message}`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return success({
|
|
404
|
+
branchName,
|
|
405
|
+
contextNames,
|
|
406
|
+
contextRunStateList,
|
|
407
|
+
});
|
|
408
|
+
function log(...params) {
|
|
409
|
+
if (verbose) {
|
|
410
|
+
console.log(...params);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async function getCodeBasePaths({ cwd, }) {
|
|
416
|
+
const allPaths = [];
|
|
417
|
+
const gitignoresMap = await getGitignoresMap({ startDir: cwd, stopAtDir: cwd });
|
|
418
|
+
try {
|
|
419
|
+
await scanDirectory({
|
|
420
|
+
dirPath: cwd,
|
|
421
|
+
allPaths,
|
|
422
|
+
gitignoresMap,
|
|
423
|
+
projectRoot: cwd,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
return failure({
|
|
428
|
+
message: `Failed to scan directory: ${error}`,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
return success(allPaths);
|
|
432
|
+
}
|
|
433
|
+
async function getGitignoresMap({ startDir, stopAtDir }) {
|
|
434
|
+
const gitignores = new Map();
|
|
435
|
+
let currentDir = startDir;
|
|
436
|
+
const stopAtDirParent = path.dirname(stopAtDir);
|
|
437
|
+
while (currentDir !== stopAtDirParent) {
|
|
438
|
+
const gitignorePath = path.join(currentDir, '.gitignore');
|
|
439
|
+
const hasGitignore = await fs.access(gitignorePath).then(() => true).catch(() => false);
|
|
440
|
+
if (hasGitignore) {
|
|
441
|
+
const gitignoreContent = await fs.readFile(gitignorePath, 'utf-8');
|
|
442
|
+
gitignores.set(currentDir, ignore().add(gitignoreContent));
|
|
443
|
+
}
|
|
444
|
+
currentDir = path.dirname(currentDir);
|
|
445
|
+
}
|
|
446
|
+
return gitignores;
|
|
447
|
+
}
|
|
448
|
+
async function scanDirectory({ dirPath, allPaths, gitignoresMap, projectRoot }) {
|
|
449
|
+
try {
|
|
450
|
+
const items = await fs.readdir(dirPath);
|
|
451
|
+
for (const item of items) {
|
|
452
|
+
const itemPath = path.join(dirPath, item);
|
|
453
|
+
try {
|
|
454
|
+
const stat = await fs.stat(itemPath);
|
|
455
|
+
let shouldIgnore = false;
|
|
456
|
+
for (const [gitignoreDir, gitignoreInstance] of gitignoresMap) {
|
|
457
|
+
const relativePathFromGitignore = path.relative(gitignoreDir, itemPath);
|
|
458
|
+
const isIgnored = gitignoreInstance.ignores(relativePathFromGitignore);
|
|
459
|
+
if (isIgnored) {
|
|
460
|
+
shouldIgnore = true;
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
if (shouldIgnore) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
allPaths.push({
|
|
468
|
+
path: path.relative(projectRoot, itemPath),
|
|
469
|
+
isDir: stat.isDirectory(),
|
|
470
|
+
});
|
|
471
|
+
if (stat.isDirectory()) {
|
|
472
|
+
await scanDirectory({
|
|
473
|
+
dirPath: itemPath,
|
|
474
|
+
allPaths,
|
|
475
|
+
gitignoresMap,
|
|
476
|
+
projectRoot,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
catch (error) {
|
|
481
|
+
console.warn(`Cannot access ${itemPath}: ${error}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
throw new Error(`Cannot read directory ${dirPath}: ${error}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async function getContextStatus(params) {
|
|
491
|
+
const { contextName, gitCommitMessageFn, projectRoot, baseBranch, lumpVariables = {}, contextVariables = {}, remoteName = "origin", verbose = false, } = params;
|
|
492
|
+
const commitMessage = gitCommitMessageFn({
|
|
493
|
+
context: { name: contextName, variables: contextVariables },
|
|
494
|
+
lumpVariables,
|
|
495
|
+
baseBranch,
|
|
496
|
+
});
|
|
497
|
+
const fetchAll = await execAsync(`git fetch --all --prune`, { cwd: projectRoot });
|
|
498
|
+
if (!fetchAll.success)
|
|
499
|
+
return 'toDo';
|
|
500
|
+
const logResult = await execAsync(`git log --remotes=${remoteName} -F --grep=${shellSingleQuote(commitMessage)} --format=${shellSingleQuote('%H %s')}`, { cwd: projectRoot });
|
|
501
|
+
if (!logResult.success)
|
|
502
|
+
return 'toDo';
|
|
503
|
+
const matchingHashes = logResult.data.stdout
|
|
504
|
+
.split('\n')
|
|
505
|
+
.map((line) => line.trim())
|
|
506
|
+
.filter(Boolean)
|
|
507
|
+
.map((line) => {
|
|
508
|
+
const sp = line.indexOf(' ');
|
|
509
|
+
return {
|
|
510
|
+
hash: sp === -1 ? line : line.slice(0, sp),
|
|
511
|
+
subject: sp === -1 ? '' : line.slice(sp + 1),
|
|
512
|
+
};
|
|
513
|
+
})
|
|
514
|
+
.filter((c) => c.subject === commitMessage)
|
|
515
|
+
.map((c) => c.hash);
|
|
516
|
+
if (verbose) {
|
|
517
|
+
console.log('remoteName', remoteName);
|
|
518
|
+
console.log('baseBranch', baseBranch);
|
|
519
|
+
console.log('commitMessage', commitMessage);
|
|
520
|
+
console.log('matchingHashes', matchingHashes);
|
|
521
|
+
}
|
|
522
|
+
if (matchingHashes.length === 0)
|
|
523
|
+
return 'toDo';
|
|
524
|
+
const baseRef = `${remoteName}/${baseBranch}`;
|
|
525
|
+
for (const hash of matchingHashes) {
|
|
526
|
+
const isAncestor = await execAsync(`git merge-base --is-ancestor ${hash} ${baseRef}`, { cwd: projectRoot });
|
|
527
|
+
if (isAncestor.success)
|
|
528
|
+
return 'finished';
|
|
529
|
+
}
|
|
530
|
+
for (const hash of matchingHashes) {
|
|
531
|
+
const branches = await execAsync(`git branch -r --contains ${hash} --format=${shellSingleQuote('%(refname:short)')}`, { cwd: projectRoot });
|
|
532
|
+
if (!branches.success)
|
|
533
|
+
continue;
|
|
534
|
+
const branchList = branches.data.stdout
|
|
535
|
+
.trim()
|
|
536
|
+
.split('\n')
|
|
537
|
+
.map((b) => b.trim())
|
|
538
|
+
.filter((b) => b && b !== remoteName && b !== baseRef);
|
|
539
|
+
if (branchList.length > 0)
|
|
540
|
+
return 'branchPushed';
|
|
541
|
+
}
|
|
542
|
+
return 'toDo';
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const VALID_CONTEXT_NAME = /^[a-zA-Z0-9_-]+$/;
|
|
546
|
+
function validateContextListNames(contextList) {
|
|
547
|
+
const invalidNames = contextList
|
|
548
|
+
.filter((context) => !VALID_CONTEXT_NAME.test(context.name))
|
|
549
|
+
.map((context) => context.name);
|
|
550
|
+
if (invalidNames.length > 0) {
|
|
551
|
+
return `Invalid context name(s): ${invalidNames.join(', ')}. Context names must contain only letters, digits, underscores (_), and hyphens (-).`;
|
|
552
|
+
}
|
|
553
|
+
const seen = new Set();
|
|
554
|
+
const duplicateNames = [];
|
|
555
|
+
for (const context of contextList) {
|
|
556
|
+
if (seen.has(context.name)) {
|
|
557
|
+
if (!duplicateNames.includes(context.name)) {
|
|
558
|
+
duplicateNames.push(context.name);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
seen.add(context.name);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
if (duplicateNames.length > 0) {
|
|
566
|
+
return `Duplicate context name(s): ${duplicateNames.join(', ')}. Context names must be unique.`;
|
|
567
|
+
}
|
|
568
|
+
return undefined;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
async function getToDoContextList(params) {
|
|
572
|
+
const { getContextListFn, lumpVariables, gitCommitMessageFn, projectRoot, baseBranch } = params;
|
|
573
|
+
const codeBasePathsResult = await getCodeBasePaths({ cwd: projectRoot });
|
|
574
|
+
if (!codeBasePathsResult.success) {
|
|
575
|
+
return failure({
|
|
576
|
+
message: 'Failed to get code base paths',
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
const codeBasePaths = codeBasePathsResult.data;
|
|
580
|
+
const contextList = await getContextListFn({ codeBasePaths, lumpVariables });
|
|
581
|
+
const contextListValidationError = validateContextListNames(contextList);
|
|
582
|
+
if (contextListValidationError) {
|
|
583
|
+
return failure({
|
|
584
|
+
message: contextListValidationError,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
const allCtxNames = contextList.flatMap(context => [context.name, ...(context.options?.dependsOnContexts ?? [])]);
|
|
588
|
+
const allCtxNamesSet = new Set(allCtxNames);
|
|
589
|
+
const allCtxNamesList = Array.from(allCtxNamesSet);
|
|
590
|
+
const contextStatusList = await Promise.all(allCtxNamesList.map((contextName) => {
|
|
591
|
+
return getContextStatus({
|
|
592
|
+
contextName: contextName,
|
|
593
|
+
contextVariables: {}, // TODO: Remove contextVariables from getContextStatus, really not needed
|
|
594
|
+
gitCommitMessageFn,
|
|
595
|
+
lumpVariables,
|
|
596
|
+
projectRoot,
|
|
597
|
+
baseBranch,
|
|
598
|
+
});
|
|
599
|
+
}));
|
|
600
|
+
const contextStatusMap = new Map(allCtxNamesList.map((contextName, i) => [contextName, contextStatusList[i]]));
|
|
601
|
+
const contextListToDo = contextList
|
|
602
|
+
.filter((context, contextIndex) => {
|
|
603
|
+
const contextStatus = contextStatusList[contextIndex];
|
|
604
|
+
if (contextStatus && contextStatus !== 'toDo')
|
|
605
|
+
return false;
|
|
606
|
+
const deps = context.options?.dependsOnContexts;
|
|
607
|
+
if (deps && deps.length > 0) {
|
|
608
|
+
return deps.every(dep => contextStatusMap.get(dep) === 'finished');
|
|
609
|
+
}
|
|
610
|
+
return true;
|
|
611
|
+
})
|
|
612
|
+
.sort((a, b) => {
|
|
613
|
+
return (a.options?.priority || 0) - (b.options?.priority || 0);
|
|
614
|
+
});
|
|
615
|
+
console.log('contextListToDo', contextListToDo);
|
|
616
|
+
return success(contextListToDo);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const contextStatus = ['toDo', 'branchPushed', 'finished'];
|
|
620
|
+
const contextStatusSchema = z.enum(contextStatus);
|
|
621
|
+
|
|
622
|
+
const defaultGitCommitMessageFn = ({ context }) => {
|
|
623
|
+
return `LUMP:${context.name}`;
|
|
624
|
+
};
|
|
625
|
+
const defaultGitPushCommandFn = (input) => {
|
|
626
|
+
return `git push origin ${shellSingleQuote(input.branchName)}`;
|
|
627
|
+
};
|
|
628
|
+
const defaultGitAddCommandFn = () => {
|
|
629
|
+
return `git add .`;
|
|
630
|
+
};
|
|
631
|
+
const defaultGitCommitCommandFn = (input) => {
|
|
632
|
+
return `git commit -m ${shellSingleQuote(input.commitMessage)}`;
|
|
633
|
+
};
|
|
634
|
+
const defaultSetupWorkspaceFn = async (input) => {
|
|
635
|
+
const { baseBranch, branchName } = input;
|
|
636
|
+
return {
|
|
637
|
+
command: `
|
|
638
|
+
git switch ${baseBranch};
|
|
639
|
+
git reset --hard origin/${baseBranch};
|
|
640
|
+
git fetch --all;
|
|
641
|
+
git pull origin ${baseBranch};
|
|
642
|
+
git branch -D ${branchName};
|
|
643
|
+
git switch -c ${branchName};
|
|
644
|
+
`,
|
|
645
|
+
workspacePath: '.',
|
|
646
|
+
};
|
|
647
|
+
};
|
|
648
|
+
const defaultTeardownWorkspaceFn = async (input) => {
|
|
649
|
+
const { baseBranch } = input;
|
|
650
|
+
return `git switch ${baseBranch}`;
|
|
651
|
+
};
|
|
652
|
+
const defaultTeardownWorkspaceFnWithWorktree = async (input) => {
|
|
653
|
+
return "";
|
|
654
|
+
};
|
|
655
|
+
const defaultSetupWorkspaceFnWithWorktree = async (input) => {
|
|
656
|
+
const { baseBranch, branchName } = input;
|
|
657
|
+
const worktreePath = `lump-wkt/${branchName}`;
|
|
658
|
+
return {
|
|
659
|
+
command: `git switch ${baseBranch} &&
|
|
660
|
+
git pull origin ${baseBranch} &&
|
|
661
|
+
git worktree remove ${worktreePath} &&
|
|
662
|
+
git branch -D ${branchName} &&
|
|
663
|
+
git push --delete origin ${branchName} &&
|
|
664
|
+
git worktree add -b ${branchName} ${worktreePath}`,
|
|
665
|
+
workspacePath: worktreePath,
|
|
666
|
+
};
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
async function runLump(input) {
|
|
670
|
+
const { baseBranch, branchFn, lumpVariables = {}, getContextListFn, gitAddCommandFn = defaultGitAddCommandFn, gitCommitCommandFn = defaultGitCommitCommandFn, gitCommitMessageFn = defaultGitCommitMessageFn, gitPushCommandFn = defaultGitPushCommandFn, numberOfContextsPerBranch = 1, projectRoot, steps, setupFn = () => ({ contextRunState: {} }), setupWorkspaceFn = defaultSetupWorkspaceFn, teardownFn = () => undefined, teardownWorkspaceFn = defaultTeardownWorkspaceFn, verbose = false, getKeepHistoryFilePathFn = () => undefined, } = input;
|
|
671
|
+
const contextListToDoResult = await getToDoContextList({
|
|
672
|
+
getContextListFn,
|
|
673
|
+
lumpVariables,
|
|
674
|
+
projectRoot,
|
|
675
|
+
baseBranch,
|
|
676
|
+
gitCommitMessageFn,
|
|
677
|
+
});
|
|
678
|
+
if (!contextListToDoResult.success) {
|
|
679
|
+
return set(contextListToDoResult, ['data', 'message'], "Error in runLump: Failed to get to do context list. Original Error: " + contextListToDoResult.data.message);
|
|
680
|
+
}
|
|
681
|
+
const contextListToDo = contextListToDoResult.data;
|
|
682
|
+
const nextContextsForBranchList = contextListToDo.slice(0, numberOfContextsPerBranch);
|
|
683
|
+
if (nextContextsForBranchList.length === 0) {
|
|
684
|
+
console.log('no next contexts for branch');
|
|
685
|
+
return success({
|
|
686
|
+
result: {
|
|
687
|
+
updatedGroupStatusRecord: {
|
|
688
|
+
data: {},
|
|
689
|
+
},
|
|
690
|
+
branchName: '',
|
|
691
|
+
contextNames: [],
|
|
692
|
+
contextRunStateList: [],
|
|
693
|
+
},
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
const executeStepsResult = await executeStepsForContextList({
|
|
697
|
+
baseBranch: baseBranch,
|
|
698
|
+
branchFn: branchFn,
|
|
699
|
+
lumpVariables: lumpVariables,
|
|
700
|
+
contextList: nextContextsForBranchList,
|
|
701
|
+
gitAddCommandFn,
|
|
702
|
+
gitCommitCommandFn,
|
|
703
|
+
gitCommitMessageFn,
|
|
704
|
+
gitPushCommandFn,
|
|
705
|
+
projectRoot,
|
|
706
|
+
steps,
|
|
707
|
+
setupFn,
|
|
708
|
+
setupWorkspaceFn,
|
|
709
|
+
teardownFn,
|
|
710
|
+
teardownWorkspaceFn,
|
|
711
|
+
verbose,
|
|
712
|
+
getKeepHistoryFilePathFn,
|
|
713
|
+
});
|
|
714
|
+
if (!executeStepsResult.success) {
|
|
715
|
+
return set(executeStepsResult, ['data', 'message'], "Error in runLump: Failed to execute steps for context list. Original Error: " + executeStepsResult.data.message);
|
|
716
|
+
}
|
|
717
|
+
return success({
|
|
718
|
+
result: executeStepsResult.data,
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
export { collectStepsForContext, contextStatus, contextStatusSchema, decision, defaultGitAddCommandFn, defaultGitCommitCommandFn, defaultGitCommitMessageFn, defaultGitPushCommandFn, defaultSetupWorkspaceFn, defaultSetupWorkspaceFnWithWorktree, defaultTeardownWorkspaceFn, defaultTeardownWorkspaceFnWithWorktree, execAsync, execBinary, executeStepsForContextList, failure, getCodeBasePaths, getContextStatus, getToDoContextList, runLump, set, shellBestEffort, shellSingleQuote, success, validateContextListNames };
|
|
723
|
+
//# sourceMappingURL=index.js.map
|