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
package/lib/diff/display.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const patch = require('./patch.js');
|
|
6
|
-
const { flattenBlock } = patch;
|
|
3
|
+
const { isCtxType, attachInline, LAYOUT_ALIGN } = require('./align.js');
|
|
4
|
+
const { flattenBlock } = require('./patch.js');
|
|
7
5
|
|
|
8
6
|
const DISPLAY_CONTEXT = 3;
|
|
9
7
|
|
|
@@ -80,11 +78,37 @@ const blockAddText = (hunk, blockId) => {
|
|
|
80
78
|
return parts.join('\n');
|
|
81
79
|
};
|
|
82
80
|
|
|
81
|
+
const countsOld = (line) => {
|
|
82
|
+
if (line.type === 'add' || line.synthetic === true) return false;
|
|
83
|
+
return line.type !== 'note' && line.type !== 'noteSep';
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const countsNew = (line) => line.type !== 'del';
|
|
87
|
+
|
|
88
|
+
const stampLineNumbers = (lines, hunk) => {
|
|
89
|
+
let oldNo = hunk && hunk.oldStart > 0 ? hunk.oldStart : 0;
|
|
90
|
+
let newNo = hunk && hunk.newStart > 0 ? hunk.newStart : 1;
|
|
91
|
+
return lines.map((line) => {
|
|
92
|
+
const next = { ...line };
|
|
93
|
+
if (line.type === 'note' || line.type === 'noteSep') return next;
|
|
94
|
+
if (countsOld(line)) {
|
|
95
|
+
if (oldNo > 0) next.oldNo = oldNo;
|
|
96
|
+
oldNo += 1;
|
|
97
|
+
}
|
|
98
|
+
if (countsNew(line)) {
|
|
99
|
+
next.newNo = newNo;
|
|
100
|
+
newNo += 1;
|
|
101
|
+
}
|
|
102
|
+
return next;
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
|
|
83
106
|
const displayLines = (hunk, blockId, layout = 'unified', radius, overlay) => {
|
|
84
107
|
const flat = flattenBlock(hunk, blockId, 'new');
|
|
85
108
|
const source = overlay ? replaceAdds(flat, overlay, blockId) : flat;
|
|
109
|
+
const numbered = stampLineNumbers(source, hunk);
|
|
86
110
|
const around = radius ?? DISPLAY_CONTEXT;
|
|
87
|
-
const painted = attachInline(windowAroundBlock(
|
|
111
|
+
const painted = attachInline(windowAroundBlock(numbered, blockId, around));
|
|
88
112
|
const alignRows = LAYOUT_ALIGN[layout];
|
|
89
113
|
return alignRows ? alignRows(painted) : painted;
|
|
90
114
|
};
|
package/lib/diff/inline.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { graphemes } = ansi;
|
|
3
|
+
const { graphemes } = require('../term/ansi.js');
|
|
5
4
|
|
|
6
5
|
const LCS_CELL_LIMIT = 250000;
|
|
7
6
|
const NOISY_TINY_SPANS = 6;
|
|
@@ -131,10 +130,9 @@ const opsSpans = (ops) => {
|
|
|
131
130
|
newParts.push({ text: op.text, changed: op.type === 'add' });
|
|
132
131
|
}
|
|
133
132
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
};
|
|
133
|
+
const oldSpans = collapseSpans(oldParts);
|
|
134
|
+
const newSpans = collapseSpans(newParts);
|
|
135
|
+
return { oldSpans, newSpans };
|
|
138
136
|
};
|
|
139
137
|
|
|
140
138
|
const joinAffix = (prefix, mid, suffix) => {
|
|
@@ -154,10 +152,9 @@ const diffTrimmed = (a, b, spansOfOps) => {
|
|
|
154
152
|
const mid = whole ? wholeChanged(midA, midB) : spansOfOps(lcsOps(midA, midB));
|
|
155
153
|
const prefix = a.slice(0, lo);
|
|
156
154
|
const suffix = a.slice(hiA);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
};
|
|
155
|
+
const oldSpans = joinAffix(prefix, mid.oldSpans, suffix);
|
|
156
|
+
const newSpans = joinAffix(prefix, mid.newSpans, suffix);
|
|
157
|
+
return { oldSpans, newSpans };
|
|
161
158
|
};
|
|
162
159
|
|
|
163
160
|
const diffTokens = (a, b) => {
|
|
@@ -221,10 +218,9 @@ const refineWordOps = (ops) => {
|
|
|
221
218
|
if (dels.length) oldParts.push({ text: dels.join(''), changed: true });
|
|
222
219
|
if (adds.length) newParts.push({ text: adds.join(''), changed: true });
|
|
223
220
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
};
|
|
221
|
+
const oldSpans = collapseSpans(oldParts);
|
|
222
|
+
const newSpans = collapseSpans(newParts);
|
|
223
|
+
return { oldSpans, newSpans };
|
|
228
224
|
};
|
|
229
225
|
|
|
230
226
|
const opRuns = (ops) => {
|
package/lib/diff/items.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { splitHunk, formatHunkHeader, formatPatch } = patch;
|
|
3
|
+
const { splitHunk, formatHunkHeader, formatPatch } = require('./patch.js');
|
|
5
4
|
|
|
6
5
|
const BINARY_ITEM = {
|
|
7
6
|
hunk: null,
|
|
@@ -70,8 +69,11 @@ const itemsFromFiles = (files, origin) => {
|
|
|
70
69
|
|
|
71
70
|
const refreshIndexPatches = (items, item) => {
|
|
72
71
|
if (!item.hunk) return items;
|
|
73
|
-
const isPeer = (other) =>
|
|
74
|
-
|
|
72
|
+
const isPeer = (other) => {
|
|
73
|
+
const sameHunk = other.hunk === item.hunk;
|
|
74
|
+
const sameFile = other.file === item.file;
|
|
75
|
+
return sameHunk && sameFile;
|
|
76
|
+
};
|
|
75
77
|
const peers = items.filter(isPeer);
|
|
76
78
|
const sides = {};
|
|
77
79
|
for (const peer of peers) sides[peer.blockId] = indexSide(peer.origin);
|
package/lib/diff/patch.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const { isCtxType } = align;
|
|
3
|
+
const { clamp } = require('../common/utilities.js');
|
|
4
|
+
const { isCtxType } = require('./align.js');
|
|
5
5
|
|
|
6
6
|
const LINE_MARK = { add: '+', del: '-' };
|
|
7
7
|
|
|
@@ -40,7 +40,11 @@ const flattenBlock = (hunk, blockId, contextSide) => {
|
|
|
40
40
|
}
|
|
41
41
|
const kept = sideOf(contextSide, line.blockId) === 'old' ? 'del' : 'add';
|
|
42
42
|
if (line.type === kept) {
|
|
43
|
-
|
|
43
|
+
const type = 'ctx';
|
|
44
|
+
const { text, noNl } = line;
|
|
45
|
+
const synthetic = true;
|
|
46
|
+
const row = { type, text, noNl, synthetic };
|
|
47
|
+
out.push(row);
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
50
|
return out;
|
|
@@ -72,10 +76,42 @@ const formatPatch = (file, hunk, blockId, contextSide) => {
|
|
|
72
76
|
return `${parts.join('\n')}\n`;
|
|
73
77
|
};
|
|
74
78
|
|
|
79
|
+
const addBlockRange = (hunk, blockId) => {
|
|
80
|
+
let newLine = hunk.newStart;
|
|
81
|
+
let start = 0;
|
|
82
|
+
let count = 0;
|
|
83
|
+
for (const line of hunk.lines) {
|
|
84
|
+
if (line.type === 'del') {
|
|
85
|
+
if (line.blockId === blockId && start === 0) start = newLine;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (line.type === 'add' && line.blockId === blockId) {
|
|
89
|
+
if (count === 0) start = newLine;
|
|
90
|
+
count += 1;
|
|
91
|
+
}
|
|
92
|
+
newLine += 1;
|
|
93
|
+
}
|
|
94
|
+
if (start === 0) start = hunk.newStart;
|
|
95
|
+
return { start, count };
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const replaceBlockAdds = (content, hunk, blockId, text) => {
|
|
99
|
+
const range = addBlockRange(hunk, blockId);
|
|
100
|
+
const ended = content.endsWith('\n');
|
|
101
|
+
const body = ended ? content.slice(0, -1) : content;
|
|
102
|
+
const lines = content === '' ? [] : body.split('\n');
|
|
103
|
+
const from = clamp(range.start - 1, 0, lines.length);
|
|
104
|
+
const added = text === '' ? [] : text.split('\n');
|
|
105
|
+
lines.splice(from, range.count, ...added);
|
|
106
|
+
return lines.join('\n') + (ended ? '\n' : '');
|
|
107
|
+
};
|
|
108
|
+
|
|
75
109
|
module.exports = {
|
|
76
110
|
splitHunk,
|
|
77
111
|
flattenBlock,
|
|
78
112
|
countSides,
|
|
79
113
|
formatHunkHeader,
|
|
80
114
|
formatPatch,
|
|
115
|
+
addBlockRange,
|
|
116
|
+
replaceBlockAdds,
|
|
81
117
|
};
|
package/lib/diff/unit.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const files = require('../files.js');
|
|
6
|
-
const { listPath } = files;
|
|
3
|
+
const { attachInline } = require('./align.js');
|
|
4
|
+
const { listPath } = require('../common/files.js');
|
|
7
5
|
|
|
8
6
|
const LCS_CELLS = 4000000;
|
|
9
7
|
|
|
@@ -75,6 +73,16 @@ const rowsFromAdds = (items) => {
|
|
|
75
73
|
return rows;
|
|
76
74
|
};
|
|
77
75
|
|
|
76
|
+
const stampFileNumbers = (lines) => {
|
|
77
|
+
let newNo = 1;
|
|
78
|
+
for (const line of lines) {
|
|
79
|
+
if (line.type === 'del') continue;
|
|
80
|
+
line.newNo = newNo;
|
|
81
|
+
newNo += 1;
|
|
82
|
+
}
|
|
83
|
+
return lines;
|
|
84
|
+
};
|
|
85
|
+
|
|
78
86
|
const unitLines = (text, items) => {
|
|
79
87
|
let rows = splitFile(text);
|
|
80
88
|
if (!rows.length) rows = rowsFromAdds(items);
|
|
@@ -95,11 +103,14 @@ const unitLines = (text, items) => {
|
|
|
95
103
|
out.push(tagged('del', del.text, del));
|
|
96
104
|
}
|
|
97
105
|
if (!out.length) out.push(tagged('ctx', '', NO_EXTRA));
|
|
98
|
-
return attachInline(out);
|
|
106
|
+
return stampFileNumbers(attachInline(out));
|
|
99
107
|
};
|
|
100
108
|
|
|
101
|
-
const sameBlock = (line, item) =>
|
|
102
|
-
|
|
109
|
+
const sameBlock = (line, item) => {
|
|
110
|
+
const sameItem = line.item === item;
|
|
111
|
+
const sameId = line.blockId === item.blockId;
|
|
112
|
+
return sameItem && sameId;
|
|
113
|
+
};
|
|
103
114
|
|
|
104
115
|
const changedLineRange = (lines, item, belongs) => {
|
|
105
116
|
let start = -1;
|
|
@@ -187,25 +198,33 @@ const zipOps = (prev, next) => {
|
|
|
187
198
|
};
|
|
188
199
|
|
|
189
200
|
const lcsOps = (prev, next) => {
|
|
190
|
-
const dp = lcsTable(prev, next);
|
|
191
201
|
const ops = [];
|
|
202
|
+
const limit = Math.min(prev.length, next.length);
|
|
203
|
+
let head = 0;
|
|
204
|
+
while (head < limit && prev[head] === next[head]) {
|
|
205
|
+
ops.push({ kind: 'eq', text: next[head] });
|
|
206
|
+
head += 1;
|
|
207
|
+
}
|
|
208
|
+
const left = head ? prev.slice(head) : prev;
|
|
209
|
+
const right = head ? next.slice(head) : next;
|
|
210
|
+
const dp = lcsTable(left, right);
|
|
192
211
|
let i = 0;
|
|
193
212
|
let j = 0;
|
|
194
|
-
while (i <
|
|
195
|
-
if (
|
|
196
|
-
ops.push({ kind: 'eq', text:
|
|
213
|
+
while (i < left.length && j < right.length) {
|
|
214
|
+
if (left[i] === right[j]) {
|
|
215
|
+
ops.push({ kind: 'eq', text: right[j] });
|
|
197
216
|
i += 1;
|
|
198
217
|
j += 1;
|
|
199
218
|
} else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
200
219
|
ops.push({ kind: 'del' });
|
|
201
220
|
i += 1;
|
|
202
221
|
} else {
|
|
203
|
-
ops.push({ kind: 'ins', text:
|
|
222
|
+
ops.push({ kind: 'ins', text: right[j] });
|
|
204
223
|
j += 1;
|
|
205
224
|
}
|
|
206
225
|
}
|
|
207
|
-
for (; i <
|
|
208
|
-
for (; j <
|
|
226
|
+
for (; i < left.length; i++) ops.push({ kind: 'del' });
|
|
227
|
+
for (; j < right.length; j++) ops.push({ kind: 'ins', text: right[j] });
|
|
209
228
|
return ops;
|
|
210
229
|
};
|
|
211
230
|
|
|
@@ -241,7 +260,7 @@ const pushDels = (out, base, at) => {
|
|
|
241
260
|
return i;
|
|
242
261
|
};
|
|
243
262
|
|
|
244
|
-
const
|
|
263
|
+
const mergeRows = (base, nextTexts) => {
|
|
245
264
|
const texts = nextTexts.length ? nextTexts : [''];
|
|
246
265
|
const prev = [];
|
|
247
266
|
for (const row of base) if (row.type !== 'del') prev.push(row.text);
|
|
@@ -259,7 +278,17 @@ const mergeEditRows = (base, nextTexts) => {
|
|
|
259
278
|
}
|
|
260
279
|
pushDels(out, base, at);
|
|
261
280
|
if (!out.length) out.push(tagged('ctx', '', NO_EXTRA));
|
|
262
|
-
return attachEditSpans(attachInline(out));
|
|
281
|
+
return stampFileNumbers(attachEditSpans(attachInline(out)));
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
let merged = { base: null, text: '', rows: [] };
|
|
285
|
+
|
|
286
|
+
const mergeEditRows = (base, nextTexts) => {
|
|
287
|
+
const text = nextTexts.join('\n');
|
|
288
|
+
if (merged.base === base && merged.text === text) return merged.rows;
|
|
289
|
+
const rows = mergeRows(base, nextTexts);
|
|
290
|
+
merged = { base, text, rows };
|
|
291
|
+
return rows;
|
|
263
292
|
};
|
|
264
293
|
|
|
265
294
|
module.exports = {
|
|
@@ -4,12 +4,9 @@ const fs = require('node:fs');
|
|
|
4
4
|
const os = require('node:os');
|
|
5
5
|
const path = require('node:path');
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const {
|
|
9
|
-
const
|
|
10
|
-
const { shortAge } = files;
|
|
11
|
-
const worktree = require('./git-worktree.js');
|
|
12
|
-
const { requireOk, runGit, command, gitOp } = worktree;
|
|
7
|
+
const { oneLine, trimText } = require('../common/utilities.js');
|
|
8
|
+
const { shortAge } = require('../common/format.js');
|
|
9
|
+
const { requireOk, runGit, command, gitOp } = require('./worktree.js');
|
|
13
10
|
|
|
14
11
|
const BRANCH_FORMAT = [
|
|
15
12
|
'%(HEAD)',
|
|
@@ -43,9 +40,7 @@ const AUTOSQUASH_ARGS = [
|
|
|
43
40
|
'--interactive',
|
|
44
41
|
'--autosquash',
|
|
45
42
|
];
|
|
46
|
-
const REWORD_TODO = path.join(__dirname, '
|
|
47
|
-
|
|
48
|
-
const trimText = (value) => `${value ?? ''}`.trim();
|
|
43
|
+
const REWORD_TODO = path.join(__dirname, 'reword-todo.js');
|
|
49
44
|
|
|
50
45
|
const required = (value, message) => {
|
|
51
46
|
const text = trimText(value);
|
|
@@ -60,9 +55,9 @@ const messageBody = (message) => {
|
|
|
60
55
|
return text.endsWith('\n') ? text : `${text}\n`;
|
|
61
56
|
};
|
|
62
57
|
|
|
63
|
-
const commitMessage = (top, sha) => {
|
|
58
|
+
const commitMessage = async (top, sha) => {
|
|
64
59
|
const spec = trimText(sha) || 'HEAD';
|
|
65
|
-
const result = runGit(['log', '-1', '--format=%B', spec], top);
|
|
60
|
+
const result = await runGit(['log', '-1', '--format=%B', spec], top);
|
|
66
61
|
return result.status === 0 ? result.stdout.trimEnd() : '';
|
|
67
62
|
};
|
|
68
63
|
|
|
@@ -112,7 +107,7 @@ const statCount = (stat, word) => {
|
|
|
112
107
|
return match ? parseInt(match[1], 10) : 0;
|
|
113
108
|
};
|
|
114
109
|
|
|
115
|
-
const listCommits = (top) => {
|
|
110
|
+
const listCommits = async (top) => {
|
|
116
111
|
const args = [
|
|
117
112
|
'log',
|
|
118
113
|
'-z',
|
|
@@ -120,7 +115,7 @@ const listCommits = (top) => {
|
|
|
120
115
|
`--format=${COMMIT_FORMAT}`,
|
|
121
116
|
`--max-count=${COMMIT_LIMIT}`,
|
|
122
117
|
];
|
|
123
|
-
const result = requireOk(runGit(args, top), 'log failed');
|
|
118
|
+
const result = requireOk(await runGit(args, top), 'log failed');
|
|
124
119
|
const commits = [];
|
|
125
120
|
for (const chunk of result.stdout.split('\0')) {
|
|
126
121
|
const stat = STAT_LEAD.exec(chunk);
|
|
@@ -141,11 +136,10 @@ const parseTrack = (text) => {
|
|
|
141
136
|
const raw = trimText(text).replace(/^\[|\]$/g, '');
|
|
142
137
|
const ahead = /ahead (\d+)/.exec(raw);
|
|
143
138
|
const behind = /behind (\d+)/.exec(raw);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
};
|
|
139
|
+
const aheadCount = ahead ? Number(ahead[1]) : 0;
|
|
140
|
+
const behindCount = behind ? Number(behind[1]) : 0;
|
|
141
|
+
const gone = raw === 'gone';
|
|
142
|
+
return { ahead: aheadCount, behind: behindCount, gone };
|
|
149
143
|
};
|
|
150
144
|
|
|
151
145
|
const parseBranchLine = (line) => {
|
|
@@ -163,31 +157,33 @@ const parseBranchLine = (line) => {
|
|
|
163
157
|
};
|
|
164
158
|
};
|
|
165
159
|
|
|
166
|
-
const defaultBranch = (top, names) => {
|
|
167
|
-
const
|
|
160
|
+
const defaultBranch = async (top, names) => {
|
|
161
|
+
const args = ['symbolic-ref', '--short', ORIGIN_HEAD];
|
|
162
|
+
const result = await runGit(args, top);
|
|
168
163
|
const ref = result.status === 0 ? result.stdout.trim() : '';
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
164
|
+
let remote = ref;
|
|
165
|
+
if (ref.startsWith(ORIGIN_PREFIX)) {
|
|
166
|
+
remote = ref.slice(ORIGIN_PREFIX.length);
|
|
167
|
+
}
|
|
172
168
|
if (names.has(remote)) return remote;
|
|
173
169
|
return DEFAULT_BRANCHES.find((name) => names.has(name)) ?? '';
|
|
174
170
|
};
|
|
175
171
|
|
|
176
|
-
const listBranches = (top) => {
|
|
172
|
+
const listBranches = async (top) => {
|
|
177
173
|
const args = ['for-each-ref', `--format=${BRANCH_FORMAT}`, 'refs/heads'];
|
|
178
|
-
const result = requireOk(runGit(args, top), 'branch failed');
|
|
174
|
+
const result = requireOk(await runGit(args, top), 'branch failed');
|
|
179
175
|
const lines = result.stdout.split('\n').filter(Boolean);
|
|
180
176
|
const branches = lines.map((line) => parseBranchLine(line)).filter(Boolean);
|
|
181
177
|
const names = new Set(branches.map((entry) => entry.name));
|
|
182
|
-
const primary = defaultBranch(top, names);
|
|
178
|
+
const primary = await defaultBranch(top, names);
|
|
183
179
|
return branches.map((entry) => ({
|
|
184
180
|
...entry,
|
|
185
181
|
isDefault: entry.name === primary,
|
|
186
182
|
}));
|
|
187
183
|
};
|
|
188
184
|
|
|
189
|
-
const hasStaged = (top) => {
|
|
190
|
-
const result = runGit(['diff', '--cached', '--quiet'], top);
|
|
185
|
+
const hasStaged = async (top) => {
|
|
186
|
+
const result = await runGit(['diff', '--cached', '--quiet'], top);
|
|
191
187
|
return result.status === 1;
|
|
192
188
|
};
|
|
193
189
|
|
|
@@ -243,6 +239,24 @@ const commitOp = gitOp(function* (kind, message) {
|
|
|
243
239
|
requireOk(result);
|
|
244
240
|
});
|
|
245
241
|
|
|
242
|
+
const updateOp = gitOp(function* (sha) {
|
|
243
|
+
const commit = yield* resolveCommit(required(sha, 'empty commit'));
|
|
244
|
+
const head = yield* resolveCommit('HEAD');
|
|
245
|
+
if (commit === head) {
|
|
246
|
+
const result = yield command(['commit', '--amend', '--no-edit']);
|
|
247
|
+
return void requireOk(result);
|
|
248
|
+
}
|
|
249
|
+
const fixed = yield command(['commit', '--fixup', commit]);
|
|
250
|
+
requireOk(fixed);
|
|
251
|
+
const range = yield* rebaseRange(commit);
|
|
252
|
+
try {
|
|
253
|
+
yield* rebase([...AUTOSQUASH_ARGS, ...range]);
|
|
254
|
+
} catch (error) {
|
|
255
|
+
yield command(['reset', '--soft', 'HEAD~1']);
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
246
260
|
const dropCommitOp = gitOp(function* (sha) {
|
|
247
261
|
const target = yield* resolveCommit(required(sha, 'empty commit'));
|
|
248
262
|
const parent = yield command(['rev-parse', '--verify', `${target}^`]);
|
|
@@ -363,24 +377,15 @@ module.exports = {
|
|
|
363
377
|
listCommits,
|
|
364
378
|
listBranches,
|
|
365
379
|
hasStaged,
|
|
366
|
-
checkoutBranch: checkoutOp
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
applyFixupAsync: fixupOp.async,
|
|
378
|
-
rewordCommit: rewordOp.sync,
|
|
379
|
-
rewordCommitAsync: rewordOp.async,
|
|
380
|
-
pullChanges: pullOp.sync,
|
|
381
|
-
pullChangesAsync: pullOp.async,
|
|
382
|
-
pushChanges: pushOp.sync,
|
|
383
|
-
pushChangesAsync: pushOp.async,
|
|
384
|
-
commitChanges: commitOp.sync,
|
|
385
|
-
commitChangesAsync: commitOp.async,
|
|
380
|
+
checkoutBranch: checkoutOp,
|
|
381
|
+
createBranch: createOp,
|
|
382
|
+
rebaseBranch: rebaseOp,
|
|
383
|
+
dropBranch: dropBranchOp,
|
|
384
|
+
dropCommit: dropCommitOp,
|
|
385
|
+
applyFixup: fixupOp,
|
|
386
|
+
rewordCommit: rewordOp,
|
|
387
|
+
pullChanges: pullOp,
|
|
388
|
+
pushChanges: pushOp,
|
|
389
|
+
commitChanges: commitOp,
|
|
390
|
+
updateCommit: updateOp,
|
|
386
391
|
};
|