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/session.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const render = require('./render.js');
|
|
3
|
+
const render = require('./render/render.js');
|
|
4
4
|
const keys = require('./keys.js');
|
|
5
5
|
const review = require('./review.js');
|
|
6
|
-
const { copyText } = require('./clipboard.js');
|
|
7
6
|
const files = require('./files.js');
|
|
8
7
|
const { makeTodoItem } = files;
|
|
9
8
|
const { renderFrame } = render;
|
|
10
9
|
const { decodeChunk } = keys;
|
|
11
10
|
const { AUTOSAVE_MS, hasNotes } = review;
|
|
12
11
|
const capabilities = require('./capabilities.js');
|
|
13
|
-
const { sessionCapabilities
|
|
12
|
+
const { sessionCapabilities } = capabilities;
|
|
14
13
|
const { createTerminal, LEAVE_TERM } = require('./session/terminal.js');
|
|
15
14
|
const { createLoadCoordinator } = require('./session/load.js');
|
|
16
15
|
const items = require('./session/items.js');
|
|
@@ -35,16 +34,17 @@ const { createDispatcher, createInput } = require('./session/dispatch.js');
|
|
|
35
34
|
const CURSOR_BLINK_MS = 500;
|
|
36
35
|
const PROGRESS_MS = 80;
|
|
37
36
|
|
|
38
|
-
const systemNow = () => new Date();
|
|
39
|
-
|
|
40
37
|
const NAV_FIELDS = [
|
|
41
38
|
'pane',
|
|
42
39
|
'index',
|
|
43
40
|
'fileCursor',
|
|
44
41
|
'branchCursor',
|
|
42
|
+
'commitCursor',
|
|
45
43
|
'scroll',
|
|
46
44
|
'listScroll',
|
|
47
45
|
'reviewPath',
|
|
46
|
+
'fileScope',
|
|
47
|
+
'unitLine',
|
|
48
48
|
'selection',
|
|
49
49
|
'mouseAnchor',
|
|
50
50
|
'pendingClick',
|
|
@@ -71,51 +71,34 @@ const assignOptions = (session, options) => {
|
|
|
71
71
|
session.stdout = options.stdout;
|
|
72
72
|
session.proc = options.proc ?? process;
|
|
73
73
|
session.color = options.color ?? true;
|
|
74
|
-
session.
|
|
75
|
-
const termSize = () => {
|
|
74
|
+
session.getSize = () => {
|
|
76
75
|
const width = session.stdout.columns ?? 80;
|
|
77
76
|
const height = session.stdout.rows ?? 24;
|
|
78
77
|
return { width, height };
|
|
79
78
|
};
|
|
80
|
-
session.getSize = options.getSize ?? termSize;
|
|
81
79
|
session.rev = options.rev ?? null;
|
|
82
80
|
session.revShort = '';
|
|
83
81
|
session.sourceLabel = options.sourceLabel ?? '';
|
|
84
82
|
session.repoName = options.repoName ?? '';
|
|
85
83
|
session.change = options.change ?? null;
|
|
86
|
-
session.now = options.now ?? systemNow;
|
|
87
84
|
session.forceNewReview = options.newReview === true;
|
|
88
85
|
session.readOnly = options.readOnly === true;
|
|
89
86
|
session.capabilities = sessionCapabilities(options);
|
|
90
|
-
const storage = options.reviewStorage ?? createReviewStorage(options);
|
|
91
87
|
session.audit = options.audit === true;
|
|
92
88
|
session.outdatedMap = options.outdatedMap;
|
|
93
89
|
session.auditMap = options.auditMap;
|
|
94
|
-
session.setInterval = options.setInterval ?? setInterval;
|
|
95
|
-
session.clearInterval = options.clearInterval ?? clearInterval;
|
|
96
|
-
session.watchOpts = {
|
|
97
|
-
watch: options.watch,
|
|
98
|
-
readdirSync: options.watchReaddir,
|
|
99
|
-
statSync: options.watchStat,
|
|
100
|
-
setTimeout: options.setTimeout ?? setTimeout,
|
|
101
|
-
clearTimeout: options.clearTimeout ?? clearTimeout,
|
|
102
|
-
debounceMs: options.watchDebounceMs,
|
|
103
|
-
recursive: options.watchRecursive,
|
|
104
|
-
};
|
|
105
90
|
session.updateOpts = options.update;
|
|
106
91
|
session.term = createTerminal({
|
|
107
92
|
stdin: session.stdin,
|
|
108
93
|
stdout: session.stdout,
|
|
109
94
|
proc: session.proc,
|
|
110
|
-
setInterval: session.setInterval,
|
|
111
|
-
clearInterval: session.clearInterval,
|
|
112
95
|
});
|
|
113
96
|
session.loader = createLoadCoordinator();
|
|
114
97
|
session.collection = createItemCollection();
|
|
115
98
|
session.nav = createNavigation({
|
|
116
99
|
startPane: options.startPane ?? 'files',
|
|
117
100
|
});
|
|
118
|
-
session.review = createReviewController(
|
|
101
|
+
session.review = createReviewController();
|
|
119
102
|
session.progress = createProgress(
|
|
120
103
|
session.term,
|
|
121
104
|
() => session.tickProgress(),
|
|
@@ -123,28 +106,6 @@ const assignOptions = (session, options) => {
|
|
|
123
106
|
);
|
|
124
107
|
};
|
|
125
108
|
|
|
126
|
-
const assignUpdater = (session) => {
|
|
127
|
-
session.updater = createUpdateCoordinator({
|
|
128
|
-
updateOpts: () => session.updateOpts,
|
|
129
|
-
didLoad: () => session.loader.didLoad,
|
|
130
|
-
getMode: () => session.mode,
|
|
131
|
-
setMode: (mode) => {
|
|
132
|
-
session.mode = mode;
|
|
133
|
-
},
|
|
134
|
-
isDone: () => session.done,
|
|
135
|
-
uiOpen: () => session.uiOpen,
|
|
136
|
-
paint: () => session.paint(),
|
|
137
|
-
setStatus: (value) => {
|
|
138
|
-
session.status = value;
|
|
139
|
-
},
|
|
140
|
-
startInstallProgress: () => {
|
|
141
|
-
session.progressFrame = 0;
|
|
142
|
-
session.progress.start('install');
|
|
143
|
-
},
|
|
144
|
-
stopInstallProgress: () => session.progress.stop('install'),
|
|
145
|
-
});
|
|
146
|
-
};
|
|
147
|
-
|
|
148
109
|
const assignComposer = (session) => {
|
|
149
110
|
session.composer = createComposer({
|
|
150
111
|
nav: session.nav,
|
|
@@ -162,73 +123,10 @@ const assignComposer = (session) => {
|
|
|
162
123
|
};
|
|
163
124
|
|
|
164
125
|
const assignControllers = (session) => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
session.mode = mode;
|
|
170
|
-
};
|
|
171
|
-
session.ops = createOpsRunner({
|
|
172
|
-
top: () => session.top,
|
|
173
|
-
isDone: () => session.done,
|
|
174
|
-
getMode: () => session.mode,
|
|
175
|
-
setMode,
|
|
176
|
-
getStatus: () => session.status,
|
|
177
|
-
setStatus,
|
|
178
|
-
paint: () => session.paint(),
|
|
179
|
-
startProgress: () => session.startProgress(),
|
|
180
|
-
stopProgress: () => session.stopProgress(),
|
|
181
|
-
resetProgressFrame: () => {
|
|
182
|
-
session.progressFrame = 0;
|
|
183
|
-
},
|
|
184
|
-
});
|
|
185
|
-
session.changeActions = createChangeActions({
|
|
186
|
-
repo: () => session.repo,
|
|
187
|
-
top: () => session.top,
|
|
188
|
-
capabilities: () => session.capabilities,
|
|
189
|
-
uiOpen: () => session.uiOpen,
|
|
190
|
-
collection: session.collection,
|
|
191
|
-
getItems: () => session.items,
|
|
192
|
-
currentItem: () => session.current(),
|
|
193
|
-
nav: session.nav,
|
|
194
|
-
fileList: () => session.fileList(),
|
|
195
|
-
runBusy: session.ops.runBusy,
|
|
196
|
-
reloadAfterChange: (afterLoad) => session.reloadAfterChange(afterLoad),
|
|
197
|
-
setStatus,
|
|
198
|
-
syncReviewPath: () => session.syncReviewPath(),
|
|
199
|
-
syncFileCursor: () => session.syncFileCursor(),
|
|
200
|
-
});
|
|
201
|
-
session.commits = createCommitController({
|
|
202
|
-
repo: () => session.repo,
|
|
203
|
-
top: () => session.top,
|
|
204
|
-
capabilities: () => session.capabilities,
|
|
205
|
-
getItems: () => session.items,
|
|
206
|
-
uiOpen: () => session.uiOpen,
|
|
207
|
-
composer: session.composer,
|
|
208
|
-
collection: session.collection,
|
|
209
|
-
runner: session.ops,
|
|
210
|
-
refreshFromRepo: (opts) => session.refreshFromRepo(opts),
|
|
211
|
-
setMode,
|
|
212
|
-
setStatus,
|
|
213
|
-
isDone: () => session.done,
|
|
214
|
-
pendingExtras: () => session.pendingExtras,
|
|
215
|
-
});
|
|
216
|
-
session.gitBranches = createBranchController({
|
|
217
|
-
repo: () => session.repo,
|
|
218
|
-
top: () => session.top,
|
|
219
|
-
capabilities: () => session.capabilities,
|
|
220
|
-
uiOpen: () => session.uiOpen,
|
|
221
|
-
composer: session.composer,
|
|
222
|
-
nav: session.nav,
|
|
223
|
-
runner: session.ops,
|
|
224
|
-
canCommit: session.commits.canCommit,
|
|
225
|
-
refreshFromRepo: (opts) => session.refreshFromRepo(opts),
|
|
226
|
-
showFiles: () => session.showFiles(),
|
|
227
|
-
getMode: () => session.mode,
|
|
228
|
-
setMode,
|
|
229
|
-
getStatus: () => session.status,
|
|
230
|
-
setStatus,
|
|
231
|
-
});
|
|
126
|
+
session.ops = createOpsRunner(session);
|
|
127
|
+
session.changeActions = createChangeActions(session);
|
|
128
|
+
session.commits = createCommitController(session);
|
|
129
|
+
session.gitBranches = createBranchController(session);
|
|
232
130
|
};
|
|
233
131
|
|
|
234
132
|
const bindSessionAccessors = (session) => {
|
|
@@ -286,33 +184,12 @@ const bindViewer = (session) => {
|
|
|
286
184
|
collection: session.collection,
|
|
287
185
|
review: session.review,
|
|
288
186
|
gitBranches: session.gitBranches,
|
|
187
|
+
commits: session.commits,
|
|
289
188
|
updater: session.updater,
|
|
290
189
|
ui: session,
|
|
291
190
|
});
|
|
292
191
|
};
|
|
293
192
|
|
|
294
|
-
const bindFilesPane = (session) => {
|
|
295
|
-
session.filesPane = createFilesPane({
|
|
296
|
-
nav: session.nav,
|
|
297
|
-
composer: session.composer,
|
|
298
|
-
items: () => session.items,
|
|
299
|
-
todoItem: () => session.todoItem,
|
|
300
|
-
fileList: () => session.fileList(),
|
|
301
|
-
setStatus: (value) => {
|
|
302
|
-
session.status = value;
|
|
303
|
-
},
|
|
304
|
-
onQuit: () => session.onQuit(),
|
|
305
|
-
onCheckoutBranch: session.gitBranches.onCheckoutBranch,
|
|
306
|
-
onBranchMove: session.gitBranches.onBranchMove,
|
|
307
|
-
layout: () => session.layout,
|
|
308
|
-
setLayout: (value) => {
|
|
309
|
-
session.layout = value;
|
|
310
|
-
},
|
|
311
|
-
lastFrame: () => session.lastFrame,
|
|
312
|
-
getSize: () => session.lastSize ?? session.getSize(),
|
|
313
|
-
});
|
|
314
|
-
};
|
|
315
|
-
|
|
316
193
|
const bindLifecycle = (session) => {
|
|
317
194
|
session.lifecycle = createLifecycle({
|
|
318
195
|
loader: session.loader,
|
|
@@ -329,104 +206,24 @@ const bindLifecycle = (session) => {
|
|
|
329
206
|
outdatedMap: session.outdatedMap,
|
|
330
207
|
auditMap: session.auditMap,
|
|
331
208
|
},
|
|
332
|
-
watch: session.watchOpts,
|
|
333
209
|
ui: session,
|
|
334
210
|
});
|
|
335
211
|
};
|
|
336
212
|
|
|
337
213
|
const bindDispatch = (session) => {
|
|
338
|
-
|
|
339
|
-
session.
|
|
340
|
-
|
|
341
|
-
getPane: () => session.pane,
|
|
342
|
-
currentTarget: () => {
|
|
343
|
-
if (session.pane === 'files') return session.fileCursorEntry();
|
|
344
|
-
if (session.pane === 'branches') {
|
|
345
|
-
return session.branches[session.branchCursor];
|
|
346
|
-
}
|
|
347
|
-
return session.current();
|
|
348
|
-
},
|
|
349
|
-
composer: session.composer,
|
|
350
|
-
changeActions: session.changeActions,
|
|
351
|
-
commits: session.commits,
|
|
352
|
-
gitBranches: session.gitBranches,
|
|
353
|
-
onFileMove: filesPane.onFileMove,
|
|
354
|
-
onBranchMove: session.gitBranches.onBranchMove,
|
|
355
|
-
onNext: filesPane.onNext,
|
|
356
|
-
onPrev: filesPane.onPrev,
|
|
357
|
-
onOpenFile: filesPane.onOpenFile,
|
|
358
|
-
onFiles: filesPane.onFiles,
|
|
359
|
-
onQuit: () => session.onQuit(),
|
|
360
|
-
onLayout: filesPane.onLayout,
|
|
361
|
-
onReload: session.lifecycle.onReload,
|
|
362
|
-
onScroll: filesPane.onScroll,
|
|
363
|
-
onHome: filesPane.onHome,
|
|
364
|
-
onEnd: filesPane.onEnd,
|
|
365
|
-
scrollStep: filesPane.scrollStep,
|
|
366
|
-
});
|
|
367
|
-
session.pointer = createPointer({
|
|
368
|
-
nav: session.nav,
|
|
369
|
-
getSize: () => session.lastSize ?? session.getSize(),
|
|
370
|
-
lastFrame: () => session.lastFrame,
|
|
371
|
-
copyText: (text, stdout) => session.copyText(text, stdout),
|
|
372
|
-
stdout: () => session.stdout,
|
|
373
|
-
setStatus: (value) => {
|
|
374
|
-
session.status = value;
|
|
375
|
-
},
|
|
376
|
-
dispatch: (action) => session.dispatcher.dispatch(action),
|
|
377
|
-
getPane: () => session.pane,
|
|
378
|
-
getMode: () => session.mode,
|
|
379
|
-
confirmChoice: (key) => session.input.confirmChoice(key),
|
|
380
|
-
onBranch: session.gitBranches.onBranch,
|
|
381
|
-
onOpenFile: filesPane.onOpenFile,
|
|
382
|
-
onCheckoutBranch: session.gitBranches.onCheckoutBranch,
|
|
383
|
-
onTodoHit: (cursor) => session.composer.onTodoHit(cursor),
|
|
384
|
-
selectTemplate: (index) => session.selectTemplate(index),
|
|
385
|
-
onScroll: filesPane.onScroll,
|
|
386
|
-
});
|
|
387
|
-
session.input = createInput({
|
|
388
|
-
getMode: () => session.mode,
|
|
389
|
-
getPane: () => session.pane,
|
|
390
|
-
composer: session.composer,
|
|
391
|
-
pointer: session.pointer,
|
|
392
|
-
dispatch: (action) => session.dispatcher.dispatch(action),
|
|
393
|
-
onEscape: filesPane.onEscape,
|
|
394
|
-
onQuit: () => session.onQuit(),
|
|
395
|
-
runComposeCommand: (result) => session.runComposeCommand(result),
|
|
396
|
-
quit: {
|
|
397
|
-
ready: () => session.finishQuit('ready'),
|
|
398
|
-
editing: () => session.finishQuit('editing'),
|
|
399
|
-
cancel: () => session.cancelQuit(),
|
|
400
|
-
},
|
|
401
|
-
commit: {
|
|
402
|
-
commit: () => session.commits.startGitCommit('commit'),
|
|
403
|
-
amend: () => session.commits.startGitCommit('amend'),
|
|
404
|
-
fixup: () => session.commits.startGitCommit('fixup'),
|
|
405
|
-
cancel: session.commits.cancelCommit,
|
|
406
|
-
},
|
|
407
|
-
update: {
|
|
408
|
-
accept: session.updater.accept,
|
|
409
|
-
decline: session.updater.decline,
|
|
410
|
-
},
|
|
411
|
-
drop: {
|
|
412
|
-
confirm: session.gitBranches.confirmDropBranch,
|
|
413
|
-
cancel: session.gitBranches.cancelDropBranch,
|
|
414
|
-
},
|
|
415
|
-
push: {
|
|
416
|
-
force: session.gitBranches.onForcePush,
|
|
417
|
-
cancel: session.gitBranches.cancelPush,
|
|
418
|
-
},
|
|
419
|
-
});
|
|
214
|
+
session.dispatcher = createDispatcher(session);
|
|
215
|
+
session.pointer = createPointer(session);
|
|
216
|
+
session.input = createInput(session);
|
|
420
217
|
};
|
|
421
218
|
|
|
422
219
|
const composeSession = (session, options) => {
|
|
423
220
|
assignOptions(session, options);
|
|
424
|
-
|
|
221
|
+
session.updater = createUpdateCoordinator(session);
|
|
425
222
|
assignComposer(session);
|
|
426
223
|
assignControllers(session);
|
|
427
224
|
bindSessionAccessors(session);
|
|
428
225
|
bindViewer(session);
|
|
429
|
-
|
|
226
|
+
session.filesPane = createFilesPane(session);
|
|
430
227
|
bindLifecycle(session);
|
|
431
228
|
bindDispatch(session);
|
|
432
229
|
};
|
|
@@ -444,6 +241,7 @@ class Session {
|
|
|
444
241
|
if (this.composer) this.composer.reset();
|
|
445
242
|
if (this.ops) this.ops.reset();
|
|
446
243
|
if (this.gitBranches) this.gitBranches.reset();
|
|
244
|
+
if (this.commits) this.commits.reset();
|
|
447
245
|
this.top = this.cwd;
|
|
448
246
|
this.branch = '';
|
|
449
247
|
this.status = '';
|
|
@@ -490,6 +288,10 @@ class Session {
|
|
|
490
288
|
this.lifecycle.reloadAfterChange(afterLoad);
|
|
491
289
|
}
|
|
492
290
|
|
|
291
|
+
ignoreWatch(ms) {
|
|
292
|
+
this.lifecycle.ignoreWatch(ms);
|
|
293
|
+
}
|
|
294
|
+
|
|
493
295
|
applyLoaded(loaded) {
|
|
494
296
|
return this.lifecycle.applyLoaded(loaded);
|
|
495
297
|
}
|
|
@@ -507,7 +309,11 @@ class Session {
|
|
|
507
309
|
height: size.height,
|
|
508
310
|
color: this.color,
|
|
509
311
|
});
|
|
510
|
-
if (
|
|
312
|
+
if (
|
|
313
|
+
this.pane === 'files' ||
|
|
314
|
+
this.pane === 'branches' ||
|
|
315
|
+
this.pane === 'commits'
|
|
316
|
+
) {
|
|
511
317
|
this.nav.listScroll = frame.listScroll;
|
|
512
318
|
}
|
|
513
319
|
const composing = this.mode === 'compose';
|
|
@@ -577,7 +383,7 @@ class Session {
|
|
|
577
383
|
}
|
|
578
384
|
|
|
579
385
|
initReview() {
|
|
580
|
-
this.review.init(this.top,
|
|
386
|
+
this.review.init(this.top, new Date(), {
|
|
581
387
|
forceNew: this.forceNewReview,
|
|
582
388
|
});
|
|
583
389
|
}
|
|
@@ -714,10 +520,7 @@ class Session {
|
|
|
714
520
|
}
|
|
715
521
|
const onData = (chunk) => {
|
|
716
522
|
this.pushInput(chunk.toString('utf8'));
|
|
717
|
-
if (this.done)
|
|
718
|
-
finish();
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
523
|
+
if (this.done) return void finish();
|
|
721
524
|
this.draw();
|
|
722
525
|
};
|
|
723
526
|
this.term.startListening({
|
package/lib/source.js
CHANGED
|
@@ -8,13 +8,13 @@ const selectChangeSource = (paths) => {
|
|
|
8
8
|
if (!paths.length) return { kind: 'local', paths };
|
|
9
9
|
const first = paths[0];
|
|
10
10
|
const pr = parseGithubPrUrl(first);
|
|
11
|
-
if (pr) return { kind: '
|
|
11
|
+
if (pr) return { kind: 'pr', pr, paths: paths.slice(1) };
|
|
12
12
|
const mr = parseGitlabMrUrl(first);
|
|
13
|
-
if (mr) return { kind: '
|
|
13
|
+
if (mr) return { kind: 'mr', mr, paths: paths.slice(1) };
|
|
14
14
|
return { kind: 'local', paths };
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
const createLoadedSource = (loaded, kind = '
|
|
17
|
+
const createLoadedSource = (loaded, kind = 'pr', extra = {}) => {
|
|
18
18
|
const load = () => {
|
|
19
19
|
const items = loaded.items ?? [];
|
|
20
20
|
return { ...loaded, items: [...items] };
|
package/lib/update.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { spawn } = require('node:child_process');
|
|
4
3
|
const fs = require('node:fs');
|
|
5
4
|
const os = require('node:os');
|
|
6
5
|
const path = require('node:path');
|
|
7
6
|
|
|
8
|
-
const {
|
|
7
|
+
const { jsonParse, isHashObject } = require('metautil');
|
|
8
|
+
const {
|
|
9
|
+
parseVersion,
|
|
10
|
+
cmpVersion,
|
|
11
|
+
npmBin,
|
|
12
|
+
npmOpts,
|
|
13
|
+
runProc,
|
|
14
|
+
oneLine,
|
|
15
|
+
} = require('./utilities.js');
|
|
9
16
|
|
|
10
17
|
const PKG = require('../package.json');
|
|
11
18
|
|
|
@@ -29,45 +36,28 @@ const asText = (value) => (typeof value === 'string' ? value : '');
|
|
|
29
36
|
|
|
30
37
|
const toInt = (text) => parseInt(text, 10);
|
|
31
38
|
|
|
32
|
-
const parseVersion = (text) => {
|
|
33
|
-
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(`${text ?? ''}`);
|
|
34
|
-
if (!match) return null;
|
|
35
|
-
return {
|
|
36
|
-
major: toInt(match[1]),
|
|
37
|
-
minor: toInt(match[2]),
|
|
38
|
-
patch: toInt(match[3]),
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const cmpVersion = (left, right) => {
|
|
43
|
-
if (left.major !== right.major) return left.major - right.major;
|
|
44
|
-
if (left.minor !== right.minor) return left.minor - right.minor;
|
|
45
|
-
return left.patch - right.patch;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
39
|
const isNpmInstall = (pkgDir) => {
|
|
49
40
|
const parent = path.basename(path.dirname(pkgDir));
|
|
50
41
|
return parent === 'node_modules';
|
|
51
42
|
};
|
|
52
43
|
|
|
53
|
-
const cacheFile = (env = process.env
|
|
54
|
-
const home = extra.home ?? os.homedir();
|
|
55
|
-
const platform = extra.platform ?? process.platform;
|
|
44
|
+
const cacheFile = (env = process.env) => {
|
|
56
45
|
if (env.XDG_CACHE_HOME) {
|
|
57
46
|
return path.join(env.XDG_CACHE_HOME, 'reslop', 'update.json');
|
|
58
47
|
}
|
|
59
|
-
if (platform === 'win32') {
|
|
60
|
-
const local =
|
|
48
|
+
if (process.platform === 'win32') {
|
|
49
|
+
const local =
|
|
50
|
+
env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
61
51
|
return path.join(local, 'reslop', 'update.json');
|
|
62
52
|
}
|
|
63
|
-
return path.join(
|
|
53
|
+
return path.join(os.homedir(), '.cache', 'reslop', 'update.json');
|
|
64
54
|
};
|
|
65
55
|
|
|
66
|
-
const readCache = (file
|
|
56
|
+
const readCache = (file) => {
|
|
67
57
|
try {
|
|
68
|
-
const text = readFileSync(file, 'utf8');
|
|
69
|
-
const data =
|
|
70
|
-
if (!
|
|
58
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
59
|
+
const data = jsonParse(text);
|
|
60
|
+
if (!isHashObject(data)) {
|
|
71
61
|
return emptyCache();
|
|
72
62
|
}
|
|
73
63
|
const checkedAt = toInt(data.checkedAt) || 0;
|
|
@@ -80,17 +70,15 @@ const readCache = (file, readFileSync = fs.readFileSync) => {
|
|
|
80
70
|
}
|
|
81
71
|
};
|
|
82
72
|
|
|
83
|
-
const writeCache = (file, data
|
|
84
|
-
const mkdirSync = extra.mkdirSync ?? fs.mkdirSync;
|
|
85
|
-
const writeFileSync = extra.writeFileSync ?? fs.writeFileSync;
|
|
73
|
+
const writeCache = (file, data) => {
|
|
86
74
|
try {
|
|
87
|
-
mkdirSync(path.dirname(file), { recursive: true });
|
|
75
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
88
76
|
const checkedAt = data.checkedAt ?? 0;
|
|
89
77
|
const compatible = data.compatible ?? '';
|
|
90
78
|
const major = data.major ?? '';
|
|
91
79
|
const skipped = data.skipped ?? '';
|
|
92
80
|
const body = JSON.stringify({ checkedAt, compatible, major, skipped });
|
|
93
|
-
writeFileSync(file, `${body}\n`);
|
|
81
|
+
fs.writeFileSync(file, `${body}\n`);
|
|
94
82
|
} catch {
|
|
95
83
|
// ignore cache write errors
|
|
96
84
|
}
|
|
@@ -106,7 +94,7 @@ const listVersions = (data) => {
|
|
|
106
94
|
if (!data || typeof data !== 'object') return [];
|
|
107
95
|
const names = [];
|
|
108
96
|
const map = data.versions;
|
|
109
|
-
if (
|
|
97
|
+
if (isHashObject(map)) {
|
|
110
98
|
for (const name of Object.keys(map)) names.push(name);
|
|
111
99
|
}
|
|
112
100
|
const tags = data['dist-tags'];
|
|
@@ -187,12 +175,6 @@ const isEnabled = (options = {}) => {
|
|
|
187
175
|
return isNpmInstall(pkgDir);
|
|
188
176
|
};
|
|
189
177
|
|
|
190
|
-
const nowMs = (options = {}) => {
|
|
191
|
-
if (typeof options.now === 'function') return options.now();
|
|
192
|
-
if (typeof options.now === 'number') return options.now;
|
|
193
|
-
return Date.now();
|
|
194
|
-
};
|
|
195
|
-
|
|
196
178
|
const fetchTargets = async (current, options = {}) => {
|
|
197
179
|
const empty = { compatible: '', major: '' };
|
|
198
180
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -207,33 +189,18 @@ const fetchTargets = async (current, options = {}) => {
|
|
|
207
189
|
return pickTargets(current, listVersions(data));
|
|
208
190
|
};
|
|
209
191
|
|
|
210
|
-
const npmInstall = (spec, extra = {}) =>
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const timer = setTimeout(() => {
|
|
223
|
-
child.kill();
|
|
224
|
-
reject(new Error('timed out'));
|
|
225
|
-
}, timeout);
|
|
226
|
-
child.on('error', (error) => {
|
|
227
|
-
clearTimeout(timer);
|
|
228
|
-
reject(error);
|
|
229
|
-
});
|
|
230
|
-
child.on('close', (status) => {
|
|
231
|
-
clearTimeout(timer);
|
|
232
|
-
if (status === 0) return void resolve();
|
|
233
|
-
const line = stderr.trim().split('\n')[0];
|
|
234
|
-
reject(new Error(line || 'npm install failed'));
|
|
235
|
-
});
|
|
236
|
-
});
|
|
192
|
+
const npmInstall = async (spec, extra = {}) => {
|
|
193
|
+
const timeout = extra.timeout ?? INSTALL_MS;
|
|
194
|
+
const result = await runProc(
|
|
195
|
+
npmBin(),
|
|
196
|
+
['install', '-g', spec],
|
|
197
|
+
npmOpts({ timeout }),
|
|
198
|
+
);
|
|
199
|
+
if (result.error) throw result.error;
|
|
200
|
+
if (result.status !== 0) {
|
|
201
|
+
throw new Error(oneLine(result.stderr, 'npm install failed'));
|
|
202
|
+
}
|
|
203
|
+
};
|
|
237
204
|
|
|
238
205
|
const installUpdate = async (version, options = {}) => {
|
|
239
206
|
if (typeof options.install === 'function') {
|
|
@@ -246,19 +213,17 @@ const installUpdate = async (version, options = {}) => {
|
|
|
246
213
|
|
|
247
214
|
const markSkipped = (version, options = {}) => {
|
|
248
215
|
const file = options.cacheFile ?? cacheFile(options.env);
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
writeCache(file, { ...cache, skipped: version }, options);
|
|
216
|
+
const cache = readCache(file);
|
|
217
|
+
writeCache(file, { ...cache, skipped: version });
|
|
252
218
|
};
|
|
253
219
|
|
|
254
220
|
const checkUpdate = async (options = {}) => {
|
|
255
221
|
if (!isEnabled(options)) return { action: 'skip' };
|
|
256
|
-
const now =
|
|
222
|
+
const now = Date.now();
|
|
257
223
|
const current = options.current ?? PKG_VERSION;
|
|
258
224
|
const file = options.cacheFile ?? cacheFile(options.env);
|
|
259
|
-
const readFileSync = options.readFileSync ?? fs.readFileSync;
|
|
260
225
|
const interval = options.interval ?? CHECK_INTERVAL_MS;
|
|
261
|
-
const cache = readCache(file
|
|
226
|
+
const cache = readCache(file);
|
|
262
227
|
if (isFresh(cache, now, interval)) {
|
|
263
228
|
const plan = planUpdate(current, cache);
|
|
264
229
|
if (plan.action === 'install') return { action: 'none' };
|
|
@@ -277,10 +242,10 @@ const checkUpdate = async (options = {}) => {
|
|
|
277
242
|
major: targets.major,
|
|
278
243
|
};
|
|
279
244
|
if (!targets.compatible && !targets.major) {
|
|
280
|
-
writeCache(file, { ...cache, checkedAt: now }
|
|
245
|
+
writeCache(file, { ...cache, checkedAt: now });
|
|
281
246
|
return { action: 'none' };
|
|
282
247
|
}
|
|
283
|
-
writeCache(file, next
|
|
248
|
+
writeCache(file, next);
|
|
284
249
|
return planUpdate(current, next);
|
|
285
250
|
};
|
|
286
251
|
|