reslop 0.2.7 → 0.3.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 +17 -1
- package/README.md +16 -14
- package/bin/reslop.js +8 -5
- package/lib/agents/agents.js +504 -0
- package/lib/agents/allow.js +71 -0
- package/lib/agents/allow.json +16 -0
- package/lib/agents/models.js +460 -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} +123 -96
- package/lib/git/git.js +71 -0
- package/lib/git/worktree.js +475 -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 +111 -48
- package/lib/{editor.js → input/editor.js} +7 -8
- package/lib/{keys.js → input/keys.js} +15 -43
- package/lib/input/line-edit.js +77 -0
- package/lib/input/menu-pick.js +70 -0
- package/lib/render/agents.js +640 -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 +383 -0
- package/lib/render/frame.js +123 -25
- package/lib/render/header.js +176 -0
- package/lib/render/log.js +319 -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} +46 -14
- 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 +9 -0
- package/lib/review/format.js +426 -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 +958 -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 -39
- package/lib/session/change-actions.js +34 -100
- package/lib/session/commit.js +91 -52
- package/lib/session/compose.js +181 -145
- package/lib/session/dashboard.js +23 -22
- package/lib/session/dispatch.js +85 -21
- package/lib/session/files-pane.js +47 -26
- package/lib/session/find.js +16 -29
- package/lib/session/import.js +82 -0
- package/lib/session/items.js +8 -17
- package/lib/session/lifecycle.js +75 -72
- package/lib/session/load.js +2 -4
- package/lib/session/navigation.js +6 -3
- package/lib/session/npm/history.js +249 -0
- package/lib/session/npm/npm.js +815 -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} +156 -63
- package/lib/session/tasks.js +320 -65
- 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} +2 -2
- 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
package/lib/session/unit.js
CHANGED
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { listPath, isTasksEntry } = files;
|
|
3
|
+
const { listPath, isTasksEntry } = require('../common/files.js');
|
|
5
4
|
const diff = require('../diff/diff.js');
|
|
6
5
|
const { unitLines, itemsForPath, blockLineIndex } = diff;
|
|
7
6
|
const { hunkLineRange, sameHunk, hunkKey } = diff;
|
|
8
7
|
const { fileOffset, splitEditor, mergeEditRows, fileLineIndex } = diff;
|
|
9
8
|
|
|
10
|
-
const fileText = (ui, rel) =>
|
|
11
|
-
if (!rel) return '';
|
|
12
|
-
const repo = ui.repo;
|
|
13
|
-
if (repo && typeof repo.fileText === 'function') {
|
|
14
|
-
return repo.fileText(ui.top, rel, ui.rev);
|
|
15
|
-
}
|
|
16
|
-
return '';
|
|
17
|
-
};
|
|
9
|
+
const fileText = (ui, rel) => ui.reads.textOf(rel);
|
|
18
10
|
|
|
19
11
|
const pathItems = (ui, rel) => itemsForPath(ui.items ?? [], rel);
|
|
20
12
|
|
|
21
|
-
const linesFor = (
|
|
22
|
-
ui
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
) => {
|
|
27
|
-
const text = overlay === null ? fileText(ui, rel) : overlay;
|
|
13
|
+
const linesFor = (ui, rel, overlay, base) => {
|
|
14
|
+
const live = ui.composer.liveFileText();
|
|
15
|
+
const shown = overlay === undefined ? live : overlay;
|
|
16
|
+
const seed = base === undefined ? null : base;
|
|
17
|
+
const text = shown === null ? fileText(ui, rel) : shown;
|
|
28
18
|
const group = pathItems(ui, rel);
|
|
29
|
-
if (
|
|
30
|
-
return mergeEditRows(
|
|
19
|
+
if (shown !== null && seed && seed.length) {
|
|
20
|
+
return mergeEditRows(seed, splitEditor(text));
|
|
31
21
|
}
|
|
32
22
|
return unitLines(text, group);
|
|
33
23
|
};
|
|
@@ -149,8 +139,8 @@ const moveUnitBlock = (ui, step) => {
|
|
|
149
139
|
nav.clearSelection();
|
|
150
140
|
};
|
|
151
141
|
|
|
152
|
-
const
|
|
153
|
-
|
|
142
|
+
const showFile = async (ui, entry) => {
|
|
143
|
+
await ui.reads.loadText(entry.path);
|
|
154
144
|
const nav = ui.nav;
|
|
155
145
|
nav.reviewPath = entry.path;
|
|
156
146
|
nav.tasksOpen = false;
|
|
@@ -170,12 +160,28 @@ const openUnitFile = (ui, entry) => {
|
|
|
170
160
|
ui.status = '';
|
|
171
161
|
};
|
|
172
162
|
|
|
173
|
-
const
|
|
174
|
-
if (
|
|
175
|
-
|
|
163
|
+
const openUnitFile = (ui, entry) => {
|
|
164
|
+
if (!entry || isTasksEntry(entry)) return;
|
|
165
|
+
ui.ops.hold(showFile(ui, entry));
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const applyFileScope = (ui, next, quiet) => {
|
|
176
169
|
ui.nav.fileScope = next;
|
|
177
170
|
ui.nav.restoreFileCursor(ui.fileList());
|
|
178
|
-
|
|
171
|
+
const label = next === 'file' ? 'file scope' : 'diff mode';
|
|
172
|
+
ui.status = quiet ? '' : label;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const listScope = async (ui, quiet) => {
|
|
176
|
+
await ui.reads.loadNames();
|
|
177
|
+
applyFileScope(ui, 'file', quiet);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const setFileScope = (ui, next, quiet = false) => {
|
|
181
|
+
if (ui.nav.pane !== 'files') return;
|
|
182
|
+
if (ui.nav.fileScope === next) return;
|
|
183
|
+
if (next === 'file') return void ui.ops.hold(listScope(ui, quiet));
|
|
184
|
+
applyFileScope(ui, next, quiet);
|
|
179
185
|
};
|
|
180
186
|
|
|
181
187
|
const editCursor = (ui) => {
|
|
@@ -189,11 +195,9 @@ const editCursor = (ui) => {
|
|
|
189
195
|
const at = atBlock
|
|
190
196
|
? blockLineIndex(lines, item)
|
|
191
197
|
: viewLine(ui.nav, lines.length);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
rows: lines,
|
|
196
|
-
};
|
|
198
|
+
const cursor = fileOffset(lines, at);
|
|
199
|
+
const rows = lines;
|
|
200
|
+
return { text, cursor, rows };
|
|
197
201
|
};
|
|
198
202
|
|
|
199
203
|
module.exports = {
|
|
@@ -201,6 +205,7 @@ module.exports = {
|
|
|
201
205
|
linesFor,
|
|
202
206
|
moveUnitBlock,
|
|
203
207
|
openUnitFile,
|
|
208
|
+
showFile,
|
|
204
209
|
setFileScope,
|
|
205
210
|
editCursor,
|
|
206
211
|
followFileCursor,
|
package/lib/session/update.js
CHANGED
|
@@ -1,7 +1,184 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
const { isHashObject } = require('metautil');
|
|
8
|
+
const utilities = require('../common/utilities.js');
|
|
9
|
+
const {
|
|
10
|
+
INSTALL_MS,
|
|
11
|
+
npmBin,
|
|
12
|
+
npmOpts,
|
|
13
|
+
runProc,
|
|
14
|
+
} = require('../common/process.js');
|
|
15
|
+
const { readJson } = utilities;
|
|
16
|
+
const { parseVersion, cmpVersion } = utilities;
|
|
17
|
+
const { oneLine, asText } = utilities;
|
|
18
|
+
|
|
19
|
+
const PKG = require('../../package.json');
|
|
20
|
+
|
|
21
|
+
const PKG_NAME = PKG.name;
|
|
22
|
+
const PKG_VERSION = PKG.version;
|
|
23
|
+
const PKG_DIR = path.resolve(__dirname, '../..');
|
|
24
|
+
const CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
|
|
25
|
+
const FETCH_MS = 8000;
|
|
26
|
+
const REGISTRY = 'https://registry.npmjs.org';
|
|
27
|
+
|
|
28
|
+
const RELEASE = /^\d+\.\d+\.\d+$/;
|
|
29
|
+
const NO_TARGETS = { compatible: '', major: '' };
|
|
30
|
+
|
|
31
|
+
const isNpmInstall = (pkgDir) =>
|
|
32
|
+
path.basename(path.dirname(pkgDir)) === 'node_modules';
|
|
33
|
+
|
|
34
|
+
const cacheFile = (env = process.env) => {
|
|
35
|
+
if (env.XDG_CACHE_HOME) {
|
|
36
|
+
return path.join(env.XDG_CACHE_HOME, 'reslop', 'update.json');
|
|
37
|
+
}
|
|
38
|
+
if (process.platform === 'win32') {
|
|
39
|
+
const local =
|
|
40
|
+
env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
41
|
+
return path.join(local, 'reslop', 'update.json');
|
|
42
|
+
}
|
|
43
|
+
return path.join(os.homedir(), '.cache', 'reslop', 'update.json');
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const readCache = (file) => {
|
|
47
|
+
const data = readJson(file);
|
|
48
|
+
if (!isHashObject(data)) {
|
|
49
|
+
return { checkedAt: 0, compatible: '', major: '', skipped: '' };
|
|
50
|
+
}
|
|
51
|
+
const checkedAt = parseInt(data.checkedAt, 10) || 0;
|
|
52
|
+
const compatible = asText(data.compatible);
|
|
53
|
+
const latest = asText(data.latest);
|
|
54
|
+
const major = asText(data.major) || latest;
|
|
55
|
+
const handled = asText(data.handled);
|
|
56
|
+
const skipped = asText(data.skipped) || handled;
|
|
57
|
+
return { checkedAt, compatible, major, skipped };
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const writeCache = (file, data) => {
|
|
61
|
+
const { checkedAt, compatible, major, skipped } = data;
|
|
62
|
+
const body = JSON.stringify({ checkedAt, compatible, major, skipped });
|
|
63
|
+
try {
|
|
64
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
65
|
+
fs.writeFileSync(file, `${body}\n`);
|
|
66
|
+
} catch {
|
|
67
|
+
// ignore cache write errors
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const isFresh = (cache, now, interval = CHECK_INTERVAL_MS) => {
|
|
72
|
+
if (!cache.checkedAt || now < cache.checkedAt) return false;
|
|
73
|
+
return now - cache.checkedAt < interval;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const listVersions = (data) => {
|
|
77
|
+
if (!data || typeof data !== 'object') return [];
|
|
78
|
+
const names = [];
|
|
79
|
+
if (isHashObject(data.versions)) names.push(...Object.keys(data.versions));
|
|
80
|
+
const tags = data['dist-tags'];
|
|
81
|
+
if (tags && typeof tags.latest === 'string') names.push(tags.latest);
|
|
82
|
+
if (typeof data.version === 'string') names.push(data.version);
|
|
83
|
+
return [...new Set(names)].filter((name) => RELEASE.test(name));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const newer = (best, name) => {
|
|
87
|
+
if (!best) return name;
|
|
88
|
+
return cmpVersion(parseVersion(name), parseVersion(best)) > 0 ? name : best;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const pickTargets = (current, names) => {
|
|
92
|
+
const from = parseVersion(current);
|
|
93
|
+
if (!from) return NO_TARGETS;
|
|
94
|
+
let compatible = '';
|
|
95
|
+
let major = '';
|
|
96
|
+
for (const name of names) {
|
|
97
|
+
const ver = parseVersion(name);
|
|
98
|
+
if (cmpVersion(ver, from) <= 0) continue;
|
|
99
|
+
if (ver.major === from.major) compatible = newer(compatible, name);
|
|
100
|
+
else if (ver.major > from.major) major = newer(major, name);
|
|
101
|
+
}
|
|
102
|
+
return { compatible, major };
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const planUpdate = (current, targets) => {
|
|
106
|
+
const from = parseVersion(current);
|
|
107
|
+
if (!from) return { action: 'none' };
|
|
108
|
+
const { compatible, major, skipped } = targets;
|
|
109
|
+
const compatVer = parseVersion(compatible);
|
|
110
|
+
if (compatVer && compatVer.major === from.major) {
|
|
111
|
+
if (cmpVersion(compatVer, from) > 0) {
|
|
112
|
+
return { action: 'install', current, latest: compatible };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const majorVer = parseVersion(major);
|
|
116
|
+
if (!majorVer || majorVer.major <= from.major) return { action: 'none' };
|
|
117
|
+
const skipVer = parseVersion(skipped);
|
|
118
|
+
if (skipVer && cmpVersion(majorVer, skipVer) <= 0) return { action: 'none' };
|
|
119
|
+
return { action: 'confirm', current, latest: major };
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const isEnabled = (options) => {
|
|
123
|
+
if (typeof options.enabled === 'boolean') return options.enabled;
|
|
124
|
+
return isNpmInstall(options.pkgDir ?? PKG_DIR);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const fetchTargets = async (current, options) => {
|
|
128
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
129
|
+
if (typeof fetchImpl !== 'function') return NO_TARGETS;
|
|
130
|
+
const url = `${REGISTRY}/${encodeURIComponent(PKG_NAME)}`;
|
|
131
|
+
const headers = { accept: 'application/json' };
|
|
132
|
+
const signal = options.signal ?? AbortSignal.timeout(FETCH_MS);
|
|
133
|
+
const response = await fetchImpl(url, { headers, signal });
|
|
134
|
+
if (!response || !response.ok) return NO_TARGETS;
|
|
135
|
+
const data = await response.json();
|
|
136
|
+
return pickTargets(current, listVersions(data));
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const installUpdate = async (version, options = {}) => {
|
|
140
|
+
if (typeof options.install === 'function') {
|
|
141
|
+
await options.install(version);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const timeout = options.timeout ?? INSTALL_MS;
|
|
145
|
+
const args = ['install', '-g', `${PKG_NAME}@${version}`];
|
|
146
|
+
const result = await runProc(npmBin(), args, npmOpts({ timeout }));
|
|
147
|
+
if (result.error) throw result.error;
|
|
148
|
+
if (result.status !== 0) {
|
|
149
|
+
throw new Error(oneLine(result.stderr, 'npm install failed'));
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const markSkipped = (version, options = {}) => {
|
|
154
|
+
const file = options.cacheFile ?? cacheFile(options.env);
|
|
155
|
+
writeCache(file, { ...readCache(file), skipped: version });
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const checkUpdate = async (options = {}) => {
|
|
159
|
+
if (!isEnabled(options)) return { action: 'skip' };
|
|
160
|
+
const now = Date.now();
|
|
161
|
+
const current = options.current ?? PKG_VERSION;
|
|
162
|
+
const file = options.cacheFile ?? cacheFile(options.env);
|
|
163
|
+
const cache = readCache(file);
|
|
164
|
+
if (isFresh(cache, now, options.interval)) {
|
|
165
|
+
const plan = planUpdate(current, cache);
|
|
166
|
+
return plan.action === 'install' ? { action: 'none' } : plan;
|
|
167
|
+
}
|
|
168
|
+
let targets = NO_TARGETS;
|
|
169
|
+
try {
|
|
170
|
+
targets = await fetchTargets(current, options);
|
|
171
|
+
} catch {
|
|
172
|
+
// ignore registry errors
|
|
173
|
+
}
|
|
174
|
+
if (!targets.compatible && !targets.major) {
|
|
175
|
+
writeCache(file, { ...cache, checkedAt: now });
|
|
176
|
+
return { action: 'none' };
|
|
177
|
+
}
|
|
178
|
+
const next = { ...cache, checkedAt: now, ...targets };
|
|
179
|
+
writeCache(file, next);
|
|
180
|
+
return planUpdate(current, next);
|
|
181
|
+
};
|
|
5
182
|
|
|
6
183
|
class UpdateCoordinator {
|
|
7
184
|
constructor(ui) {
|
|
@@ -62,13 +239,13 @@ class UpdateCoordinator {
|
|
|
62
239
|
}
|
|
63
240
|
|
|
64
241
|
async check() {
|
|
65
|
-
let plan;
|
|
242
|
+
let plan = null;
|
|
66
243
|
try {
|
|
67
244
|
plan = await checkUpdate(this.opts);
|
|
68
245
|
} catch {
|
|
69
|
-
|
|
246
|
+
// update check failed
|
|
70
247
|
}
|
|
71
|
-
if (this.ui.done) return;
|
|
248
|
+
if (!plan || this.ui.done) return;
|
|
72
249
|
if (plan.action === 'install') {
|
|
73
250
|
this.installPromise = this.install(plan.latest);
|
|
74
251
|
await this.installPromise;
|
|
@@ -89,4 +266,15 @@ class UpdateCoordinator {
|
|
|
89
266
|
}
|
|
90
267
|
}
|
|
91
268
|
|
|
92
|
-
module.exports = {
|
|
269
|
+
module.exports = {
|
|
270
|
+
CHECK_INTERVAL_MS,
|
|
271
|
+
isNpmInstall,
|
|
272
|
+
cacheFile,
|
|
273
|
+
readCache,
|
|
274
|
+
writeCache,
|
|
275
|
+
isFresh,
|
|
276
|
+
planUpdate,
|
|
277
|
+
checkUpdate,
|
|
278
|
+
markSkipped,
|
|
279
|
+
UpdateCoordinator,
|
|
280
|
+
};
|
package/lib/session/view.js
CHANGED
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const {
|
|
8
|
-
const { fileEntries, fileTotals } = files;
|
|
9
|
-
const review = require('../review.js');
|
|
10
|
-
const { noteCounts } = review;
|
|
5
|
+
const { fileEntries, fileTotals } = require('../common/files.js');
|
|
6
|
+
const { listedCommits } = require('./commit.js');
|
|
7
|
+
const { noteCounts } = require('../review/review.js');
|
|
11
8
|
const diff = require('../diff/diff.js');
|
|
12
9
|
const { unitLines, itemsForPath, splitEditor, mergeEditRows } = diff;
|
|
13
10
|
const unit = require('./unit.js');
|
|
@@ -43,18 +40,6 @@ const blankEntry = (rel) => ({
|
|
|
43
40
|
status: '',
|
|
44
41
|
});
|
|
45
42
|
|
|
46
|
-
const listedNames = (ui) => {
|
|
47
|
-
const repo = ui.repo;
|
|
48
|
-
if (!repo.listFiles) return [];
|
|
49
|
-
try {
|
|
50
|
-
return repo.listFiles(ui.top || ui.cwd, ui.paths ?? [], {
|
|
51
|
-
commit: ui.rev,
|
|
52
|
-
});
|
|
53
|
-
} catch {
|
|
54
|
-
return [];
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
43
|
const mergeUnitFiles = (entries, names) => {
|
|
59
44
|
const have = new Set();
|
|
60
45
|
for (const entry of entries) have.add(entry.path);
|
|
@@ -74,9 +59,8 @@ const fileList = (ui) => {
|
|
|
74
59
|
const from = sourceLabel ? 'pr' : 'commit';
|
|
75
60
|
const to = sourceLabel || ui.revShort;
|
|
76
61
|
const labeled = relabelStatus(entries, from, to);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return labeled;
|
|
62
|
+
if (ui.nav.fileScope !== 'file') return labeled;
|
|
63
|
+
return mergeUnitFiles(labeled, ui.reads.names);
|
|
80
64
|
};
|
|
81
65
|
|
|
82
66
|
const counts = (ui, notes = noteCounts(ui.review.store)) => {
|
|
@@ -144,76 +128,92 @@ const commitRows = (ui) => {
|
|
|
144
128
|
return rows;
|
|
145
129
|
};
|
|
146
130
|
|
|
147
|
-
const
|
|
148
|
-
const {
|
|
149
|
-
const templates = composer.templates.shownTemplates();
|
|
150
|
-
const change = ui.change;
|
|
151
|
-
const sourceKind = (change && change.source) || '';
|
|
152
|
-
const notes = noteCounts(ui.review.store);
|
|
131
|
+
const navView = (ui) => {
|
|
132
|
+
const { nav } = ui;
|
|
153
133
|
return {
|
|
154
134
|
item: ui.current(),
|
|
155
135
|
index: nav.index,
|
|
156
136
|
total: ui.collection.items.length,
|
|
157
137
|
scroll: nav.scroll,
|
|
158
138
|
listScroll: nav.listScroll,
|
|
159
|
-
status: viewStatus(ui),
|
|
160
|
-
progressFrame: ui.progressFrame,
|
|
161
|
-
layout: ui.layout,
|
|
162
|
-
counts: counts(ui, notes),
|
|
163
139
|
selection: nav.selection,
|
|
164
140
|
pane: nav.pane,
|
|
165
141
|
fileScope: nav.fileScope,
|
|
166
|
-
files: fileList(ui),
|
|
167
142
|
fileCursor: nav.fileCursor,
|
|
168
143
|
find: nav.find,
|
|
144
|
+
import: nav.import,
|
|
169
145
|
reviewPath: nav.reviewPath,
|
|
170
146
|
unitLine: nav.unitLine,
|
|
147
|
+
branchCursor: nav.branchCursor,
|
|
148
|
+
commitCursor: nav.commitCursor,
|
|
149
|
+
packagesCursor: nav.packagesCursor,
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const dropNameOf = (ui) => {
|
|
154
|
+
const { packages, gitBranches, commits, npm } = ui;
|
|
155
|
+
const name = packages.dropName || gitBranches.dropName;
|
|
156
|
+
return name || commits.dropName || npm.dropName;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const repoView = (ui) => {
|
|
160
|
+
const { change, updater } = ui;
|
|
161
|
+
return {
|
|
162
|
+
status: viewStatus(ui),
|
|
163
|
+
progressFrame: ui.progressFrame,
|
|
164
|
+
layout: ui.layout,
|
|
165
|
+
lineNumbers: ui.lineNumbers === true,
|
|
166
|
+
counts: counts(ui, noteCounts(ui.review.store)),
|
|
167
|
+
files: fileList(ui),
|
|
171
168
|
unitLines: unitBodyLines(ui),
|
|
172
169
|
branch: ui.branch,
|
|
173
|
-
branches: gitBranches.branches,
|
|
174
|
-
branchCursor: nav.branchCursor,
|
|
170
|
+
branches: ui.gitBranches.branches,
|
|
175
171
|
commits: commitRows(ui),
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
npmCommands: npm.commands,
|
|
179
|
-
npmCursor: nav.npmCursor,
|
|
180
|
-
npmView: npm.viewing,
|
|
181
|
-
npmOutput: npm.output,
|
|
182
|
-
npmFollow: npm.followEnd,
|
|
183
|
-
npmScroll: npm.logScroll,
|
|
184
|
-
npmEditName: npm.editName,
|
|
185
|
-
npmEditField: npm.editField,
|
|
186
|
-
npmDraftName: npm.draftName,
|
|
187
|
-
npmDraftCommand: npm.draftCommand,
|
|
188
|
-
npmRunning: npm.running,
|
|
189
|
-
npmLogs: nav.pane === 'npm' ? npm.logLabel : '',
|
|
172
|
+
commitView: ui.commits.commitView,
|
|
173
|
+
quitWarning: ui.quitWarning || '',
|
|
190
174
|
repoName: repoNameOf(ui),
|
|
191
175
|
rev: ui.rev || '',
|
|
192
176
|
revShort: ui.revShort || '',
|
|
193
177
|
sourceLabel: ui.sourceLabel || '',
|
|
194
|
-
sourceKind,
|
|
178
|
+
sourceKind: (change && change.source) || '',
|
|
195
179
|
mode: ui.mode,
|
|
180
|
+
updateFrom: updater.from,
|
|
181
|
+
updateTo: updater.to,
|
|
182
|
+
dropName: dropNameOf(ui),
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const composeView = (composer) => {
|
|
187
|
+
const templates = composer.templates.shownTemplates();
|
|
188
|
+
return {
|
|
196
189
|
compose: composer.composeView(),
|
|
197
190
|
noteText: composer.idleNoteText(),
|
|
198
|
-
tasks: composer.tasks.taskTexts(),
|
|
199
|
-
taskSections: composer.tasks.taskSections(),
|
|
200
|
-
tasksFocus: composer.tasks.clampedTaskFocus(),
|
|
201
|
-
taskEdit: composer.tasks.taskEditView(),
|
|
202
191
|
codeOverlay: composer.codeOverlayView(),
|
|
203
192
|
templates,
|
|
204
193
|
templateIndex: composer.templates.clampedTemplateIndex(templates),
|
|
205
|
-
updateFrom: updater.from,
|
|
206
|
-
updateTo: updater.to,
|
|
207
|
-
dropName:
|
|
208
|
-
ui.packages.dropName ||
|
|
209
|
-
gitBranches.dropName ||
|
|
210
|
-
commits.dropName ||
|
|
211
|
-
npm.dropName,
|
|
212
|
-
dashboard: nav.pane === 'dashboard' ? ui.dashboard.view() : null,
|
|
213
|
-
packages: nav.pane === 'packages' ? ui.dashboard.packagesView() : null,
|
|
214
|
-
packagesCursor: nav.packagesCursor,
|
|
215
|
-
repos: nav.pane === 'repos' ? ui.workspace.view() : null,
|
|
216
194
|
};
|
|
217
195
|
};
|
|
218
196
|
|
|
219
|
-
|
|
197
|
+
const screenView = (ui) => {
|
|
198
|
+
const { pane } = ui.nav;
|
|
199
|
+
return {
|
|
200
|
+
dashboard: pane === 'dashboard' ? ui.dashboard.view() : null,
|
|
201
|
+
packages: pane === 'packages' ? ui.dashboard.packagesView() : null,
|
|
202
|
+
repos: pane === 'repos' ? ui.workspace.view() : null,
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const view = (ui) => {
|
|
207
|
+
const { pane } = ui.nav;
|
|
208
|
+
return {
|
|
209
|
+
...navView(ui),
|
|
210
|
+
...repoView(ui),
|
|
211
|
+
...ui.npm.view(pane === 'npm'),
|
|
212
|
+
...ui.agents.view(pane === 'agents'),
|
|
213
|
+
...composeView(ui.composer),
|
|
214
|
+
...ui.composer.tasks.view(pane === 'tasks'),
|
|
215
|
+
...screenView(ui),
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
module.exports = { fileList, counts, unitBodyLines, view };
|