reslop 0.1.9 → 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 +12 -1
- package/README.md +2 -1
- package/bin/reslop.js +2 -2
- package/lib/ansi.js +4 -2
- package/lib/api.js +2 -2
- package/lib/capabilities.js +7 -14
- package/lib/cli.js +28 -47
- package/lib/clipboard.js +1 -1
- package/lib/{deps/changes.js → deps-diff.js} +309 -19
- package/lib/deps.js +498 -29
- 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 +5 -8
- package/lib/{git/branches.js → git-branches.js} +6 -5
- package/lib/{git/dependencies.js → git-deps.js} +111 -38
- package/lib/git.js +589 -68
- 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 +14 -8
- package/lib/manifest.js +330 -0
- package/lib/remote.js +374 -0
- package/lib/render/branches.js +14 -68
- package/lib/render/chrome.js +24 -9
- package/lib/render/commits.js +6 -59
- package/lib/render/diff.js +16 -16
- package/lib/render/files.js +6 -34
- package/lib/render/frame.js +23 -12
- package/lib/render/notes.js +4 -3
- package/lib/render/primitives.js +45 -0
- package/lib/{render.js → render/render.js} +5 -5
- 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 +32 -16
- package/lib/session/branches.js +116 -128
- package/lib/session/change-actions.js +202 -123
- package/lib/session/commit.js +105 -112
- package/lib/session/compose.js +158 -13
- package/lib/session/dispatch.js +104 -60
- package/lib/session/files-pane.js +142 -148
- package/lib/session/items.js +22 -30
- package/lib/session/lifecycle.js +44 -44
- package/lib/session/load.js +19 -33
- package/lib/session/navigation.js +12 -1
- package/lib/session/ops.js +28 -41
- package/lib/session/pointer.js +54 -57
- 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 +78 -9
- package/lib/session/watch.js +11 -19
- package/lib/session.js +21 -246
- 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 +1 -1
- package/lib/deps/items.js +0 -134
- package/lib/deps/manifest.js +0 -152
- 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 -176
- 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/select.js
CHANGED
|
@@ -145,8 +145,6 @@ const parseCells = (line) => {
|
|
|
145
145
|
|
|
146
146
|
const rgbKey = (rgb) => (rgb ? `${rgb[0]},${rgb[1]},${rgb[2]}` : '');
|
|
147
147
|
|
|
148
|
-
const styleKey = (fg, bg) => `${rgbKey(fg)}|${rgbKey(bg)}`;
|
|
149
|
-
|
|
150
148
|
const styleSeq = (fg, bg) => {
|
|
151
149
|
if (fg && bg) return RESET + seq(fg, bg);
|
|
152
150
|
if (fg) return RESET + ansi.fg(fg);
|
|
@@ -169,7 +167,7 @@ const overlayRange = (line, fromCol, toCol) => {
|
|
|
169
167
|
fg = cell.bg ?? THEME.ctxBg;
|
|
170
168
|
bg = cell.fg ?? THEME.ctxFg;
|
|
171
169
|
}
|
|
172
|
-
const key =
|
|
170
|
+
const key = `${rgbKey(fg)}|${rgbKey(bg)}`;
|
|
173
171
|
if (key !== last) {
|
|
174
172
|
out += styleSeq(fg, bg);
|
|
175
173
|
last = key;
|
|
@@ -181,14 +179,11 @@ const overlayRange = (line, fromCol, toCol) => {
|
|
|
181
179
|
|
|
182
180
|
const overlayRows = (rows, sel) => {
|
|
183
181
|
if (!isRange(sel)) return rows;
|
|
184
|
-
const
|
|
185
|
-
|
|
182
|
+
const { length } = rows;
|
|
183
|
+
const next = new Array(length);
|
|
184
|
+
for (let i = 0; i < length; i++) {
|
|
186
185
|
const range = lineRange(i, sel);
|
|
187
|
-
|
|
188
|
-
next.push(rows[i]);
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
next.push(overlayRange(rows[i], range.from, range.to));
|
|
186
|
+
next[i] = range ? overlayRange(rows[i], range.from, range.to) : rows[i];
|
|
192
187
|
}
|
|
193
188
|
return next;
|
|
194
189
|
};
|
package/lib/session/accessors.js
CHANGED
|
@@ -22,4 +22,12 @@ const bindGetters = (target, owner, names) => {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
const stateView = (state, methods, writable = [], readonly = []) => {
|
|
26
|
+
const descriptors = Object.getOwnPropertyDescriptors(methods);
|
|
27
|
+
const view = Object.defineProperties({}, descriptors);
|
|
28
|
+
bindAccessors(view, state, writable);
|
|
29
|
+
bindGetters(view, state, readonly);
|
|
30
|
+
return view;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
module.exports = { bindAccessors, bindGetters, bindAlias, stateView };
|
package/lib/session/actions.js
CHANGED
|
@@ -12,6 +12,8 @@ const ACTIONS = {
|
|
|
12
12
|
todo: ['t'],
|
|
13
13
|
code: ['e'],
|
|
14
14
|
branch: ['b'],
|
|
15
|
+
file: ['f'],
|
|
16
|
+
diff: ['d'],
|
|
15
17
|
quit: ['q', 'ctrl-c'],
|
|
16
18
|
};
|
|
17
19
|
const ACTION_IDS = Object.keys(ACTIONS);
|
|
@@ -28,6 +30,8 @@ const COMMIT_ACTIONS = {
|
|
|
28
30
|
amend: ['a'],
|
|
29
31
|
fixup: ['f'],
|
|
30
32
|
drop: ['d'],
|
|
33
|
+
pull: ['p'],
|
|
34
|
+
push: ['s'],
|
|
31
35
|
};
|
|
32
36
|
|
|
33
37
|
const ACTION_HOT = {
|
|
@@ -45,9 +49,17 @@ const ACTION_LABEL = {
|
|
|
45
49
|
next: '→',
|
|
46
50
|
};
|
|
47
51
|
|
|
48
|
-
const DIFF_DISABLED = ['commit', 'branch', 'pull', 'push'];
|
|
52
|
+
const DIFF_DISABLED = ['commit', 'branch', 'pull', 'push', 'file', 'diff'];
|
|
53
|
+
const UNIT_DISABLED = [...DIFF_DISABLED, 'layout'];
|
|
49
54
|
const FILES_DISABLED = ['layout', 'feedback', 'code'];
|
|
50
|
-
const FILES_HIDDEN = [
|
|
55
|
+
const FILES_HIDDEN = [
|
|
56
|
+
...FILES_DISABLED,
|
|
57
|
+
'prev',
|
|
58
|
+
'next',
|
|
59
|
+
'commit',
|
|
60
|
+
'file',
|
|
61
|
+
'diff',
|
|
62
|
+
];
|
|
51
63
|
const FILES_GIT_DISABLED = ['add', 'unstage', 'revert'];
|
|
52
64
|
const FILES_TODO_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
|
|
53
65
|
const TODO_DISABLED = [
|
|
@@ -60,6 +72,8 @@ const TODO_DISABLED = [
|
|
|
60
72
|
'todo',
|
|
61
73
|
'code',
|
|
62
74
|
'branch',
|
|
75
|
+
'file',
|
|
76
|
+
'diff',
|
|
63
77
|
'pull',
|
|
64
78
|
'push',
|
|
65
79
|
];
|
|
@@ -73,6 +87,8 @@ const BRANCHES_DISABLED = [
|
|
|
73
87
|
'todo',
|
|
74
88
|
'code',
|
|
75
89
|
'branch',
|
|
90
|
+
'file',
|
|
91
|
+
'diff',
|
|
76
92
|
'prev',
|
|
77
93
|
'next',
|
|
78
94
|
];
|
|
@@ -85,10 +101,10 @@ const COMMITS_DISABLED = [
|
|
|
85
101
|
'todo',
|
|
86
102
|
'code',
|
|
87
103
|
'branch',
|
|
104
|
+
'file',
|
|
105
|
+
'diff',
|
|
88
106
|
'prev',
|
|
89
107
|
'next',
|
|
90
|
-
'pull',
|
|
91
|
-
'push',
|
|
92
108
|
];
|
|
93
109
|
|
|
94
110
|
const isTodosTarget = (item) =>
|
|
@@ -122,6 +138,7 @@ const commitGitDisabled = (item) => {
|
|
|
122
138
|
const disabledActions = (pane, item) => {
|
|
123
139
|
const onTodos = isTodosTarget(item);
|
|
124
140
|
if (pane === 'files') return onTodos ? FILES_TODO_DISABLED : FILES_DISABLED;
|
|
141
|
+
if (pane === 'unit') return [...UNIT_DISABLED, ...diffGitDisabled(item)];
|
|
125
142
|
if (pane === 'branches') {
|
|
126
143
|
return [...BRANCHES_DISABLED, ...branchGitDisabled(item)];
|
|
127
144
|
}
|
|
@@ -151,11 +168,9 @@ const SCROLL = {
|
|
|
151
168
|
};
|
|
152
169
|
|
|
153
170
|
const KEY_TO_ACTION = {};
|
|
154
|
-
const PANE_ONLY = ['branch'];
|
|
171
|
+
const PANE_ONLY = ['branch', 'file', 'diff'];
|
|
155
172
|
const FILES_KEYS = {};
|
|
156
|
-
for (const
|
|
157
|
-
for (const key of ACTIONS[id]) FILES_KEYS[key] = id;
|
|
158
|
-
}
|
|
173
|
+
for (const key of ACTIONS.branch) FILES_KEYS[key] = 'branch';
|
|
159
174
|
for (const id of BRANCH_REMOTE) {
|
|
160
175
|
for (const key of BRANCH_ACTIONS[id]) FILES_KEYS[key] = id;
|
|
161
176
|
}
|
|
@@ -180,12 +195,16 @@ for (const id of ACTION_IDS) {
|
|
|
180
195
|
|
|
181
196
|
for (const key of Object.keys(SCROLL)) KEY_TO_ACTION[key] = SCROLL[key];
|
|
182
197
|
|
|
183
|
-
const actionFromKey = (key, pane) => {
|
|
198
|
+
const actionFromKey = (key, pane, fileScope) => {
|
|
184
199
|
const listPane =
|
|
185
200
|
pane === 'files' || pane === 'branches' || pane === 'commits';
|
|
186
201
|
if (listPane && (key === 'left' || key === 'right')) return null;
|
|
187
202
|
const paneKeys = PANE_KEYS[pane];
|
|
188
203
|
if (paneKeys && paneKeys[key]) return paneKeys[key];
|
|
204
|
+
if (pane === 'files') {
|
|
205
|
+
if (key === 'f' && fileScope !== 'file') return 'file';
|
|
206
|
+
if (key === 'd' && fileScope === 'file') return 'diff';
|
|
207
|
+
}
|
|
189
208
|
return KEY_TO_ACTION[key] ?? null;
|
|
190
209
|
};
|
|
191
210
|
|
|
@@ -194,12 +213,10 @@ const actionKeys = (id) =>
|
|
|
194
213
|
|
|
195
214
|
const actionHot = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
|
|
196
215
|
|
|
197
|
-
const actionLabel = (id) => ACTION_LABEL[id] ?? ACTION_HOT[id] ?? id;
|
|
198
|
-
|
|
199
216
|
const actionLetter = actionHot;
|
|
200
217
|
|
|
201
218
|
const buttonWord = (id) => {
|
|
202
|
-
const word =
|
|
219
|
+
const word = ACTION_LABEL[id] ?? ACTION_HOT[id] ?? id;
|
|
203
220
|
const mark = actionLetter(id);
|
|
204
221
|
if (word.includes(mark)) return word;
|
|
205
222
|
return `${mark}${word}`;
|
|
@@ -257,13 +274,11 @@ const CONFIRM = {
|
|
|
257
274
|
|
|
258
275
|
const CONFIRM_MODE = Object.keys(CONFIRM);
|
|
259
276
|
|
|
260
|
-
const normalizeConfirmKey = (key) =>
|
|
261
|
-
key.length === 1 ? key.toLowerCase() : key;
|
|
262
|
-
|
|
263
277
|
const confirmKey = (mode, key) => {
|
|
264
278
|
const spec = CONFIRM[mode];
|
|
265
279
|
if (!spec) return null;
|
|
266
|
-
|
|
280
|
+
const norm = key.length === 1 ? key.toLowerCase() : key;
|
|
281
|
+
return spec.keys[norm] ?? null;
|
|
267
282
|
};
|
|
268
283
|
|
|
269
284
|
const applyConfirm = (mode, key, handlers) => {
|
|
@@ -289,6 +304,7 @@ module.exports = {
|
|
|
289
304
|
ACTION_HOT,
|
|
290
305
|
ACTION_LABEL,
|
|
291
306
|
DIFF_DISABLED,
|
|
307
|
+
UNIT_DISABLED,
|
|
292
308
|
FILES_DISABLED,
|
|
293
309
|
FILES_HIDDEN,
|
|
294
310
|
FILES_GIT_DISABLED,
|
package/lib/session/branches.js
CHANGED
|
@@ -1,261 +1,257 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { stateView } = require('./accessors.js');
|
|
4
|
+
|
|
3
5
|
const { pickRepoWrite } = require('./ops.js');
|
|
4
6
|
|
|
5
7
|
const selectedBranch = (api) => {
|
|
6
|
-
const cursor = api.
|
|
8
|
+
const cursor = api.ui.nav.branchCursor;
|
|
7
9
|
return api.state.branches[cursor];
|
|
8
10
|
};
|
|
9
11
|
|
|
10
12
|
const refreshBranchList = (api) => {
|
|
11
|
-
const repo = api.
|
|
13
|
+
const repo = api.ui.repo;
|
|
12
14
|
if (!repo.listBranches) return;
|
|
13
15
|
try {
|
|
14
|
-
api.state.branches = repo.listBranches(api.
|
|
16
|
+
api.state.branches = repo.listBranches(api.ui.top);
|
|
15
17
|
} catch (error) {
|
|
16
|
-
api.
|
|
18
|
+
api.ui.status = error.message;
|
|
17
19
|
return;
|
|
18
20
|
}
|
|
19
21
|
const last = api.state.branches.length - 1;
|
|
20
|
-
const nav = api.
|
|
22
|
+
const nav = api.ui.nav;
|
|
21
23
|
if (nav.branchCursor > last) nav.branchCursor = Math.max(0, last);
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
const refreshAfterWrite = (api, extra = {}) => {
|
|
25
27
|
refreshBranchList(api);
|
|
26
|
-
api.
|
|
28
|
+
api.ui.commits.refresh();
|
|
29
|
+
api.ui.refreshFromRepo({ keepEmpty: true, ...extra });
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
const onBranch = (api) => {
|
|
30
|
-
if (api.
|
|
31
|
-
if (!api.
|
|
32
|
-
const repo = api.
|
|
33
|
-
const caps = api.
|
|
33
|
+
if (api.ui.mode === 'compose') return;
|
|
34
|
+
if (!api.ui.commits.canCommit()) return;
|
|
35
|
+
const repo = api.ui.repo;
|
|
36
|
+
const caps = api.ui.capabilities;
|
|
34
37
|
if (!caps.branches || !repo.listBranches) {
|
|
35
|
-
api.
|
|
38
|
+
api.ui.status = 'read only';
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
41
|
try {
|
|
39
|
-
api.state.branches = repo.listBranches(api.
|
|
42
|
+
api.state.branches = repo.listBranches(api.ui.top);
|
|
40
43
|
} catch (error) {
|
|
41
|
-
api.
|
|
44
|
+
api.ui.status = error.message;
|
|
42
45
|
return;
|
|
43
46
|
}
|
|
44
47
|
const current = api.state.branches.findIndex((entry) => entry.current);
|
|
45
|
-
api.
|
|
46
|
-
api.
|
|
47
|
-
api.
|
|
48
|
-
api.
|
|
48
|
+
api.ui.nav.branchCursor = current < 0 ? 0 : current;
|
|
49
|
+
api.ui.nav.pane = 'branches';
|
|
50
|
+
api.ui.status = '';
|
|
51
|
+
api.ui.nav.clearSelection();
|
|
49
52
|
};
|
|
50
53
|
|
|
51
54
|
const onBranchMove = (api, delta) => {
|
|
52
55
|
const branches = api.state.branches;
|
|
53
56
|
if (!branches.length) {
|
|
54
|
-
api.
|
|
57
|
+
api.ui.status = 'nothing to review';
|
|
55
58
|
return;
|
|
56
59
|
}
|
|
57
60
|
const next = Math.min(
|
|
58
61
|
branches.length - 1,
|
|
59
|
-
Math.max(0, api.
|
|
62
|
+
Math.max(0, api.ui.nav.branchCursor + delta),
|
|
60
63
|
);
|
|
61
|
-
if (next === api.
|
|
62
|
-
api.
|
|
63
|
-
api.
|
|
64
|
+
if (next === api.ui.nav.branchCursor) return;
|
|
65
|
+
api.ui.nav.branchCursor = next;
|
|
66
|
+
api.ui.status = '';
|
|
64
67
|
};
|
|
65
68
|
|
|
66
69
|
const checkoutAsync = (api, name, done, write) => {
|
|
67
|
-
api.
|
|
70
|
+
api.ui.showFiles();
|
|
68
71
|
const run = (top) => write(top, name);
|
|
69
72
|
const after = () =>
|
|
70
|
-
api.
|
|
71
|
-
return void api.
|
|
73
|
+
api.ui.refreshFromRepo({ keepEmpty: true, doneStatus: done });
|
|
74
|
+
return void api.ui.ops.runBusy('checking out', done, run, after);
|
|
72
75
|
};
|
|
73
76
|
|
|
74
77
|
const onCheckoutBranch = (api) => {
|
|
75
|
-
if (!api.
|
|
78
|
+
if (!api.ui.commits.canCommit()) return;
|
|
76
79
|
const entry = selectedBranch(api);
|
|
77
80
|
if (!entry) return;
|
|
78
|
-
if (entry.current)
|
|
79
|
-
api.options.showFiles();
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
81
|
+
if (entry.current) return void api.ui.showFiles();
|
|
82
82
|
const name = entry.name;
|
|
83
83
|
const done = `checked out ${name}`;
|
|
84
|
-
const uiOpen = api.
|
|
85
|
-
const picked = pickRepoWrite(api.
|
|
84
|
+
const uiOpen = api.ui.uiOpen;
|
|
85
|
+
const picked = pickRepoWrite(api.ui.repo, 'checkout', uiOpen);
|
|
86
86
|
if (picked.async) {
|
|
87
|
-
checkoutAsync(api, name, done, picked.write);
|
|
88
|
-
return;
|
|
87
|
+
return void checkoutAsync(api, name, done, picked.write);
|
|
89
88
|
}
|
|
90
|
-
const ok = api.
|
|
91
|
-
api.
|
|
89
|
+
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
90
|
+
api.ui.repo.checkout(top, name);
|
|
92
91
|
});
|
|
93
92
|
if (!ok) return;
|
|
94
|
-
api.
|
|
95
|
-
api.
|
|
96
|
-
if (!api.
|
|
93
|
+
api.ui.showFiles();
|
|
94
|
+
api.ui.refreshFromRepo({ keepEmpty: true });
|
|
95
|
+
if (!api.ui.status) api.ui.status = done;
|
|
97
96
|
};
|
|
98
97
|
|
|
99
98
|
const rebaseAsync = (api, onto, done, write) => {
|
|
100
99
|
const run = (top) => write(top, onto);
|
|
101
100
|
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
102
|
-
return void api.
|
|
101
|
+
return void api.ui.ops.runBusy('rebasing', done, run, after);
|
|
103
102
|
};
|
|
104
103
|
|
|
105
104
|
const onRebaseBranch = (api) => {
|
|
106
|
-
if (api.
|
|
107
|
-
if (!api.
|
|
105
|
+
if (api.ui.nav.pane !== 'branches') return;
|
|
106
|
+
if (!api.ui.commits.canCommit()) return;
|
|
108
107
|
const entry = selectedBranch(api);
|
|
109
108
|
if (!entry || entry.current) return;
|
|
110
109
|
const onto = entry.name;
|
|
111
110
|
const done = `rebased onto ${onto}`;
|
|
112
|
-
const uiOpen = api.
|
|
113
|
-
const picked = pickRepoWrite(api.
|
|
111
|
+
const uiOpen = api.ui.uiOpen;
|
|
112
|
+
const picked = pickRepoWrite(api.ui.repo, 'rebase', uiOpen);
|
|
114
113
|
if (picked.async) {
|
|
115
|
-
rebaseAsync(api, onto, done, picked.write);
|
|
116
|
-
return;
|
|
114
|
+
return void rebaseAsync(api, onto, done, picked.write);
|
|
117
115
|
}
|
|
118
|
-
const ok = api.
|
|
119
|
-
api.
|
|
116
|
+
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
117
|
+
api.ui.repo.rebase(top, onto);
|
|
120
118
|
});
|
|
121
119
|
if (!ok) return;
|
|
122
120
|
refreshAfterWrite(api);
|
|
123
|
-
if (!api.
|
|
121
|
+
if (!api.ui.status) api.ui.status = done;
|
|
124
122
|
};
|
|
125
123
|
|
|
126
124
|
const onDropBranch = (api) => {
|
|
127
|
-
if (api.
|
|
128
|
-
if (!api.
|
|
125
|
+
if (api.ui.nav.pane !== 'branches') return;
|
|
126
|
+
if (!api.ui.commits.canCommit()) return;
|
|
129
127
|
const entry = selectedBranch(api);
|
|
130
128
|
if (!entry || entry.current) return;
|
|
131
129
|
api.state.dropName = entry.name;
|
|
132
|
-
api.
|
|
133
|
-
api.
|
|
130
|
+
api.ui.mode = 'confirmDrop';
|
|
131
|
+
api.ui.status = '';
|
|
134
132
|
};
|
|
135
133
|
|
|
136
134
|
const cancelDropBranch = (api) => {
|
|
137
|
-
api.
|
|
135
|
+
api.ui.mode = 'review';
|
|
138
136
|
api.state.dropName = '';
|
|
139
|
-
api.
|
|
137
|
+
api.ui.status = '';
|
|
140
138
|
};
|
|
141
139
|
|
|
142
140
|
const dropAsync = (api, name, done, write) => {
|
|
143
141
|
const run = (top) => write(top, name);
|
|
144
142
|
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
145
|
-
return void api.
|
|
143
|
+
return void api.ui.ops.runBusy('dropping', done, run, after);
|
|
146
144
|
};
|
|
147
145
|
|
|
148
146
|
const confirmDropBranch = (api) => {
|
|
149
147
|
const name = api.state.dropName;
|
|
150
|
-
api.
|
|
148
|
+
api.ui.mode = 'review';
|
|
151
149
|
api.state.dropName = '';
|
|
152
150
|
if (!name) return;
|
|
153
151
|
const done = `dropped ${name}`;
|
|
154
|
-
const uiOpen = api.
|
|
155
|
-
const picked = pickRepoWrite(api.
|
|
152
|
+
const uiOpen = api.ui.uiOpen;
|
|
153
|
+
const picked = pickRepoWrite(api.ui.repo, 'drop', uiOpen);
|
|
156
154
|
if (picked.async) {
|
|
157
|
-
dropAsync(api, name, done, picked.write);
|
|
158
|
-
return;
|
|
155
|
+
return void dropAsync(api, name, done, picked.write);
|
|
159
156
|
}
|
|
160
|
-
const ok = api.
|
|
161
|
-
api.
|
|
157
|
+
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
158
|
+
api.ui.repo.drop(top, name);
|
|
162
159
|
});
|
|
163
160
|
if (!ok) return;
|
|
164
161
|
refreshAfterWrite(api);
|
|
165
|
-
if (!api.
|
|
162
|
+
if (!api.ui.status) api.ui.status = done;
|
|
166
163
|
};
|
|
167
164
|
|
|
168
165
|
const onNewBranch = (api) => {
|
|
169
|
-
if (api.
|
|
170
|
-
if (!api.
|
|
171
|
-
api.
|
|
166
|
+
if (api.ui.nav.pane !== 'branches') return;
|
|
167
|
+
if (!api.ui.commits.canCommit()) return;
|
|
168
|
+
api.ui.composer.openCompose('branch', '');
|
|
172
169
|
};
|
|
173
170
|
|
|
174
171
|
const createAsync = (api, name, done, write) => {
|
|
175
|
-
api.
|
|
176
|
-
api.
|
|
172
|
+
api.ui.composer.closeCompose();
|
|
173
|
+
api.ui.showFiles();
|
|
177
174
|
const run = (top) => write(top, name);
|
|
178
175
|
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
179
|
-
return void api.
|
|
176
|
+
return void api.ui.ops.runBusy('creating branch', done, run, after);
|
|
180
177
|
};
|
|
181
178
|
|
|
182
179
|
const finishCreateBranch = (api) => {
|
|
183
|
-
const editor = api.
|
|
180
|
+
const editor = api.ui.composer.state.editor;
|
|
184
181
|
const name = editor ? editor.text.trim() : '';
|
|
185
182
|
if (!name) {
|
|
186
|
-
api.
|
|
183
|
+
api.ui.status = 'empty branch name';
|
|
187
184
|
return;
|
|
188
185
|
}
|
|
189
186
|
const done = `created ${name}`;
|
|
190
|
-
const uiOpen = api.
|
|
191
|
-
const picked = pickRepoWrite(api.
|
|
187
|
+
const uiOpen = api.ui.uiOpen;
|
|
188
|
+
const picked = pickRepoWrite(api.ui.repo, 'createBranch', uiOpen);
|
|
192
189
|
if (picked.async) {
|
|
193
|
-
createAsync(api, name, done, picked.write);
|
|
194
|
-
return;
|
|
190
|
+
return void createAsync(api, name, done, picked.write);
|
|
195
191
|
}
|
|
196
|
-
const ok = api.
|
|
197
|
-
api.
|
|
192
|
+
const ok = api.ui.ops.runRepo(done, (top) => {
|
|
193
|
+
api.ui.repo.createBranch(top, name);
|
|
198
194
|
});
|
|
199
195
|
if (!ok) return;
|
|
200
|
-
api.
|
|
201
|
-
api.
|
|
196
|
+
api.ui.composer.closeCompose();
|
|
197
|
+
api.ui.showFiles();
|
|
202
198
|
refreshAfterWrite(api);
|
|
203
|
-
if (!api.
|
|
199
|
+
if (!api.ui.status) api.ui.status = done;
|
|
204
200
|
};
|
|
205
201
|
|
|
206
202
|
const onPull = (api) => {
|
|
207
|
-
if (!api.
|
|
208
|
-
const repo = api.
|
|
209
|
-
const picked = pickRepoWrite(repo, 'pull', api.
|
|
203
|
+
if (!api.ui.commits.canCommit()) return;
|
|
204
|
+
const repo = api.ui.repo;
|
|
205
|
+
const picked = pickRepoWrite(repo, 'pull', api.ui.uiOpen);
|
|
210
206
|
if (picked.async) {
|
|
211
207
|
const after = () => refreshAfterWrite(api);
|
|
212
208
|
const write = (top) => picked.write(top);
|
|
213
|
-
return void api.
|
|
209
|
+
return void api.ui.ops.runBusy('pulling', 'pulled', write, after);
|
|
214
210
|
}
|
|
215
|
-
const ok = api.
|
|
211
|
+
const ok = api.ui.ops.runRepo('pulled', (top) => {
|
|
216
212
|
repo.pull(top);
|
|
217
213
|
});
|
|
218
214
|
if (!ok) return;
|
|
219
215
|
refreshAfterWrite(api);
|
|
220
|
-
if (!api.
|
|
216
|
+
if (!api.ui.status) api.ui.status = 'pulled';
|
|
221
217
|
};
|
|
222
218
|
|
|
223
219
|
const startPush = (api, force) => {
|
|
224
|
-
if (!api.
|
|
220
|
+
if (!api.ui.commits.canCommit()) return;
|
|
225
221
|
const done = force ? 'force pushed' : 'pushed';
|
|
226
222
|
const kind = force ? 'force pushing' : 'pushing';
|
|
227
|
-
const repo = api.
|
|
228
|
-
const picked = pickRepoWrite(repo, 'push', api.
|
|
223
|
+
const repo = api.ui.repo;
|
|
224
|
+
const picked = pickRepoWrite(repo, 'push', api.ui.uiOpen);
|
|
229
225
|
if (picked.async) {
|
|
230
226
|
const write = (top) => picked.write(top, force);
|
|
231
227
|
const after = () => refreshAfterWrite(api);
|
|
232
|
-
return void api.
|
|
228
|
+
return void api.ui.ops.runBusy(kind, done, write, after);
|
|
233
229
|
}
|
|
234
230
|
try {
|
|
235
|
-
repo.push(api.
|
|
231
|
+
repo.push(api.ui.top, force);
|
|
236
232
|
} catch (error) {
|
|
237
233
|
if (error.rejected && !force) {
|
|
238
|
-
api.
|
|
239
|
-
api.
|
|
234
|
+
api.ui.mode = 'confirmPush';
|
|
235
|
+
api.ui.status = '';
|
|
240
236
|
return;
|
|
241
237
|
}
|
|
242
|
-
api.
|
|
238
|
+
api.ui.status = error.message;
|
|
243
239
|
return;
|
|
244
240
|
}
|
|
245
241
|
refreshAfterWrite(api);
|
|
246
|
-
api.
|
|
242
|
+
api.ui.status = done;
|
|
247
243
|
};
|
|
248
244
|
|
|
249
245
|
const onPush = (api) => startPush(api, false);
|
|
250
246
|
|
|
251
247
|
const onForcePush = (api) => {
|
|
252
|
-
api.
|
|
248
|
+
api.ui.mode = 'review';
|
|
253
249
|
startPush(api, true);
|
|
254
250
|
};
|
|
255
251
|
|
|
256
252
|
const cancelPush = (api) => {
|
|
257
|
-
api.
|
|
258
|
-
api.
|
|
253
|
+
api.ui.mode = 'review';
|
|
254
|
+
api.ui.status = '';
|
|
259
255
|
};
|
|
260
256
|
|
|
261
257
|
const reset = (state) => {
|
|
@@ -263,40 +259,32 @@ const reset = (state) => {
|
|
|
263
259
|
state.dropName = '';
|
|
264
260
|
};
|
|
265
261
|
|
|
266
|
-
const createBranchController = (
|
|
262
|
+
const createBranchController = (ui) => {
|
|
267
263
|
const state = {
|
|
268
264
|
branches: [],
|
|
269
265
|
dropName: '',
|
|
270
266
|
};
|
|
271
|
-
const api = {
|
|
272
|
-
return
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
267
|
+
const api = { ui, state };
|
|
268
|
+
return stateView(
|
|
269
|
+
state,
|
|
270
|
+
{
|
|
271
|
+
reset: () => reset(state),
|
|
272
|
+
onBranch: () => onBranch(api),
|
|
273
|
+
onBranchMove: (delta) => onBranchMove(api, delta),
|
|
274
|
+
onCheckoutBranch: () => onCheckoutBranch(api),
|
|
275
|
+
onRebaseBranch: () => onRebaseBranch(api),
|
|
276
|
+
onDropBranch: () => onDropBranch(api),
|
|
277
|
+
cancelDropBranch: () => cancelDropBranch(api),
|
|
278
|
+
confirmDropBranch: () => confirmDropBranch(api),
|
|
279
|
+
onNewBranch: () => onNewBranch(api),
|
|
280
|
+
finishCreateBranch: () => finishCreateBranch(api),
|
|
281
|
+
onPull: () => onPull(api),
|
|
282
|
+
onPush: () => onPush(api),
|
|
283
|
+
onForcePush: () => onForcePush(api),
|
|
284
|
+
cancelPush: () => cancelPush(api),
|
|
281
285
|
},
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
},
|
|
285
|
-
reset: () => reset(state),
|
|
286
|
-
onBranch: () => onBranch(api),
|
|
287
|
-
onBranchMove: (delta) => onBranchMove(api, delta),
|
|
288
|
-
onCheckoutBranch: () => onCheckoutBranch(api),
|
|
289
|
-
onRebaseBranch: () => onRebaseBranch(api),
|
|
290
|
-
onDropBranch: () => onDropBranch(api),
|
|
291
|
-
cancelDropBranch: () => cancelDropBranch(api),
|
|
292
|
-
confirmDropBranch: () => confirmDropBranch(api),
|
|
293
|
-
onNewBranch: () => onNewBranch(api),
|
|
294
|
-
finishCreateBranch: () => finishCreateBranch(api),
|
|
295
|
-
onPull: () => onPull(api),
|
|
296
|
-
onPush: () => onPush(api),
|
|
297
|
-
onForcePush: () => onForcePush(api),
|
|
298
|
-
cancelPush: () => cancelPush(api),
|
|
299
|
-
};
|
|
286
|
+
['branches', 'dropName'],
|
|
287
|
+
);
|
|
300
288
|
};
|
|
301
289
|
|
|
302
290
|
module.exports = { createBranchController };
|