reslop 0.1.8 → 0.2.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 +25 -1
- package/README.md +27 -38
- package/bin/reslop.js +2 -2
- package/lib/ansi.js +6 -2
- package/lib/api.js +2 -2
- package/lib/capabilities.js +10 -14
- package/lib/cli.js +28 -47
- package/lib/clipboard.js +1 -1
- package/lib/deps-diff.js +712 -0
- package/lib/deps.js +556 -32
- package/lib/detect.js +1 -7
- package/lib/diff/align.js +7 -10
- package/lib/diff/diff.js +53 -0
- package/lib/diff/display.js +5 -4
- package/lib/diff/inline.js +26 -21
- package/lib/diff/items.js +6 -4
- package/lib/diff/patch.js +1 -3
- package/lib/diff/unit.js +392 -0
- package/lib/files.js +34 -8
- package/lib/{git/branches.js → git-branches.js} +103 -10
- package/lib/{git/dependencies.js → git-deps.js} +111 -38
- package/lib/git.js +592 -65
- package/lib/github.js +28 -197
- package/lib/gitlab.js +24 -195
- package/lib/highlight/bash.js +1 -3
- package/lib/highlight/css.js +1 -3
- package/lib/highlight/js.js +11 -14
- package/lib/highlight.js +6 -9
- package/lib/keys.js +22 -9
- package/lib/manifest.js +330 -0
- package/lib/remote.js +374 -0
- package/lib/render/branches.js +34 -66
- package/lib/render/chrome.js +57 -22
- package/lib/render/commits.js +85 -0
- package/lib/render/diff.js +16 -16
- package/lib/render/files.js +29 -37
- package/lib/render/frame.js +29 -13
- package/lib/render/notes.js +4 -3
- package/lib/render/primitives.js +46 -1
- package/lib/{render.js → render/render.js} +6 -7
- package/lib/render/unit.js +41 -0
- package/lib/review.js +750 -14
- package/lib/select.js +5 -10
- package/lib/session/accessors.js +9 -1
- package/lib/session/actions.js +93 -36
- package/lib/session/branches.js +130 -144
- package/lib/session/change-actions.js +206 -124
- package/lib/session/commit.js +217 -62
- package/lib/session/compose.js +158 -13
- package/lib/session/dispatch.js +109 -55
- package/lib/session/files-pane.js +145 -142
- package/lib/session/items.js +131 -34
- package/lib/session/lifecycle.js +82 -42
- package/lib/session/load.js +19 -33
- package/lib/session/navigation.js +15 -3
- package/lib/session/ops.js +28 -41
- package/lib/session/pointer.js +58 -54
- package/lib/session/review.js +23 -37
- package/lib/session/terminal.js +6 -12
- package/lib/session/todos.js +8 -12
- package/lib/session/unit.js +208 -0
- package/lib/session/update.js +33 -46
- package/lib/session/view.js +82 -11
- package/lib/session/watch.js +11 -19
- package/lib/session.js +29 -226
- package/lib/source.js +3 -3
- package/lib/update.js +40 -75
- package/lib/{git/proc.js → utilities.js} +75 -11
- package/lib/wrap.js +1 -3
- package/package.json +2 -2
- package/lib/deps/changes.js +0 -331
- package/lib/deps/items.js +0 -131
- package/lib/deps/manifest.js +0 -145
- package/lib/deps/merge.js +0 -120
- package/lib/deps/proposals.js +0 -164
- package/lib/deps/reports.js +0 -180
- package/lib/deps/rows.js +0 -177
- package/lib/deps/scan.js +0 -138
- package/lib/deps/usage.js +0 -68
- package/lib/deps/versions.js +0 -119
- package/lib/diff.js +0 -33
- package/lib/git/changes.js +0 -164
- package/lib/git/read.js +0 -253
- package/lib/git/run.js +0 -100
- package/lib/npm/commands.js +0 -100
- package/lib/remote/changes.js +0 -37
- package/lib/remote/headers.js +0 -36
- package/lib/remote/http.js +0 -122
- package/lib/remote/notes.js +0 -94
- package/lib/review/format.js +0 -434
- package/lib/review/storage.js +0 -150
- package/lib/review/store.js +0 -178
- package/lib/review/templates.js +0 -49
- package/lib/session/origins.js +0 -7
- package/lib/sys.js +0 -84
package/lib/files.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { listFilePath } = require('./manifest.js');
|
|
4
|
+
|
|
3
5
|
const REVIEW_DIR = '.review';
|
|
4
6
|
const ORIGIN_ORDER = ['staged', 'unstaged', 'untracked', 'commit', 'pr'];
|
|
5
7
|
const TODO_FILE = 'TODOs';
|
|
6
8
|
const REPO_TODOS_LABEL = 'Repository TODOs and Issues';
|
|
7
9
|
const TOTAL_LABEL = 'total';
|
|
8
10
|
|
|
9
|
-
const normalizePathSpec = (spec) =>
|
|
10
|
-
`${spec ?? ''}`.replaceAll('\\', '/').replace(/\/+$/, '');
|
|
11
|
-
|
|
12
11
|
const isPathInScope = (rel, paths) => {
|
|
13
12
|
if (!paths.length) return true;
|
|
14
13
|
for (const spec of paths) {
|
|
15
|
-
const norm =
|
|
14
|
+
const norm = `${spec ?? ''}`.replaceAll('\\', '/').replace(/\/+$/, '');
|
|
16
15
|
if (!norm || norm === '.') return true;
|
|
17
16
|
if (rel === norm || rel.startsWith(`${norm}/`)) return true;
|
|
18
17
|
}
|
|
@@ -24,14 +23,16 @@ const itemPath = (item) => {
|
|
|
24
23
|
return item.file.newPath || item.file.oldPath || '';
|
|
25
24
|
};
|
|
26
25
|
|
|
26
|
+
const listPath = (item) => listFilePath(itemPath(item));
|
|
27
|
+
|
|
27
28
|
const isTodoItem = (item) => !!(item && item.origin === 'todo');
|
|
28
29
|
|
|
30
|
+
const isReadOnlyOrigin = (origin) => origin === 'commit' || origin === 'pr';
|
|
31
|
+
|
|
29
32
|
const isTodosEntry = (entry) => !!(entry && entry.kind === 'todos');
|
|
30
33
|
|
|
31
34
|
const isTotalEntry = (entry) => !!(entry && entry.kind === 'total');
|
|
32
35
|
|
|
33
|
-
const repoTodosLabel = () => REPO_TODOS_LABEL;
|
|
34
|
-
|
|
35
36
|
const makeTodoItem = () => ({
|
|
36
37
|
origin: 'todo',
|
|
37
38
|
file: {
|
|
@@ -72,6 +73,25 @@ const lineDelta = ({ hunk, blockId }) => {
|
|
|
72
73
|
return delta;
|
|
73
74
|
};
|
|
74
75
|
|
|
76
|
+
const countAgo = (n, unit) => {
|
|
77
|
+
const label = n === 1 ? unit : `${unit}s`;
|
|
78
|
+
return `${n} ${label} ago`;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const relativeAge = (thenMs, nowMs = Date.now()) => {
|
|
82
|
+
const diff = Math.max(0, Math.round((nowMs - thenMs) / 1000));
|
|
83
|
+
if (diff < 90) return countAgo(diff, 'second');
|
|
84
|
+
const minutes = Math.round(diff / 60);
|
|
85
|
+
if (minutes < 90) return countAgo(minutes, 'minute');
|
|
86
|
+
const hours = Math.round(minutes / 60);
|
|
87
|
+
if (hours < 36) return countAgo(hours, 'hour');
|
|
88
|
+
const days = Math.round(hours / 24);
|
|
89
|
+
if (days < 14) return countAgo(days, 'day');
|
|
90
|
+
if (days < 70) return countAgo(Math.round(days / 7), 'week');
|
|
91
|
+
if (days < 365) return countAgo(Math.round(days / 30), 'month');
|
|
92
|
+
return countAgo(Math.round(days / 365), 'year');
|
|
93
|
+
};
|
|
94
|
+
|
|
75
95
|
const addLineDelta = (group, origin, delta) => {
|
|
76
96
|
group.added += delta.added;
|
|
77
97
|
group.removed += delta.removed;
|
|
@@ -116,7 +136,8 @@ const fileEntries = (items) => {
|
|
|
116
136
|
for (let i = 0; i < items.length; i++) {
|
|
117
137
|
const item = items[i];
|
|
118
138
|
if (isTodoItem(item)) continue;
|
|
119
|
-
const rel =
|
|
139
|
+
const rel = listPath(item);
|
|
140
|
+
if (!rel) continue;
|
|
120
141
|
if (!groups.has(rel)) {
|
|
121
142
|
groups.set(rel, {
|
|
122
143
|
path: rel,
|
|
@@ -132,10 +153,12 @@ const fileEntries = (items) => {
|
|
|
132
153
|
unstagedRemoved: 0,
|
|
133
154
|
staged: 0,
|
|
134
155
|
unstaged: 0,
|
|
156
|
+
date: '',
|
|
135
157
|
});
|
|
136
158
|
}
|
|
137
159
|
const group = groups.get(rel);
|
|
138
160
|
const { origin } = item;
|
|
161
|
+
if (item.date && !group.date) group.date = item.date;
|
|
139
162
|
group.origins.push(origin);
|
|
140
163
|
group.remaining += 1;
|
|
141
164
|
addLineDelta(group, origin, lineDelta(item));
|
|
@@ -149,6 +172,7 @@ const fileEntries = (items) => {
|
|
|
149
172
|
for (const group of entries) {
|
|
150
173
|
group.status = fileStatus(group.origins);
|
|
151
174
|
}
|
|
175
|
+
entries.sort((left, right) => left.path.localeCompare(right.path, 'en'));
|
|
152
176
|
return entries;
|
|
153
177
|
};
|
|
154
178
|
|
|
@@ -197,12 +221,14 @@ module.exports = {
|
|
|
197
221
|
TOTAL_LABEL,
|
|
198
222
|
isPathInScope,
|
|
199
223
|
itemPath,
|
|
224
|
+
listPath,
|
|
200
225
|
isTodoItem,
|
|
226
|
+
isReadOnlyOrigin,
|
|
201
227
|
isTodosEntry,
|
|
202
228
|
isTotalEntry,
|
|
203
|
-
repoTodosLabel,
|
|
204
229
|
makeTodoItem,
|
|
205
230
|
fileStatus,
|
|
206
231
|
fileEntries,
|
|
207
232
|
fileTotals,
|
|
233
|
+
relativeAge,
|
|
208
234
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { oneLine, requireOk, runGit, runGitAsync } = require('./
|
|
3
|
+
const { oneLine, requireOk, runGit, runGitAsync } = require('./git.js');
|
|
4
4
|
|
|
5
5
|
const BRANCH_FORMAT = [
|
|
6
6
|
'%(HEAD)',
|
|
@@ -26,6 +26,100 @@ const lastMessage = (top) => {
|
|
|
26
26
|
return (result.stdout ?? '').replace(/\s+$/, '');
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
const COMMIT_FORMAT = ['%H', '%h', '%an', '%ar', '%s'].join('%x1f');
|
|
30
|
+
const COMMIT_LIMIT = 256;
|
|
31
|
+
const UNIT = '\x1f';
|
|
32
|
+
|
|
33
|
+
const parseCommitLine = (line, index) => {
|
|
34
|
+
const parts = line.split(UNIT);
|
|
35
|
+
if (parts.length < 5) return null;
|
|
36
|
+
const sha = (parts[0] ?? '').trim();
|
|
37
|
+
if (!sha) return null;
|
|
38
|
+
return {
|
|
39
|
+
sha,
|
|
40
|
+
shortSha: (parts[1] ?? '').trim() || sha.slice(0, 7),
|
|
41
|
+
author: (parts[2] ?? '').trim(),
|
|
42
|
+
date: (parts[3] ?? '').trim(),
|
|
43
|
+
subject: parts.slice(4).join(UNIT).trim(),
|
|
44
|
+
head: index === 0,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const listCommits = (top) => {
|
|
49
|
+
const args = [
|
|
50
|
+
'log',
|
|
51
|
+
`--format=${COMMIT_FORMAT}`,
|
|
52
|
+
`--max-count=${COMMIT_LIMIT}`,
|
|
53
|
+
];
|
|
54
|
+
const result = requireOk(runGit(args, top), 'log failed');
|
|
55
|
+
const commits = [];
|
|
56
|
+
for (const line of result.stdout.split('\n')) {
|
|
57
|
+
if (!line) continue;
|
|
58
|
+
const entry = parseCommitLine(line, commits.length);
|
|
59
|
+
if (entry) commits.push(entry);
|
|
60
|
+
}
|
|
61
|
+
return commits;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const namedCommit = (sha) => {
|
|
65
|
+
const commit = `${sha ?? ''}`.trim();
|
|
66
|
+
if (!commit) throw new Error('empty commit');
|
|
67
|
+
return commit;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const resolveCommit = (top, sha) => {
|
|
71
|
+
const result = requireOk(runGit(['rev-parse', sha], top), 'rev-parse failed');
|
|
72
|
+
return (result.stdout ?? '').trim();
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const dropHeadCommit = (top) => {
|
|
76
|
+
requireOk(runGit(['reset', '--soft', 'HEAD~1'], top), 'drop failed');
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const rebaseFailed = (result) => {
|
|
80
|
+
if (result.status === 0) return '';
|
|
81
|
+
return result.stderr || result.stdout || 'rebase failed';
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const dropOlderCommit = (top, sha) => {
|
|
85
|
+
const onto = `${sha}^`;
|
|
86
|
+
const result = runGit(['rebase', '--onto', onto, sha], top);
|
|
87
|
+
const failed = rebaseFailed(result);
|
|
88
|
+
if (!failed) return;
|
|
89
|
+
runGit(['rebase', '--abort'], top);
|
|
90
|
+
throw new Error(oneLine(failed));
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const dropOlderCommitAsync = async (top, sha) => {
|
|
94
|
+
const onto = `${sha}^`;
|
|
95
|
+
const result = await runGitAsync(['rebase', '--onto', onto, sha], top);
|
|
96
|
+
const failed = rebaseFailed(result);
|
|
97
|
+
if (!failed) return;
|
|
98
|
+
await runGitAsync(['rebase', '--abort'], top);
|
|
99
|
+
throw new Error(oneLine(failed));
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const dropCommit = (top, sha) => {
|
|
103
|
+
const spec = namedCommit(sha);
|
|
104
|
+
const target = resolveCommit(top, spec);
|
|
105
|
+
const parent = runGit(['rev-parse', '--verify', `${target}^`], top);
|
|
106
|
+
if (parent.status !== 0) throw new Error('cannot drop root commit');
|
|
107
|
+
const head = resolveCommit(top, 'HEAD');
|
|
108
|
+
if (target === head) return void dropHeadCommit(top);
|
|
109
|
+
dropOlderCommit(top, target);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const dropCommitAsync = async (top, sha) => {
|
|
113
|
+
const spec = namedCommit(sha);
|
|
114
|
+
const target = resolveCommit(top, spec);
|
|
115
|
+
const parentArgs = ['rev-parse', '--verify', `${target}^`];
|
|
116
|
+
const parent = await runGitAsync(parentArgs, top);
|
|
117
|
+
if (parent.status !== 0) throw new Error('cannot drop root commit');
|
|
118
|
+
const head = resolveCommit(top, 'HEAD');
|
|
119
|
+
if (target === head) return void dropHeadCommit(top);
|
|
120
|
+
await dropOlderCommitAsync(top, target);
|
|
121
|
+
};
|
|
122
|
+
|
|
29
123
|
const parseTrack = (text) => {
|
|
30
124
|
const raw = `${text ?? ''}`.trim().replace(/^\[|\]$/g, '');
|
|
31
125
|
if (!raw) return { ahead: 0, behind: 0, gone: false };
|
|
@@ -89,10 +183,11 @@ const listBranches = (top) => {
|
|
|
89
183
|
const names = new Set();
|
|
90
184
|
for (const entry of branches) names.add(entry.name);
|
|
91
185
|
const primary = defaultBranch(top, names);
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
186
|
+
const { length } = branches;
|
|
187
|
+
const listed = new Array(length);
|
|
188
|
+
for (let i = 0; i < length; i++) {
|
|
189
|
+
const entry = branches[i];
|
|
190
|
+
listed[i] = { ...entry, isDefault: entry.name === primary };
|
|
96
191
|
}
|
|
97
192
|
return listed;
|
|
98
193
|
};
|
|
@@ -125,11 +220,6 @@ const createBranchAsync = async (top, name) => {
|
|
|
125
220
|
requireOk(await runGitAsync(args, top), 'checkout failed');
|
|
126
221
|
};
|
|
127
222
|
|
|
128
|
-
const rebaseFailed = (result) => {
|
|
129
|
-
if (result.status === 0) return '';
|
|
130
|
-
return result.stderr || result.stdout || 'rebase failed';
|
|
131
|
-
};
|
|
132
|
-
|
|
133
223
|
const rebaseBranch = (top, onto) => {
|
|
134
224
|
const branch = namedBranch(onto);
|
|
135
225
|
const result = runGit(['rebase', branch], top);
|
|
@@ -272,6 +362,7 @@ const commitChangesAsync = async (top, kind, message) => {
|
|
|
272
362
|
|
|
273
363
|
module.exports = {
|
|
274
364
|
lastMessage,
|
|
365
|
+
listCommits,
|
|
275
366
|
listBranches,
|
|
276
367
|
checkoutBranch,
|
|
277
368
|
checkoutBranchAsync,
|
|
@@ -279,6 +370,8 @@ module.exports = {
|
|
|
279
370
|
createBranchAsync,
|
|
280
371
|
rebaseBranch,
|
|
281
372
|
rebaseBranchAsync,
|
|
373
|
+
dropCommit,
|
|
374
|
+
dropCommitAsync,
|
|
282
375
|
dropBranch,
|
|
283
376
|
dropBranchAsync,
|
|
284
377
|
pullChanges,
|
|
@@ -3,21 +3,55 @@
|
|
|
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.js');
|
|
7
7
|
const { foldDepItems, mergeDepFile, depFileMeta } = deps;
|
|
8
8
|
const { parseAuditReport, parseOutdatedReport } = deps;
|
|
9
9
|
const { mergeProposedItems, MANIFEST, LOCKFILE } = deps;
|
|
10
|
-
const
|
|
11
|
-
const {
|
|
12
|
-
const
|
|
13
|
-
const { abortError } =
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const { gitText, worktreeText, readDepSides } =
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
10
|
+
const { collectUsedNames, collectExportMeta } = deps;
|
|
11
|
+
const { itemPath, isPathInScope } = require('./files.js');
|
|
12
|
+
const proc = require('./utilities.js');
|
|
13
|
+
const { abortError, npmBin, npmOpts, runProc, runProcSync } = proc;
|
|
14
|
+
const git = require('./git.js');
|
|
15
|
+
const { oneLine, requireOk, runGit } = git;
|
|
16
|
+
const { gitText, worktreeText, readDepSides, revertOnePath } = git;
|
|
17
|
+
|
|
18
|
+
const AUDIT_MS = 15000;
|
|
19
|
+
const INSTALL_MS = 120000;
|
|
20
|
+
|
|
21
|
+
const npmProcOptions = (cwd, extra = {}) => ({
|
|
22
|
+
cwd,
|
|
23
|
+
encoding: proc.DEFAULT_ENCODING,
|
|
24
|
+
maxBuffer: proc.DEFAULT_MAX_BUFFER,
|
|
25
|
+
timeout: extra.timeout,
|
|
26
|
+
signal: extra.signal,
|
|
27
|
+
shell: npmOpts().shell,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const runNpm = (cwd, args) =>
|
|
31
|
+
runProcSync(npmBin(), args, npmProcOptions(cwd, { timeout: INSTALL_MS }));
|
|
32
|
+
|
|
33
|
+
const runNpmAsync = (cwd, args, extra = {}) =>
|
|
34
|
+
runProc(
|
|
35
|
+
npmBin(),
|
|
36
|
+
args,
|
|
37
|
+
npmProcOptions(cwd, { timeout: INSTALL_MS, signal: extra.signal }),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const runNpmJson = (top, args, timeout) => {
|
|
41
|
+
const result = runProcSync(npmBin(), args, npmProcOptions(top, { timeout }));
|
|
42
|
+
if (result.error) return '';
|
|
43
|
+
return result.stdout || '';
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const runNpmJsonAsync = async (top, args, timeout, signal) => {
|
|
47
|
+
const result = await runProc(
|
|
48
|
+
npmBin(),
|
|
49
|
+
args,
|
|
50
|
+
npmProcOptions(top, { timeout, signal }),
|
|
51
|
+
);
|
|
52
|
+
if (result.error) return '';
|
|
53
|
+
return result.stdout || '';
|
|
54
|
+
};
|
|
21
55
|
|
|
22
56
|
const depPaths = (item) => item.dep?.files ?? [];
|
|
23
57
|
|
|
@@ -25,15 +59,59 @@ const origDepItems = (item) => item.dep?.items ?? [];
|
|
|
25
59
|
|
|
26
60
|
const depChange = (item) => item.dep?.change ?? null;
|
|
27
61
|
|
|
62
|
+
const firstDepRel = (files, kind) => {
|
|
63
|
+
for (const rel of files) {
|
|
64
|
+
const meta = depFileMeta(rel);
|
|
65
|
+
if (meta && meta.kind === kind) return rel;
|
|
66
|
+
}
|
|
67
|
+
return '';
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const proposedNpmPlan = (top, item) => {
|
|
71
|
+
const change = depChange(item);
|
|
72
|
+
if (!change) return null;
|
|
73
|
+
const files = depPaths(item);
|
|
74
|
+
const lockOnly = change.section === 'resolved';
|
|
75
|
+
const removing = !!change.unused;
|
|
76
|
+
const manifest = firstDepRel(files, 'manifest');
|
|
77
|
+
const lockRel = firstDepRel(files, 'lockfile');
|
|
78
|
+
const picked = lockOnly ? lockRel : manifest;
|
|
79
|
+
const target = picked || files[0] || '';
|
|
80
|
+
const meta = depFileMeta(target);
|
|
81
|
+
if (!meta) return null;
|
|
82
|
+
const cwd = meta.dir === '.' ? top : path.join(top, meta.dir);
|
|
83
|
+
let npmArgs = ['i'];
|
|
84
|
+
if (removing) npmArgs = ['uninstall', change.name];
|
|
85
|
+
else if (lockOnly) npmArgs = ['audit', 'fix'];
|
|
86
|
+
const fail = removing ? 'npm uninstall failed' : 'npm i failed';
|
|
87
|
+
const dirLock = meta.dir === '.' ? LOCKFILE : `${meta.dir}/${LOCKFILE}`;
|
|
88
|
+
const lockPath = lockRel || dirLock;
|
|
89
|
+
const prepareManifest = !lockOnly && !removing && !!manifest;
|
|
90
|
+
return {
|
|
91
|
+
cwd,
|
|
92
|
+
npmArgs,
|
|
93
|
+
fail,
|
|
94
|
+
lockOnly,
|
|
95
|
+
lockPath,
|
|
96
|
+
manifest,
|
|
97
|
+
prepareManifest,
|
|
98
|
+
runner: item.dep.install,
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
28
102
|
const hasProposed = (item) => {
|
|
29
103
|
const change = depChange(item);
|
|
30
104
|
return !!(change && change.propose);
|
|
31
105
|
};
|
|
32
106
|
|
|
33
107
|
const relatedFiles = (items) => {
|
|
34
|
-
|
|
108
|
+
let size = 0;
|
|
109
|
+
for (const item of items) size += depPaths(item).length;
|
|
110
|
+
const files = new Array(size);
|
|
111
|
+
let i = 0;
|
|
35
112
|
for (const item of items) {
|
|
36
|
-
|
|
113
|
+
const paths = depPaths(item);
|
|
114
|
+
for (let j = 0; j < paths.length; j++) files[i++] = paths[j];
|
|
37
115
|
}
|
|
38
116
|
return files;
|
|
39
117
|
};
|
|
@@ -230,10 +308,7 @@ const captureFile = (top, rel) => {
|
|
|
230
308
|
|
|
231
309
|
const restoreFile = (top, saved) => {
|
|
232
310
|
const abs = path.join(top, saved.rel);
|
|
233
|
-
if (saved.existed)
|
|
234
|
-
fs.writeFileSync(abs, saved.text);
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
311
|
+
if (saved.existed) return void fs.writeFileSync(abs, saved.text);
|
|
237
312
|
try {
|
|
238
313
|
fs.unlinkSync(abs);
|
|
239
314
|
} catch {
|
|
@@ -242,8 +317,9 @@ const restoreFile = (top, saved) => {
|
|
|
242
317
|
};
|
|
243
318
|
|
|
244
319
|
const captureFiles = (top, rels) => {
|
|
245
|
-
const
|
|
246
|
-
|
|
320
|
+
const { length } = rels;
|
|
321
|
+
const owned = new Array(length);
|
|
322
|
+
for (let i = 0; i < length; i++) owned[i] = captureFile(top, rels[i]);
|
|
247
323
|
return owned;
|
|
248
324
|
};
|
|
249
325
|
|
|
@@ -299,9 +375,6 @@ const ownedRelsOf = (plan) => {
|
|
|
299
375
|
return rels;
|
|
300
376
|
};
|
|
301
377
|
|
|
302
|
-
const resultFailed = (result) =>
|
|
303
|
-
!!(result && (result.error || result.status !== 0));
|
|
304
|
-
|
|
305
378
|
const errorFromResult = (result, fail) => {
|
|
306
379
|
if (!result) return new Error(fail);
|
|
307
380
|
if (result.error) {
|
|
@@ -338,7 +411,9 @@ const stagePlan = (top, plan) => {
|
|
|
338
411
|
};
|
|
339
412
|
|
|
340
413
|
const finishPlan = (top, plan, result, stage) => {
|
|
341
|
-
if (
|
|
414
|
+
if (result && (result.error || result.status !== 0)) {
|
|
415
|
+
throw errorFromResult(result, plan.fail);
|
|
416
|
+
}
|
|
342
417
|
const stageFn = stage ?? stagePlan;
|
|
343
418
|
stageFn(top, plan);
|
|
344
419
|
};
|
|
@@ -409,10 +484,7 @@ const applyDepChange = (top, item, mode) => {
|
|
|
409
484
|
|
|
410
485
|
const addItem = (top, item) => {
|
|
411
486
|
if (item.origin === 'staged' || item.origin === 'commit') return;
|
|
412
|
-
if (depChange(item))
|
|
413
|
-
applyDepChange(top, item, 'add');
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
487
|
+
if (depChange(item)) return void applyDepChange(top, item, 'add');
|
|
416
488
|
const files = depPaths(item);
|
|
417
489
|
if (files.length) {
|
|
418
490
|
requireOk(runGit(['add', '--', ...files], top));
|
|
@@ -430,10 +502,7 @@ const addItemAsync = async (top, item) => {
|
|
|
430
502
|
|
|
431
503
|
const unstageItem = (top, item) => {
|
|
432
504
|
if (item.origin !== 'staged') return;
|
|
433
|
-
if (depChange(item))
|
|
434
|
-
applyDepChange(top, item, 'unstage');
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
505
|
+
if (depChange(item)) return void applyDepChange(top, item, 'unstage');
|
|
437
506
|
const files = depPaths(item);
|
|
438
507
|
if (files.length) {
|
|
439
508
|
requireOk(runGit(['restore', '--staged', '--', ...files], top));
|
|
@@ -441,10 +510,7 @@ const unstageItem = (top, item) => {
|
|
|
441
510
|
};
|
|
442
511
|
|
|
443
512
|
const revertDepItem = (top, item) => {
|
|
444
|
-
if (depChange(item))
|
|
445
|
-
applyDepChange(top, item, 'revert');
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
513
|
+
if (depChange(item)) return void applyDepChange(top, item, 'revert');
|
|
448
514
|
const byPath = new Map();
|
|
449
515
|
for (const orig of origDepItems(item)) {
|
|
450
516
|
const rel = itemPath(orig);
|
|
@@ -453,7 +519,7 @@ const revertDepItem = (top, item) => {
|
|
|
453
519
|
else byPath.set(rel, [orig]);
|
|
454
520
|
}
|
|
455
521
|
for (const rel of byPath.keys()) {
|
|
456
|
-
|
|
522
|
+
revertOnePath(top, rel, byPath.get(rel));
|
|
457
523
|
}
|
|
458
524
|
};
|
|
459
525
|
|
|
@@ -463,7 +529,7 @@ const revertFile = (top, rel, items) => {
|
|
|
463
529
|
for (const file of paths) {
|
|
464
530
|
const group = itemsForPath(file, items);
|
|
465
531
|
const targets = group.length ? group : items;
|
|
466
|
-
|
|
532
|
+
revertOnePath(top, file, targets);
|
|
467
533
|
}
|
|
468
534
|
};
|
|
469
535
|
|
|
@@ -486,4 +552,11 @@ module.exports = {
|
|
|
486
552
|
unstageItem,
|
|
487
553
|
revertDepItem,
|
|
488
554
|
revertFile,
|
|
555
|
+
AUDIT_MS,
|
|
556
|
+
INSTALL_MS,
|
|
557
|
+
runNpm,
|
|
558
|
+
runNpmAsync,
|
|
559
|
+
runNpmJson,
|
|
560
|
+
runNpmJsonAsync,
|
|
561
|
+
proposedNpmPlan,
|
|
489
562
|
};
|