reslop 0.2.7 → 0.3.1
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 +30 -1
- package/README.md +16 -14
- package/bin/reslop.js +8 -5
- package/lib/agents/agents.js +573 -0
- package/lib/agents/allow.js +71 -0
- package/lib/agents/allow.json +17 -0
- package/lib/agents/models.js +467 -0
- package/lib/api.js +15 -12
- package/lib/cli.js +43 -68
- package/lib/{files.js → common/files.js} +48 -55
- package/lib/{find.js → common/find.js} +1 -1
- package/lib/common/format.js +101 -0
- package/lib/{utilities.js → common/process.js} +7 -95
- package/lib/common/tasks.json +27 -0
- package/lib/common/utilities.js +112 -0
- package/lib/dashboard/git.js +9 -16
- package/lib/dashboard/model.js +90 -49
- package/lib/dashboard/npm.js +17 -13
- package/lib/dashboard/tree.js +27 -30
- package/lib/{session → dashboard}/watch.js +36 -31
- package/lib/{workspace.js → dashboard/workspace.js} +23 -38
- package/lib/{deps.js → deps/deps.js} +31 -45
- package/lib/{deps-diff.js → deps/diff.js} +35 -25
- package/lib/{manifest.js → deps/manifest.js} +47 -30
- package/lib/diff/align.js +1 -2
- package/lib/diff/diff.js +2 -2
- package/lib/diff/display.js +29 -5
- package/lib/diff/inline.js +10 -14
- package/lib/diff/items.js +6 -4
- package/lib/diff/patch.js +39 -3
- package/lib/diff/unit.js +45 -16
- package/lib/{git-branches.js → git/branches.js} +53 -48
- package/lib/{git-deps.js → git/deps.js} +151 -95
- package/lib/git/git.js +71 -0
- package/lib/git/worktree.js +504 -0
- package/lib/highlight/bash.js +1 -2
- package/lib/highlight/csv.js +1 -2
- package/lib/highlight/dot.js +1 -2
- package/lib/{highlight.js → highlight/highlight.js} +42 -11
- package/lib/highlight/html.js +20 -18
- package/lib/highlight/json.js +1 -2
- package/lib/highlight/log.js +1 -2
- package/lib/highlight/txt.js +1 -2
- package/lib/{session → input}/actions.js +114 -48
- package/lib/{editor.js → input/editor.js} +16 -8
- package/lib/{keys.js → input/keys.js} +24 -45
- package/lib/input/line-edit.js +78 -0
- package/lib/input/menu-pick.js +70 -0
- package/lib/render/agents.js +642 -0
- package/lib/render/branches.js +4 -5
- package/lib/render/commits.js +54 -64
- package/lib/render/{dash-activity.js → dashboard/activity.js} +25 -40
- package/lib/render/{dash-blocks.js → dashboard/blocks.js} +131 -137
- package/lib/render/{dashboard.js → dashboard/dashboard.js} +25 -22
- package/lib/render/diff.js +166 -45
- package/lib/render/field.js +131 -0
- package/lib/render/files.js +9 -14
- package/lib/render/footer.js +385 -0
- package/lib/render/frame.js +123 -25
- package/lib/render/header.js +176 -0
- package/lib/render/log.js +320 -0
- package/lib/render/menu.js +60 -0
- package/lib/render/notes.js +16 -11
- package/lib/render/npm.js +322 -196
- package/lib/render/packages.js +9 -13
- package/lib/render/primitives.js +101 -15
- package/lib/render/render.js +7 -11
- package/lib/render/repos.js +13 -25
- package/lib/render/status.js +370 -0
- package/lib/render/status.json +85 -0
- package/lib/render/{dash-table.js → table.js} +13 -60
- package/lib/render/tiles.js +109 -48
- package/lib/render/unit.js +32 -13
- package/lib/{report-model.js → report/model.js} +4 -6
- package/lib/{report-parse.js → report/parse.js} +9 -14
- package/lib/{report-render.js → report/render.js} +48 -19
- package/lib/{report-run.js → report/run.js} +42 -30
- package/lib/{report-test.js → report/test.js} +56 -55
- package/lib/{report-tools.js → report/tools.js} +24 -33
- package/lib/review/agent-instructions.md +14 -0
- package/lib/review/format.js +420 -0
- package/lib/{review-merge.js → review/merge.js} +9 -8
- package/lib/review/review.js +190 -0
- package/lib/review/store.js +281 -0
- package/lib/review/templates.js +83 -0
- package/lib/runs/commands.js +14 -0
- package/lib/runs/logs.js +299 -0
- package/lib/runs/output.js +174 -0
- package/lib/runs/process.js +113 -0
- package/lib/{runs.js → runs/runs.js} +84 -36
- package/lib/runs/scripts.js +150 -0
- package/lib/session/agents/agents.js +976 -0
- package/lib/session/agents/job.js +320 -0
- package/lib/session/agents/jobs.js +355 -0
- package/lib/session/agents/options.js +153 -0
- package/lib/session/agents/plans.js +83 -0
- package/lib/session/branches.js +33 -40
- package/lib/session/change-actions.js +34 -100
- package/lib/session/commit.js +91 -52
- package/lib/session/compose.js +189 -147
- package/lib/session/dashboard.js +23 -22
- package/lib/session/dispatch.js +86 -21
- package/lib/session/files-pane.js +47 -26
- package/lib/session/find.js +16 -29
- package/lib/session/import.js +93 -0
- package/lib/session/items.js +8 -17
- package/lib/session/lifecycle.js +78 -72
- package/lib/session/load.js +2 -4
- package/lib/session/navigation.js +6 -3
- package/lib/session/npm/history.js +250 -0
- package/lib/session/npm/npm.js +836 -0
- package/lib/session/{packages.js → npm/packages.js} +21 -14
- package/lib/session/ops.js +125 -34
- package/lib/session/pointer.js +202 -10
- package/lib/session/prefs.js +112 -0
- package/lib/session/reads.js +109 -0
- package/lib/session/review.js +28 -10
- package/lib/session/run-panel.js +40 -0
- package/lib/{session.js → session/session.js} +158 -63
- package/lib/session/tasks.js +321 -66
- package/lib/session/templates.js +1 -1
- package/lib/session/terminal.js +94 -12
- package/lib/session/unit.js +35 -30
- package/lib/session/update.js +194 -6
- package/lib/session/view.js +65 -65
- package/lib/session/workspace.js +39 -78
- package/lib/{capabilities.js → source/capabilities.js} +3 -12
- package/lib/{github.js → source/github.js} +102 -32
- package/lib/{gitlab.js → source/gitlab.js} +87 -10
- package/lib/{remote.js → source/remote.js} +144 -40
- package/lib/source/review-threads.graphql +20 -0
- package/lib/source/source.js +74 -0
- package/lib/term/ansi.js +396 -0
- package/lib/{clipboard.js → term/clipboard.js} +3 -6
- package/lib/{select.js → term/select.js} +4 -3
- package/lib/term/themes/dark.json +122 -0
- package/lib/term/themes/light.json +122 -0
- package/lib/term/wide.txt +21 -0
- package/lib/{wrap.js → term/wrap.js} +4 -4
- package/package.json +2 -2
- package/lib/ansi.js +0 -545
- package/lib/detect.js +0 -34
- package/lib/diff/edit.js +0 -33
- package/lib/git-worktree.js +0 -455
- package/lib/git.js +0 -79
- package/lib/npm-commands.js +0 -522
- package/lib/render/chrome.js +0 -806
- package/lib/render/present.js +0 -19
- package/lib/render/report.js +0 -43
- package/lib/render/search.js +0 -25
- package/lib/review.js +0 -745
- package/lib/session/accessors.js +0 -26
- package/lib/session/edit-click.js +0 -57
- package/lib/session/npm.js +0 -452
- package/lib/session/progress.js +0 -41
- package/lib/source.js +0 -36
- package/lib/update.js +0 -192
- /package/lib/{git-reword-todo.js → git/reword-todo.js} +0 -0
|
@@ -3,22 +3,28 @@
|
|
|
3
3
|
const fs = require('node:fs');
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
|
|
6
|
-
const deps = require('
|
|
6
|
+
const deps = require('../deps/deps.js');
|
|
7
7
|
const { foldDepItems, mergeProposedItems } = deps;
|
|
8
8
|
const { parseAuditReport, parseOutdatedReport } = deps;
|
|
9
9
|
const { collectUsedNames, collectExportMeta } = deps;
|
|
10
|
-
const
|
|
10
|
+
const { collectGroups } = require('../deps/diff.js');
|
|
11
|
+
const manifest = require('../deps/manifest.js');
|
|
11
12
|
const { MANIFEST, LOCKFILE, depFileMeta, mergeDepFile, relOf } = manifest;
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
const { itemPath, isPathInScope } = require('../common/files.js');
|
|
14
|
+
const utilities = require('../common/utilities.js');
|
|
15
|
+
const {
|
|
16
|
+
INSTALL_MS,
|
|
17
|
+
IS_WIN,
|
|
18
|
+
abortError,
|
|
19
|
+
npmBin,
|
|
20
|
+
runProc,
|
|
21
|
+
} = require('../common/process.js');
|
|
22
|
+
const { oneLine } = utilities;
|
|
23
|
+
const worktree = require('./worktree.js');
|
|
24
|
+
const { gitOk, indexedText, worktreeText, readDepSides } = worktree;
|
|
18
25
|
const { revertOnePath, groupByPath, writeFile, writeIndex } = worktree;
|
|
19
26
|
|
|
20
27
|
const AUDIT_MS = 15000;
|
|
21
|
-
const INSTALL_MS = 120000;
|
|
22
28
|
|
|
23
29
|
const NPM_REPORT = {
|
|
24
30
|
audit: {
|
|
@@ -41,21 +47,11 @@ const npmOptions = (cwd, timeout, signal) => ({
|
|
|
41
47
|
});
|
|
42
48
|
|
|
43
49
|
const runNpm = (cwd, args) =>
|
|
44
|
-
runProcSync(npmBin(), args, npmOptions(cwd, INSTALL_MS));
|
|
45
|
-
|
|
46
|
-
const runNpmAsync = (cwd, args) =>
|
|
47
50
|
runProc(npmBin(), args, npmOptions(cwd, INSTALL_MS));
|
|
48
51
|
|
|
49
52
|
const npmOutput = (result) => (result.error ? '' : result.stdout);
|
|
50
53
|
|
|
51
|
-
const collectReport = (top, kind) => {
|
|
52
|
-
const report = NPM_REPORT[kind];
|
|
53
|
-
if (!fs.existsSync(path.join(top, report.file))) return null;
|
|
54
|
-
const options = npmOptions(top, AUDIT_MS);
|
|
55
|
-
return report.parse(npmOutput(runProcSync(npmBin(), report.args, options)));
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const collectReportAsync = async (top, kind, signal) => {
|
|
54
|
+
const collectReport = async (top, kind, signal) => {
|
|
59
55
|
const report = NPM_REPORT[kind];
|
|
60
56
|
if (!fs.existsSync(path.join(top, report.file))) return null;
|
|
61
57
|
const options = npmOptions(top, AUDIT_MS, signal);
|
|
@@ -67,13 +63,16 @@ const depPaths = (item) => item.dep?.files ?? [];
|
|
|
67
63
|
|
|
68
64
|
const depChange = (item) => item.dep?.change ?? null;
|
|
69
65
|
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
66
|
+
const isStagedOrCommit = (item) => {
|
|
67
|
+
const staged = item.origin === 'staged';
|
|
68
|
+
const commit = item.origin === 'commit';
|
|
69
|
+
return staged || commit;
|
|
70
|
+
};
|
|
74
71
|
|
|
75
|
-
const firstDepRel = (rels, kind) =>
|
|
76
|
-
|
|
72
|
+
const firstDepRel = (rels, kind) => {
|
|
73
|
+
const match = (rel) => depFileMeta(rel)?.kind === kind;
|
|
74
|
+
return rels.find(match) ?? '';
|
|
75
|
+
};
|
|
77
76
|
|
|
78
77
|
const proposedNpmPlan = (top, item) => {
|
|
79
78
|
const change = depChange(item);
|
|
@@ -118,8 +117,25 @@ const extrasNeeds = (items, rev, extra) => {
|
|
|
118
117
|
return { live, scan: live || hasDepDiff, audit };
|
|
119
118
|
};
|
|
120
119
|
|
|
121
|
-
const
|
|
122
|
-
|
|
120
|
+
const NO_SIDES = { oldText: '', newText: '' };
|
|
121
|
+
|
|
122
|
+
const sidesReader = async (items, top, rev) => {
|
|
123
|
+
const sides = new Map();
|
|
124
|
+
const reads = [];
|
|
125
|
+
for (const group of collectGroups(items).values()) {
|
|
126
|
+
for (const name of [MANIFEST, LOCKFILE]) {
|
|
127
|
+
const rel = relOf(group.dir, name);
|
|
128
|
+
const key = `${group.origin}\0${rel}`;
|
|
129
|
+
const keep = (found) => sides.set(key, found);
|
|
130
|
+
reads.push(readDepSides(top, rev, group.origin, rel).then(keep));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
await Promise.all(reads);
|
|
134
|
+
return (origin, rel) => sides.get(`${origin}\0${rel}`) ?? NO_SIDES;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const foldLoaded = async (items, top, rev, extra) => {
|
|
138
|
+
const readSides = await sidesReader(items, top, rev);
|
|
123
139
|
const needs = extrasNeeds(items, rev, extra);
|
|
124
140
|
const collect = extra.collect !== false;
|
|
125
141
|
const scan = collect && needs.scan;
|
|
@@ -129,10 +145,10 @@ const foldLoaded = (items, top, rev, extra) => {
|
|
|
129
145
|
exportEntries = collectExportMeta(top);
|
|
130
146
|
}
|
|
131
147
|
if (collect && needs.audit && audit === undefined) {
|
|
132
|
-
audit = collectReport(top, 'audit');
|
|
148
|
+
audit = await collectReport(top, 'audit', extra.signal);
|
|
133
149
|
}
|
|
134
150
|
if (collect && needs.live && outdated === undefined) {
|
|
135
|
-
outdated = collectReport(top, 'outdated');
|
|
151
|
+
outdated = await collectReport(top, 'outdated', extra.signal);
|
|
136
152
|
}
|
|
137
153
|
audit ??= null;
|
|
138
154
|
outdated ??= null;
|
|
@@ -141,16 +157,16 @@ const foldLoaded = (items, top, rev, extra) => {
|
|
|
141
157
|
exportEntries,
|
|
142
158
|
});
|
|
143
159
|
if (!needs.live || !isPathInScope(MANIFEST, extra.paths)) return folded;
|
|
144
|
-
const
|
|
145
|
-
const lockText =
|
|
160
|
+
const texts = [worktreeText(top, MANIFEST), worktreeText(top, LOCKFILE)];
|
|
161
|
+
const [pkgText, lockText] = await Promise.all(texts);
|
|
146
162
|
const options = { lockText, usedNames, root: top, exportEntries };
|
|
147
163
|
return mergeProposedItems(folded, pkgText, outdated, audit, options);
|
|
148
164
|
};
|
|
149
165
|
|
|
150
|
-
const finishLoad = (snapshot, extra) => {
|
|
166
|
+
const finishLoad = async (snapshot, extra) => {
|
|
151
167
|
const { top, rev, parsed } = snapshot;
|
|
152
168
|
const options = { ...extra, collect: !extra.deferExtras };
|
|
153
|
-
const items = foldLoaded(parsed, top, rev, options);
|
|
169
|
+
const items = await foldLoaded(parsed, top, rev, options);
|
|
154
170
|
const pending = extra.deferExtras && extrasNeeds(parsed, rev, extra).audit;
|
|
155
171
|
return { ...snapshot, items, pending };
|
|
156
172
|
};
|
|
@@ -167,21 +183,23 @@ const loadExtras = async (snapshot, extra = {}) => {
|
|
|
167
183
|
const { signal } = extra;
|
|
168
184
|
const needs = extrasNeeds(parsed, rev, extra);
|
|
169
185
|
const known = extra.exportEntries;
|
|
186
|
+
let exportMeta = known;
|
|
187
|
+
if (known === undefined && needs.scan) {
|
|
188
|
+
exportMeta = later(() => collectExportMeta(top));
|
|
189
|
+
}
|
|
170
190
|
const [usedNames, audit, outdated, exportEntries] = await Promise.all([
|
|
171
191
|
needs.scan ? later(() => collectUsedNames(top)) : null,
|
|
172
192
|
reportTask(needs.audit, extra.auditMap, () =>
|
|
173
|
-
|
|
193
|
+
collectReport(top, 'audit', signal),
|
|
174
194
|
),
|
|
175
195
|
reportTask(needs.live, extra.outdatedMap, () =>
|
|
176
|
-
|
|
196
|
+
collectReport(top, 'outdated', signal),
|
|
177
197
|
),
|
|
178
|
-
|
|
179
|
-
? later(() => collectExportMeta(top))
|
|
180
|
-
: known,
|
|
198
|
+
exportMeta,
|
|
181
199
|
]);
|
|
182
200
|
if (signal && signal.aborted) throw abortError();
|
|
183
201
|
const found = { usedNames, auditMap: audit, outdatedMap: outdated };
|
|
184
|
-
const items = foldLoaded(parsed, top, rev, {
|
|
202
|
+
const items = await foldLoaded(parsed, top, rev, {
|
|
185
203
|
...extra,
|
|
186
204
|
...found,
|
|
187
205
|
paths: extra.paths ?? [],
|
|
@@ -207,23 +225,23 @@ const restoreFile = (top, saved) => {
|
|
|
207
225
|
else fs.rmSync(abs, { force: true });
|
|
208
226
|
};
|
|
209
227
|
|
|
210
|
-
const mergeLive = (top, rel, item, base, side) => {
|
|
211
|
-
const sides = readDepSides(top, null, item.origin, rel);
|
|
228
|
+
const mergeLive = async (top, rel, item, base, side) => {
|
|
229
|
+
const sides = await readDepSides(top, null, item.origin, rel);
|
|
212
230
|
const { kind } = depFileMeta(rel);
|
|
213
231
|
const change = depChange(item);
|
|
214
232
|
return mergeDepFile(base, sides.oldText, sides.newText, change, side, kind);
|
|
215
233
|
};
|
|
216
234
|
|
|
217
|
-
const applyDepIndex = (top, rel, item, side) => {
|
|
235
|
+
const applyDepIndex = async (top, rel, item, side) => {
|
|
218
236
|
if (!depFileMeta(rel)) return;
|
|
219
|
-
const indexed =
|
|
220
|
-
writeIndex(top, rel, mergeLive(top, rel, item, indexed, side));
|
|
237
|
+
const indexed = await indexedText(top, rel);
|
|
238
|
+
await writeIndex(top, rel, await mergeLive(top, rel, item, indexed, side));
|
|
221
239
|
};
|
|
222
240
|
|
|
223
|
-
const applyDepWorktree = (top, rel, item, side) => {
|
|
241
|
+
const applyDepWorktree = async (top, rel, item, side) => {
|
|
224
242
|
if (!depFileMeta(rel)) return;
|
|
225
|
-
const
|
|
226
|
-
writeFile(top, rel,
|
|
243
|
+
const live = await worktreeText(top, rel);
|
|
244
|
+
await writeFile(top, rel, await mergeLive(top, rel, item, live, side));
|
|
227
245
|
};
|
|
228
246
|
|
|
229
247
|
const npmError = (result, fail) => {
|
|
@@ -232,12 +250,12 @@ const npmError = (result, fail) => {
|
|
|
232
250
|
return new Error(oneLine(msg || fail, fail));
|
|
233
251
|
};
|
|
234
252
|
|
|
235
|
-
const stagePlan = (top, plan) => {
|
|
253
|
+
const stagePlan = async (top, plan) => {
|
|
236
254
|
const toAdd = [];
|
|
237
255
|
if (!plan.lockOnly && plan.manifest) toAdd.push(plan.manifest);
|
|
238
256
|
if (fs.existsSync(path.join(top, plan.lockPath))) toAdd.push(plan.lockPath);
|
|
239
257
|
if (!toAdd.length) return;
|
|
240
|
-
|
|
258
|
+
await gitOk(['add', '--', ...toAdd], top);
|
|
241
259
|
};
|
|
242
260
|
|
|
243
261
|
const startPlan = (top, item) => {
|
|
@@ -248,113 +266,151 @@ const startPlan = (top, item) => {
|
|
|
248
266
|
return { plan, owned };
|
|
249
267
|
};
|
|
250
268
|
|
|
251
|
-
const finishPlan = (top, plan, result, stage = stagePlan) => {
|
|
269
|
+
const finishPlan = async (top, plan, result, stage = stagePlan) => {
|
|
252
270
|
const failed = result && (result.error || result.status !== 0);
|
|
253
271
|
if (failed) throw npmError(result, plan.fail);
|
|
254
|
-
stage(top, plan);
|
|
272
|
+
await stage(top, plan);
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const manifestPlan = (top, rel) => {
|
|
276
|
+
const meta = depFileMeta(rel);
|
|
277
|
+
if (!meta || meta.kind !== 'manifest') return null;
|
|
278
|
+
return {
|
|
279
|
+
cwd: meta.dir === '.' ? top : path.join(top, meta.dir),
|
|
280
|
+
npmArgs: ['i'],
|
|
281
|
+
fail: 'npm i failed',
|
|
282
|
+
lockOnly: false,
|
|
283
|
+
lockPath: relOf(meta.dir, LOCKFILE),
|
|
284
|
+
manifest: rel,
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const syncManifest = async (top, rel, extra = {}) => {
|
|
289
|
+
const plan = manifestPlan(top, rel);
|
|
290
|
+
if (!plan) return;
|
|
291
|
+
const install = extra.run ?? runNpm;
|
|
292
|
+
const result = await install(plan.cwd, plan.npmArgs);
|
|
293
|
+
await finishPlan(top, plan, result, extra.stage);
|
|
255
294
|
};
|
|
256
295
|
|
|
257
296
|
const restoreOwned = (top, owned) => {
|
|
258
297
|
for (const saved of owned) restoreFile(top, saved);
|
|
259
298
|
};
|
|
260
299
|
|
|
261
|
-
const
|
|
262
|
-
const started = startPlan(top, item);
|
|
263
|
-
if (!started) return;
|
|
264
|
-
const { plan, owned } = started;
|
|
265
|
-
try {
|
|
266
|
-
if (plan.prepareManifest) applyDepWorktree(top, plan.manifest, item, 'new');
|
|
267
|
-
const install = extra.run ?? plan.runner ?? runNpm;
|
|
268
|
-
finishPlan(top, plan, install(plan.cwd, plan.npmArgs), extra.stage);
|
|
269
|
-
} catch (error) {
|
|
270
|
-
restoreOwned(top, owned);
|
|
271
|
-
throw error;
|
|
272
|
-
}
|
|
273
|
-
};
|
|
300
|
+
const unlocked = (write) => write();
|
|
274
301
|
|
|
275
|
-
|
|
302
|
+
// The install can run for minutes, so only the file and index steps around
|
|
303
|
+
// it go through the caller's write lock
|
|
304
|
+
const applyProposedUpdate = async (top, item, extra = {}) => {
|
|
276
305
|
const started = startPlan(top, item);
|
|
277
306
|
if (!started) return;
|
|
278
307
|
const { plan, owned } = started;
|
|
308
|
+
const locked = extra.locked ?? unlocked;
|
|
279
309
|
try {
|
|
280
|
-
if (plan.prepareManifest)
|
|
281
|
-
|
|
282
|
-
|
|
310
|
+
if (plan.prepareManifest) {
|
|
311
|
+
await locked(() => applyDepWorktree(top, plan.manifest, item, 'new'));
|
|
312
|
+
}
|
|
313
|
+
const install = extra.run ?? plan.runner ?? runNpm;
|
|
314
|
+
const result = await install(plan.cwd, plan.npmArgs);
|
|
315
|
+
await locked(() => finishPlan(top, plan, result, extra.stage));
|
|
283
316
|
} catch (error) {
|
|
284
317
|
restoreOwned(top, owned);
|
|
285
318
|
throw error;
|
|
286
319
|
}
|
|
287
320
|
};
|
|
288
321
|
|
|
289
|
-
const applyDepChange = (top, item, mode) => {
|
|
322
|
+
const applyDepChange = async (top, item, mode, extra) => {
|
|
290
323
|
const change = depChange(item);
|
|
291
324
|
if (change.propose) {
|
|
292
|
-
if (mode === 'add')
|
|
325
|
+
if (mode === 'add') {
|
|
326
|
+
await applyProposedUpdate(top, item, extra);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
293
329
|
if (!change.unused) return;
|
|
294
330
|
}
|
|
295
331
|
for (const rel of depPaths(item)) {
|
|
296
332
|
if (mode !== 'revert') {
|
|
297
|
-
applyDepIndex(top, rel, item, mode === 'add' ? 'new' : 'old');
|
|
333
|
+
await applyDepIndex(top, rel, item, mode === 'add' ? 'new' : 'old');
|
|
298
334
|
continue;
|
|
299
335
|
}
|
|
300
|
-
if (item.origin === 'staged') applyDepIndex(top, rel, item, 'old');
|
|
301
|
-
applyDepWorktree(top, rel, item, 'old');
|
|
336
|
+
if (item.origin === 'staged') await applyDepIndex(top, rel, item, 'old');
|
|
337
|
+
await applyDepWorktree(top, rel, item, 'old');
|
|
302
338
|
}
|
|
303
339
|
};
|
|
304
340
|
|
|
305
|
-
const addItem = (top, item) => {
|
|
306
|
-
if (!item.dep)
|
|
341
|
+
const addItem = async (top, item, extra) => {
|
|
342
|
+
if (!item.dep) {
|
|
343
|
+
await worktree.addItem(top, item);
|
|
344
|
+
await syncManifest(top, itemPath(item), extra);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
307
347
|
if (isStagedOrCommit(item)) return;
|
|
308
|
-
if (depChange(item))
|
|
348
|
+
if (depChange(item)) {
|
|
349
|
+
await applyDepChange(top, item, 'add', extra);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
309
352
|
const rels = depPaths(item);
|
|
310
|
-
if (rels.length)
|
|
353
|
+
if (rels.length) await gitOk(['add', '--', ...rels], top);
|
|
311
354
|
};
|
|
312
355
|
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
await applyProposedUpdateAsync(top, item);
|
|
356
|
+
const stagePath = async (top, rel, extra) => {
|
|
357
|
+
await worktree.stagePath(top, rel);
|
|
358
|
+
await syncManifest(top, rel, extra);
|
|
318
359
|
};
|
|
319
360
|
|
|
320
|
-
const unstageItem = (top, item) => {
|
|
321
|
-
if (!item.dep)
|
|
361
|
+
const unstageItem = async (top, item) => {
|
|
362
|
+
if (!item.dep) {
|
|
363
|
+
await worktree.unstageItem(top, item);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
322
366
|
if (item.origin !== 'staged') return;
|
|
323
|
-
if (depChange(item))
|
|
367
|
+
if (depChange(item)) {
|
|
368
|
+
await applyDepChange(top, item, 'unstage');
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
324
371
|
const rels = depPaths(item);
|
|
325
372
|
if (!rels.length) return;
|
|
326
|
-
|
|
373
|
+
await gitOk(['restore', '--staged', '--', ...rels], top);
|
|
327
374
|
};
|
|
328
375
|
|
|
329
|
-
const revertItem = (top, item) => {
|
|
376
|
+
const revertItem = async (top, item) => {
|
|
330
377
|
if (item.origin === 'commit') return;
|
|
331
|
-
if (!item.dep)
|
|
332
|
-
|
|
378
|
+
if (!item.dep) {
|
|
379
|
+
await worktree.revertItem(top, item);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (depChange(item)) {
|
|
383
|
+
await applyDepChange(top, item, 'revert');
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
333
386
|
const byPath = groupByPath(item.dep.items ?? []);
|
|
334
|
-
for (const rel of byPath.keys())
|
|
387
|
+
for (const rel of byPath.keys()) {
|
|
388
|
+
await revertOnePath(top, rel, byPath.get(rel));
|
|
389
|
+
}
|
|
335
390
|
};
|
|
336
391
|
|
|
337
|
-
const revertFile = (top, rel, items) => {
|
|
392
|
+
const revertFile = async (top, rel, items) => {
|
|
338
393
|
const rels = new Set([rel]);
|
|
339
394
|
for (const item of items) {
|
|
340
395
|
for (const file of depPaths(item)) rels.add(file);
|
|
341
396
|
}
|
|
342
397
|
for (const file of rels) {
|
|
343
398
|
const group = itemsForPath(file, items);
|
|
344
|
-
revertOnePath(top, file, group.length ? group : items);
|
|
399
|
+
await revertOnePath(top, file, group.length ? group : items);
|
|
345
400
|
}
|
|
346
401
|
};
|
|
347
402
|
|
|
348
403
|
module.exports = {
|
|
349
|
-
|
|
404
|
+
collectReport,
|
|
350
405
|
finishLoad,
|
|
351
406
|
loadExtras,
|
|
352
407
|
captureFile,
|
|
353
408
|
restoreFile,
|
|
354
409
|
proposedNpmPlan,
|
|
355
410
|
applyProposedUpdate,
|
|
411
|
+
syncManifest,
|
|
356
412
|
addItem,
|
|
357
|
-
|
|
413
|
+
stagePath,
|
|
358
414
|
unstageItem,
|
|
359
415
|
revertItem,
|
|
360
416
|
revertFile,
|
package/lib/git/git.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
capabilitiesFor,
|
|
5
|
+
attachCapabilities,
|
|
6
|
+
} = require('../source/capabilities.js');
|
|
7
|
+
const worktree = require('./worktree.js');
|
|
8
|
+
const branches = require('./branches.js');
|
|
9
|
+
const gitDeps = require('./deps.js');
|
|
10
|
+
|
|
11
|
+
const load = async (cwd, paths = [], options = {}) => {
|
|
12
|
+
const snapshot = await worktree.readSnapshot(cwd, paths, options);
|
|
13
|
+
const deferExtras = options.deferExtras ?? true;
|
|
14
|
+
return gitDeps.finishLoad(snapshot, { ...options, paths, deferExtras });
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const REPO_METHODS = {
|
|
18
|
+
load,
|
|
19
|
+
loadExtras: gitDeps.loadExtras,
|
|
20
|
+
toplevel: worktree.toplevel,
|
|
21
|
+
resolveRev: worktree.resolveRev,
|
|
22
|
+
listFiles: worktree.listScopeFiles,
|
|
23
|
+
fileText: worktree.fileText,
|
|
24
|
+
add: gitDeps.addItem,
|
|
25
|
+
unstage: gitDeps.unstageItem,
|
|
26
|
+
revert: gitDeps.revertItem,
|
|
27
|
+
revertFile: gitDeps.revertFile,
|
|
28
|
+
edit: worktree.editItem,
|
|
29
|
+
writeFile: worktree.writeFile,
|
|
30
|
+
stagePath: gitDeps.stagePath,
|
|
31
|
+
commit: branches.commitChanges,
|
|
32
|
+
updateCommit: branches.updateCommit,
|
|
33
|
+
hasStaged: branches.hasStaged,
|
|
34
|
+
lastMessage: branches.lastMessage,
|
|
35
|
+
commitMessage: branches.commitMessage,
|
|
36
|
+
listBranches: branches.listBranches,
|
|
37
|
+
listCommits: branches.listCommits,
|
|
38
|
+
currentBranch: worktree.currentBranch,
|
|
39
|
+
checkout: branches.checkoutBranch,
|
|
40
|
+
createBranch: branches.createBranch,
|
|
41
|
+
rebase: branches.rebaseBranch,
|
|
42
|
+
drop: branches.dropBranch,
|
|
43
|
+
dropCommit: branches.dropCommit,
|
|
44
|
+
applyFixup: branches.applyFixup,
|
|
45
|
+
reword: branches.rewordCommit,
|
|
46
|
+
pull: branches.pullChanges,
|
|
47
|
+
push: branches.pushChanges,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const createGitRepo = () =>
|
|
51
|
+
attachCapabilities(REPO_METHODS, capabilitiesFor('local'));
|
|
52
|
+
|
|
53
|
+
const listed = createGitRepo();
|
|
54
|
+
const unlisted = Object.keys(REPO_METHODS).filter(
|
|
55
|
+
(name) => !Object.hasOwn(listed, name),
|
|
56
|
+
);
|
|
57
|
+
if (unlisted.length) {
|
|
58
|
+
throw new Error(`git methods without a capability: ${unlisted.join(', ')}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {
|
|
62
|
+
...branches,
|
|
63
|
+
currentBranch: worktree.currentBranch,
|
|
64
|
+
editItem: worktree.editItem,
|
|
65
|
+
load,
|
|
66
|
+
loadExtras: gitDeps.loadExtras,
|
|
67
|
+
addItem: gitDeps.addItem,
|
|
68
|
+
unstageItem: gitDeps.unstageItem,
|
|
69
|
+
revertItem: gitDeps.revertItem,
|
|
70
|
+
createGitRepo,
|
|
71
|
+
};
|