reslop 0.1.8 → 0.1.9
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 +14 -1
- package/README.md +26 -38
- package/lib/ansi.js +2 -0
- package/lib/capabilities.js +3 -0
- package/lib/deps/changes.js +92 -1
- package/lib/deps/items.js +5 -2
- package/lib/deps/manifest.js +7 -0
- package/lib/deps/rows.js +0 -1
- package/lib/deps.js +65 -10
- package/lib/files.js +30 -1
- package/lib/git/branches.js +97 -5
- package/lib/git.js +6 -0
- package/lib/keys.js +9 -2
- package/lib/render/branches.js +39 -17
- package/lib/render/chrome.js +35 -15
- package/lib/render/commits.js +138 -0
- package/lib/render/files.js +30 -10
- package/lib/render/frame.js +6 -1
- package/lib/render/primitives.js +1 -1
- package/lib/render.js +1 -2
- package/lib/session/actions.js +65 -24
- package/lib/session/branches.js +16 -18
- package/lib/session/change-actions.js +8 -5
- package/lib/session/commit.js +191 -29
- package/lib/session/dispatch.js +12 -2
- package/lib/session/files-pane.js +10 -1
- package/lib/session/items.js +112 -7
- package/lib/session/lifecycle.js +44 -4
- package/lib/session/navigation.js +3 -2
- package/lib/session/pointer.js +7 -0
- package/lib/session/view.js +4 -2
- package/lib/session.js +37 -9
- package/package.json +2 -2
package/lib/session/actions.js
CHANGED
|
@@ -11,10 +11,7 @@ const ACTIONS = {
|
|
|
11
11
|
feedback: ['f'],
|
|
12
12
|
todo: ['t'],
|
|
13
13
|
code: ['e'],
|
|
14
|
-
reload: ['r'],
|
|
15
14
|
branch: ['b'],
|
|
16
|
-
pull: ['p'],
|
|
17
|
-
push: ['s'],
|
|
18
15
|
quit: ['q', 'ctrl-c'],
|
|
19
16
|
};
|
|
20
17
|
const ACTION_IDS = Object.keys(ACTIONS);
|
|
@@ -23,6 +20,14 @@ const BRANCH_ACTIONS = {
|
|
|
23
20
|
newBranch: ['n'],
|
|
24
21
|
rebase: ['r'],
|
|
25
22
|
drop: ['d'],
|
|
23
|
+
pull: ['p'],
|
|
24
|
+
push: ['s'],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const COMMIT_ACTIONS = {
|
|
28
|
+
amend: ['a'],
|
|
29
|
+
fixup: ['f'],
|
|
30
|
+
drop: ['d'],
|
|
26
31
|
};
|
|
27
32
|
|
|
28
33
|
const ACTION_HOT = {
|
|
@@ -40,8 +45,9 @@ const ACTION_LABEL = {
|
|
|
40
45
|
next: '→',
|
|
41
46
|
};
|
|
42
47
|
|
|
43
|
-
const DIFF_DISABLED = ['commit', '
|
|
48
|
+
const DIFF_DISABLED = ['commit', 'branch', 'pull', 'push'];
|
|
44
49
|
const FILES_DISABLED = ['layout', 'feedback', 'code'];
|
|
50
|
+
const FILES_HIDDEN = [...FILES_DISABLED, 'prev', 'next', 'commit'];
|
|
45
51
|
const FILES_GIT_DISABLED = ['add', 'unstage', 'revert'];
|
|
46
52
|
const FILES_TODO_DISABLED = [...FILES_GIT_DISABLED, ...FILES_DISABLED];
|
|
47
53
|
const TODO_DISABLED = [
|
|
@@ -53,7 +59,6 @@ const TODO_DISABLED = [
|
|
|
53
59
|
'feedback',
|
|
54
60
|
'todo',
|
|
55
61
|
'code',
|
|
56
|
-
'reload',
|
|
57
62
|
'branch',
|
|
58
63
|
'pull',
|
|
59
64
|
'push',
|
|
@@ -67,8 +72,21 @@ const BRANCHES_DISABLED = [
|
|
|
67
72
|
'feedback',
|
|
68
73
|
'todo',
|
|
69
74
|
'code',
|
|
70
|
-
'reload',
|
|
71
75
|
'branch',
|
|
76
|
+
'prev',
|
|
77
|
+
'next',
|
|
78
|
+
];
|
|
79
|
+
const COMMITS_DISABLED = [
|
|
80
|
+
'add',
|
|
81
|
+
'unstage',
|
|
82
|
+
'revert',
|
|
83
|
+
'layout',
|
|
84
|
+
'feedback',
|
|
85
|
+
'todo',
|
|
86
|
+
'code',
|
|
87
|
+
'branch',
|
|
88
|
+
'prev',
|
|
89
|
+
'next',
|
|
72
90
|
'pull',
|
|
73
91
|
'push',
|
|
74
92
|
];
|
|
@@ -82,9 +100,23 @@ const diffGitDisabled = (item) => {
|
|
|
82
100
|
return ['unstage'];
|
|
83
101
|
};
|
|
84
102
|
|
|
103
|
+
const BRANCH_REMOTE = ['pull', 'push'];
|
|
104
|
+
|
|
85
105
|
const branchGitDisabled = (item) => {
|
|
86
|
-
|
|
87
|
-
return [
|
|
106
|
+
const off = item && !item.current ? [] : ['rebase', 'drop'];
|
|
107
|
+
if (!item || !item.current) return [...off, ...BRANCH_REMOTE];
|
|
108
|
+
return off;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const commitWriteDisabled = (item) => {
|
|
112
|
+
if (!item || !item.sha) return ['amend', 'fixup', 'drop'];
|
|
113
|
+
return [];
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const commitGitDisabled = (item) => {
|
|
117
|
+
const off = commitWriteDisabled(item);
|
|
118
|
+
if (item && item.canCommit === true) return off;
|
|
119
|
+
return [...off, 'commit', 'fixup'];
|
|
88
120
|
};
|
|
89
121
|
|
|
90
122
|
const disabledActions = (pane, item) => {
|
|
@@ -93,6 +125,9 @@ const disabledActions = (pane, item) => {
|
|
|
93
125
|
if (pane === 'branches') {
|
|
94
126
|
return [...BRANCHES_DISABLED, ...branchGitDisabled(item)];
|
|
95
127
|
}
|
|
128
|
+
if (pane === 'commits') {
|
|
129
|
+
return [...COMMITS_DISABLED, ...commitWriteDisabled(item)];
|
|
130
|
+
}
|
|
96
131
|
if (onTodos) return TODO_DISABLED;
|
|
97
132
|
return [...DIFF_DISABLED, ...diffGitDisabled(item)];
|
|
98
133
|
};
|
|
@@ -116,16 +151,27 @@ const SCROLL = {
|
|
|
116
151
|
};
|
|
117
152
|
|
|
118
153
|
const KEY_TO_ACTION = {};
|
|
119
|
-
const PANE_ONLY = ['branch'
|
|
154
|
+
const PANE_ONLY = ['branch'];
|
|
120
155
|
const FILES_KEYS = {};
|
|
121
156
|
for (const id of PANE_ONLY) {
|
|
122
157
|
for (const key of ACTIONS[id]) FILES_KEYS[key] = id;
|
|
123
158
|
}
|
|
159
|
+
for (const id of BRANCH_REMOTE) {
|
|
160
|
+
for (const key of BRANCH_ACTIONS[id]) FILES_KEYS[key] = id;
|
|
161
|
+
}
|
|
124
162
|
const BRANCH_KEYS = {};
|
|
125
163
|
for (const id of Object.keys(BRANCH_ACTIONS)) {
|
|
126
164
|
for (const key of BRANCH_ACTIONS[id]) BRANCH_KEYS[key] = id;
|
|
127
165
|
}
|
|
128
|
-
const
|
|
166
|
+
const COMMIT_KEYS = {};
|
|
167
|
+
for (const id of Object.keys(COMMIT_ACTIONS)) {
|
|
168
|
+
for (const key of COMMIT_ACTIONS[id]) COMMIT_KEYS[key] = id;
|
|
169
|
+
}
|
|
170
|
+
const PANE_KEYS = {
|
|
171
|
+
files: FILES_KEYS,
|
|
172
|
+
branches: BRANCH_KEYS,
|
|
173
|
+
commits: COMMIT_KEYS,
|
|
174
|
+
};
|
|
129
175
|
|
|
130
176
|
for (const id of ACTION_IDS) {
|
|
131
177
|
if (PANE_ONLY.includes(id)) continue;
|
|
@@ -135,12 +181,16 @@ for (const id of ACTION_IDS) {
|
|
|
135
181
|
for (const key of Object.keys(SCROLL)) KEY_TO_ACTION[key] = SCROLL[key];
|
|
136
182
|
|
|
137
183
|
const actionFromKey = (key, pane) => {
|
|
184
|
+
const listPane =
|
|
185
|
+
pane === 'files' || pane === 'branches' || pane === 'commits';
|
|
186
|
+
if (listPane && (key === 'left' || key === 'right')) return null;
|
|
138
187
|
const paneKeys = PANE_KEYS[pane];
|
|
139
188
|
if (paneKeys && paneKeys[key]) return paneKeys[key];
|
|
140
189
|
return KEY_TO_ACTION[key] ?? null;
|
|
141
190
|
};
|
|
142
191
|
|
|
143
|
-
const actionKeys = (id) =>
|
|
192
|
+
const actionKeys = (id) =>
|
|
193
|
+
ACTIONS[id] ?? BRANCH_ACTIONS[id] ?? COMMIT_ACTIONS[id] ?? [];
|
|
144
194
|
|
|
145
195
|
const actionHot = (id) => ACTION_HOT[id] ?? actionKeys(id)[0];
|
|
146
196
|
|
|
@@ -173,19 +223,6 @@ const CONFIRM = {
|
|
|
173
223
|
escape: 'cancel',
|
|
174
224
|
},
|
|
175
225
|
},
|
|
176
|
-
confirmCommit: {
|
|
177
|
-
choices: [
|
|
178
|
-
{ letter: 'c', label: 'commit', lead: ' ' },
|
|
179
|
-
{ letter: 'a', label: 'amend', lead: ' ' },
|
|
180
|
-
{ letter: 'f', label: 'fixup', lead: ' ' },
|
|
181
|
-
],
|
|
182
|
-
keys: {
|
|
183
|
-
c: 'commit',
|
|
184
|
-
a: 'amend',
|
|
185
|
-
f: 'fixup',
|
|
186
|
-
escape: 'cancel',
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
226
|
confirmUpdate: {
|
|
190
227
|
choices: YES_NO,
|
|
191
228
|
prefix: (view) => {
|
|
@@ -248,19 +285,23 @@ module.exports = {
|
|
|
248
285
|
ACTIONS,
|
|
249
286
|
ACTION_IDS,
|
|
250
287
|
BRANCH_ACTIONS,
|
|
288
|
+
COMMIT_ACTIONS,
|
|
251
289
|
ACTION_HOT,
|
|
252
290
|
ACTION_LABEL,
|
|
253
291
|
DIFF_DISABLED,
|
|
254
292
|
FILES_DISABLED,
|
|
293
|
+
FILES_HIDDEN,
|
|
255
294
|
FILES_GIT_DISABLED,
|
|
256
295
|
FILES_TODO_DISABLED,
|
|
257
296
|
TODO_DISABLED,
|
|
258
297
|
BRANCHES_DISABLED,
|
|
298
|
+
COMMITS_DISABLED,
|
|
259
299
|
SCROLL,
|
|
260
300
|
PANE_ONLY,
|
|
261
301
|
disabledActions,
|
|
262
302
|
diffGitDisabled,
|
|
263
303
|
branchGitDisabled,
|
|
304
|
+
commitGitDisabled,
|
|
264
305
|
actionFromKey,
|
|
265
306
|
actionKeys,
|
|
266
307
|
actionHot,
|
package/lib/session/branches.js
CHANGED
|
@@ -21,6 +21,11 @@ const refreshBranchList = (api) => {
|
|
|
21
21
|
if (nav.branchCursor > last) nav.branchCursor = Math.max(0, last);
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
const refreshAfterWrite = (api, extra = {}) => {
|
|
25
|
+
refreshBranchList(api);
|
|
26
|
+
api.options.refreshFromRepo({ keepEmpty: true, ...extra });
|
|
27
|
+
};
|
|
28
|
+
|
|
24
29
|
const onBranch = (api) => {
|
|
25
30
|
if (api.options.getMode() === 'compose') return;
|
|
26
31
|
if (!api.options.canCommit()) return;
|
|
@@ -93,10 +98,7 @@ const onCheckoutBranch = (api) => {
|
|
|
93
98
|
|
|
94
99
|
const rebaseAsync = (api, onto, done, write) => {
|
|
95
100
|
const run = (top) => write(top, onto);
|
|
96
|
-
const after = () => {
|
|
97
|
-
refreshBranchList(api);
|
|
98
|
-
api.options.refreshFromRepo({ keepEmpty: true, doneStatus: done });
|
|
99
|
-
};
|
|
101
|
+
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
100
102
|
return void api.options.runner.runBusy('rebasing', done, run, after);
|
|
101
103
|
};
|
|
102
104
|
|
|
@@ -117,8 +119,7 @@ const onRebaseBranch = (api) => {
|
|
|
117
119
|
api.options.repo().rebase(top, onto);
|
|
118
120
|
});
|
|
119
121
|
if (!ok) return;
|
|
120
|
-
|
|
121
|
-
api.options.refreshFromRepo({ keepEmpty: true });
|
|
122
|
+
refreshAfterWrite(api);
|
|
122
123
|
if (!api.options.getStatus()) api.options.setStatus(done);
|
|
123
124
|
};
|
|
124
125
|
|
|
@@ -140,10 +141,7 @@ const cancelDropBranch = (api) => {
|
|
|
140
141
|
|
|
141
142
|
const dropAsync = (api, name, done, write) => {
|
|
142
143
|
const run = (top) => write(top, name);
|
|
143
|
-
const after = () => {
|
|
144
|
-
refreshBranchList(api);
|
|
145
|
-
api.options.refreshFromRepo({ keepEmpty: true, doneStatus: done });
|
|
146
|
-
};
|
|
144
|
+
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
147
145
|
return void api.options.runner.runBusy('dropping', done, run, after);
|
|
148
146
|
};
|
|
149
147
|
|
|
@@ -163,8 +161,7 @@ const confirmDropBranch = (api) => {
|
|
|
163
161
|
api.options.repo().drop(top, name);
|
|
164
162
|
});
|
|
165
163
|
if (!ok) return;
|
|
166
|
-
|
|
167
|
-
api.options.refreshFromRepo({ keepEmpty: true });
|
|
164
|
+
refreshAfterWrite(api);
|
|
168
165
|
if (!api.options.getStatus()) api.options.setStatus(done);
|
|
169
166
|
};
|
|
170
167
|
|
|
@@ -178,8 +175,7 @@ const createAsync = (api, name, done, write) => {
|
|
|
178
175
|
api.options.composer.closeCompose();
|
|
179
176
|
api.options.showFiles();
|
|
180
177
|
const run = (top) => write(top, name);
|
|
181
|
-
const after = () =>
|
|
182
|
-
api.options.refreshFromRepo({ keepEmpty: true, doneStatus: done });
|
|
178
|
+
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
183
179
|
return void api.options.runner.runBusy('creating branch', done, run, after);
|
|
184
180
|
};
|
|
185
181
|
|
|
@@ -203,7 +199,7 @@ const finishCreateBranch = (api) => {
|
|
|
203
199
|
if (!ok) return;
|
|
204
200
|
api.options.composer.closeCompose();
|
|
205
201
|
api.options.showFiles();
|
|
206
|
-
api
|
|
202
|
+
refreshAfterWrite(api);
|
|
207
203
|
if (!api.options.getStatus()) api.options.setStatus(done);
|
|
208
204
|
};
|
|
209
205
|
|
|
@@ -212,7 +208,7 @@ const onPull = (api) => {
|
|
|
212
208
|
const repo = api.options.repo();
|
|
213
209
|
const picked = pickRepoWrite(repo, 'pull', api.options.uiOpen());
|
|
214
210
|
if (picked.async) {
|
|
215
|
-
const after = () => api
|
|
211
|
+
const after = () => refreshAfterWrite(api);
|
|
216
212
|
const write = (top) => picked.write(top);
|
|
217
213
|
return void api.options.runner.runBusy('pulling', 'pulled', write, after);
|
|
218
214
|
}
|
|
@@ -220,7 +216,7 @@ const onPull = (api) => {
|
|
|
220
216
|
repo.pull(top);
|
|
221
217
|
});
|
|
222
218
|
if (!ok) return;
|
|
223
|
-
api
|
|
219
|
+
refreshAfterWrite(api);
|
|
224
220
|
if (!api.options.getStatus()) api.options.setStatus('pulled');
|
|
225
221
|
};
|
|
226
222
|
|
|
@@ -232,7 +228,8 @@ const startPush = (api, force) => {
|
|
|
232
228
|
const picked = pickRepoWrite(repo, 'push', api.options.uiOpen());
|
|
233
229
|
if (picked.async) {
|
|
234
230
|
const write = (top) => picked.write(top, force);
|
|
235
|
-
|
|
231
|
+
const after = () => refreshAfterWrite(api);
|
|
232
|
+
return void api.options.runner.runBusy(kind, done, write, after);
|
|
236
233
|
}
|
|
237
234
|
try {
|
|
238
235
|
repo.push(api.options.top(), force);
|
|
@@ -245,6 +242,7 @@ const startPush = (api, force) => {
|
|
|
245
242
|
api.options.setStatus(error.message);
|
|
246
243
|
return;
|
|
247
244
|
}
|
|
245
|
+
refreshAfterWrite(api);
|
|
248
246
|
api.options.setStatus(done);
|
|
249
247
|
};
|
|
250
248
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const files = require('../files.js');
|
|
4
|
-
const {
|
|
4
|
+
const { listPath, isTodoItem, isTodosEntry } = files;
|
|
5
5
|
const items = require('./items.js');
|
|
6
6
|
const { needsReload, npmBusyKind, sameBlock } = items;
|
|
7
7
|
const { isReadOnlyOrigin } = require('./origins.js');
|
|
@@ -27,6 +27,9 @@ const COMMANDS = {
|
|
|
27
27
|
|
|
28
28
|
const keepOrigin = (options, item, origin) => {
|
|
29
29
|
options.collection.keepOrigin(item, origin);
|
|
30
|
+
const idx = options.collection.findRestoredIndex({ ...item, origin });
|
|
31
|
+
if (idx >= 0) options.nav.index = idx;
|
|
32
|
+
if (options.ignoreWatch) options.ignoreWatch();
|
|
30
33
|
options.nav.clearSelection();
|
|
31
34
|
options.syncReviewPath();
|
|
32
35
|
options.syncFileCursor();
|
|
@@ -44,7 +47,7 @@ const fileActionItems = (options) => {
|
|
|
44
47
|
const selected = [];
|
|
45
48
|
for (const item of options.getItems()) {
|
|
46
49
|
if (isTodoItem(item)) continue;
|
|
47
|
-
if (
|
|
50
|
+
if (listPath(item) !== rel) continue;
|
|
48
51
|
selected.push(item);
|
|
49
52
|
}
|
|
50
53
|
return selected;
|
|
@@ -222,7 +225,7 @@ const onFileAdd = (options) => {
|
|
|
222
225
|
return;
|
|
223
226
|
}
|
|
224
227
|
if (!guardWritable(options, selected[0])) return;
|
|
225
|
-
const rel =
|
|
228
|
+
const rel = listPath(selected[0]);
|
|
226
229
|
const targets = selected.filter(COMMANDS.add.match);
|
|
227
230
|
if (!targets.length) {
|
|
228
231
|
options.setStatus('already staged');
|
|
@@ -257,7 +260,7 @@ const onFileUnstage = (options) => {
|
|
|
257
260
|
return;
|
|
258
261
|
}
|
|
259
262
|
if (!guardWritable(options, selected[0])) return;
|
|
260
|
-
const rel =
|
|
263
|
+
const rel = listPath(selected[0]);
|
|
261
264
|
const targets = selected.filter(COMMANDS.unstage.match);
|
|
262
265
|
if (!targets.length) {
|
|
263
266
|
options.setStatus('not staged');
|
|
@@ -283,7 +286,7 @@ const onFileRevert = (options) => {
|
|
|
283
286
|
return;
|
|
284
287
|
}
|
|
285
288
|
if (!guardWritable(options, selected[0])) return;
|
|
286
|
-
const rel =
|
|
289
|
+
const rel = listPath(selected[0]);
|
|
287
290
|
for (const item of selected) {
|
|
288
291
|
if (needsReload(item)) options.collection.dismiss(item);
|
|
289
292
|
}
|
package/lib/session/commit.js
CHANGED
|
@@ -33,19 +33,71 @@ const hasStagedChanges = (options) => {
|
|
|
33
33
|
return false;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
options.setStatus('');
|
|
36
|
+
const selectedCommit = (api) => {
|
|
37
|
+
const cursor = api.options.nav.commitCursor;
|
|
38
|
+
return api.state.commits[cursor] ?? null;
|
|
40
39
|
};
|
|
41
40
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
const clampCommitCursor = (api) => {
|
|
42
|
+
const last = api.state.commits.length - 1;
|
|
43
|
+
const nav = api.options.nav;
|
|
44
|
+
if (nav.commitCursor > last) nav.commitCursor = Math.max(0, last);
|
|
46
45
|
};
|
|
47
46
|
|
|
48
|
-
const
|
|
47
|
+
const refreshCommitList = (api) => {
|
|
48
|
+
const repo = api.options.repo();
|
|
49
|
+
if (!repo.listCommits) return;
|
|
50
|
+
try {
|
|
51
|
+
api.state.commits = repo.listCommits(api.options.top());
|
|
52
|
+
} catch (error) {
|
|
53
|
+
api.options.setStatus(error.message);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
clampCommitCursor(api);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const refreshAfterWrite = (api, extra = {}) => {
|
|
60
|
+
refreshCommitList(api);
|
|
61
|
+
api.options.refreshFromRepo({ keepEmpty: true, ...extra });
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const showCommits = (api) => {
|
|
65
|
+
if (api.options.getMode() === 'compose') return;
|
|
66
|
+
if (!canCommit(api.options)) return;
|
|
67
|
+
const repo = api.options.repo();
|
|
68
|
+
if (!repo.listCommits) {
|
|
69
|
+
api.options.setStatus('read only');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
api.state.commits = repo.listCommits(api.options.top());
|
|
74
|
+
} catch (error) {
|
|
75
|
+
api.options.setStatus(error.message);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
api.options.nav.commitCursor = 0;
|
|
79
|
+
api.options.nav.pane = 'commits';
|
|
80
|
+
api.options.setStatus('');
|
|
81
|
+
api.options.nav.clearSelection();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const onCommitMove = (api, delta) => {
|
|
85
|
+
const commits = api.state.commits;
|
|
86
|
+
if (!commits.length) {
|
|
87
|
+
api.options.setStatus('nothing to review');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const next = Math.min(
|
|
91
|
+
commits.length - 1,
|
|
92
|
+
Math.max(0, api.options.nav.commitCursor + delta),
|
|
93
|
+
);
|
|
94
|
+
if (next === api.options.nav.commitCursor) return;
|
|
95
|
+
api.options.nav.commitCursor = next;
|
|
96
|
+
api.options.setStatus('');
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const startGitCommit = (api, kind) => {
|
|
100
|
+
const options = api.options;
|
|
49
101
|
if (kind !== 'amend' && !hasStagedChanges(options)) {
|
|
50
102
|
options.setMode('review');
|
|
51
103
|
options.composer.state.commitKind = null;
|
|
@@ -54,25 +106,50 @@ const startGitCommit = (options, kind) => {
|
|
|
54
106
|
}
|
|
55
107
|
options.composer.state.commitKind = kind;
|
|
56
108
|
let text = '';
|
|
57
|
-
if (kind === 'fixup')
|
|
109
|
+
if (kind === 'fixup') {
|
|
110
|
+
const entry = selectedCommit(api);
|
|
111
|
+
text = entry ? entry.shortSha || entry.sha : 'HEAD';
|
|
112
|
+
}
|
|
58
113
|
if (kind === 'amend' && options.repo().lastMessage) {
|
|
59
114
|
text = options.repo().lastMessage(options.top()) ?? '';
|
|
60
115
|
}
|
|
61
116
|
options.composer.openCompose('commit', text);
|
|
62
117
|
};
|
|
63
118
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
119
|
+
const onCommit = (api) => {
|
|
120
|
+
if (api.options.nav.pane !== 'commits') return void showCommits(api);
|
|
121
|
+
if (!canCommit(api.options)) return;
|
|
122
|
+
startGitCommit(api, 'commit');
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const onAmend = (api) => {
|
|
126
|
+
if (api.options.nav.pane !== 'commits') return;
|
|
127
|
+
if (!canCommit(api.options)) return;
|
|
128
|
+
startGitCommit(api, 'amend');
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const onFixup = (api) => {
|
|
132
|
+
if (api.options.nav.pane !== 'commits') return;
|
|
133
|
+
if (!canCommit(api.options)) return;
|
|
134
|
+
startGitCommit(api, 'fixup');
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const cancelCommit = (api) => {
|
|
138
|
+
api.options.setMode('review');
|
|
139
|
+
api.options.composer.state.commitKind = null;
|
|
140
|
+
api.options.setStatus('');
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const finishAsyncCommit = (api, kind, message, done, write) => {
|
|
144
|
+
const options = api.options;
|
|
145
|
+
options.composer.closeCompose();
|
|
67
146
|
const run = (top) => write(top, kind, message);
|
|
68
|
-
const after = () => {
|
|
69
|
-
options.collection.clearDismissed();
|
|
70
|
-
options.refreshFromRepo({ doneStatus: done });
|
|
71
|
-
};
|
|
147
|
+
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
72
148
|
return void options.runner.runBusy('committing', done, run, after);
|
|
73
149
|
};
|
|
74
150
|
|
|
75
|
-
const finishSyncCommit = (
|
|
151
|
+
const finishSyncCommit = (api, kind, message, done) => {
|
|
152
|
+
const options = api.options;
|
|
76
153
|
try {
|
|
77
154
|
options.repo().commit(options.top(), kind, message);
|
|
78
155
|
} catch (error) {
|
|
@@ -81,13 +158,14 @@ const finishSyncCommit = (options, kind, message, done) => {
|
|
|
81
158
|
}
|
|
82
159
|
options.composer.closeCompose();
|
|
83
160
|
options.collection.clearDismissed();
|
|
84
|
-
|
|
161
|
+
refreshAfterWrite(api);
|
|
85
162
|
if (!options.isDone() && !options.pendingExtras()) {
|
|
86
163
|
options.setStatus(done);
|
|
87
164
|
}
|
|
88
165
|
};
|
|
89
166
|
|
|
90
|
-
const finishGitCommit = (
|
|
167
|
+
const finishGitCommit = (api) => {
|
|
168
|
+
const options = api.options;
|
|
91
169
|
const kind = options.composer.state.commitKind;
|
|
92
170
|
const editor = options.composer.state.editor;
|
|
93
171
|
const message = editor ? editor.text : '';
|
|
@@ -104,19 +182,103 @@ const finishGitCommit = (options) => {
|
|
|
104
182
|
const uiOpen = options.uiOpen();
|
|
105
183
|
const picked = pickRepoWrite(options.repo(), 'commit', uiOpen);
|
|
106
184
|
if (picked.async) {
|
|
107
|
-
finishAsyncCommit(
|
|
185
|
+
finishAsyncCommit(api, kind, message, done, picked.write);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
finishSyncCommit(api, kind, message, done);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const onDropCommit = (api) => {
|
|
192
|
+
if (api.options.nav.pane !== 'commits') return;
|
|
193
|
+
if (!canCommit(api.options)) return;
|
|
194
|
+
const entry = selectedCommit(api);
|
|
195
|
+
if (!entry) return;
|
|
196
|
+
api.state.dropName = entry.shortSha || entry.sha;
|
|
197
|
+
api.state.dropSha = entry.sha;
|
|
198
|
+
api.options.setMode('confirmDrop');
|
|
199
|
+
api.options.setStatus('');
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const cancelDropCommit = (api) => {
|
|
203
|
+
api.options.setMode('review');
|
|
204
|
+
api.state.dropName = '';
|
|
205
|
+
api.state.dropSha = '';
|
|
206
|
+
api.options.setStatus('');
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const dropAsync = (api, sha, done, write) => {
|
|
210
|
+
const run = (top) => write(top, sha);
|
|
211
|
+
const after = () => refreshAfterWrite(api, { doneStatus: done });
|
|
212
|
+
return void api.options.runner.runBusy('dropping', done, run, after);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const confirmDropCommit = (api) => {
|
|
216
|
+
const sha = api.state.dropSha;
|
|
217
|
+
const name = api.state.dropName;
|
|
218
|
+
api.options.setMode('review');
|
|
219
|
+
api.state.dropName = '';
|
|
220
|
+
api.state.dropSha = '';
|
|
221
|
+
if (!sha) return;
|
|
222
|
+
const done = `dropped ${name}`;
|
|
223
|
+
const repo = api.options.repo();
|
|
224
|
+
if (!repo.dropCommit) {
|
|
225
|
+
api.options.setStatus('read only');
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const uiOpen = api.options.uiOpen();
|
|
229
|
+
const picked = pickRepoWrite(repo, 'dropCommit', uiOpen);
|
|
230
|
+
if (picked.async) {
|
|
231
|
+
dropAsync(api, sha, done, picked.write);
|
|
108
232
|
return;
|
|
109
233
|
}
|
|
110
|
-
|
|
234
|
+
const ok = api.options.runner.runRepo(done, (top) => {
|
|
235
|
+
repo.dropCommit(top, sha);
|
|
236
|
+
});
|
|
237
|
+
if (!ok) return;
|
|
238
|
+
refreshAfterWrite(api);
|
|
239
|
+
if (!api.options.getStatus()) api.options.setStatus(done);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const reset = (state) => {
|
|
243
|
+
state.commits = [];
|
|
244
|
+
state.dropName = '';
|
|
245
|
+
state.dropSha = '';
|
|
111
246
|
};
|
|
112
247
|
|
|
113
|
-
const createCommitController = (options) =>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
248
|
+
const createCommitController = (options) => {
|
|
249
|
+
const state = {
|
|
250
|
+
commits: [],
|
|
251
|
+
dropName: '',
|
|
252
|
+
dropSha: '',
|
|
253
|
+
};
|
|
254
|
+
const api = { options, state };
|
|
255
|
+
return {
|
|
256
|
+
get commits() {
|
|
257
|
+
return state.commits;
|
|
258
|
+
},
|
|
259
|
+
set commits(value) {
|
|
260
|
+
state.commits = value;
|
|
261
|
+
},
|
|
262
|
+
get dropName() {
|
|
263
|
+
return state.dropName;
|
|
264
|
+
},
|
|
265
|
+
set dropName(value) {
|
|
266
|
+
state.dropName = value;
|
|
267
|
+
},
|
|
268
|
+
reset: () => reset(state),
|
|
269
|
+
canCommit: () => canCommit(options),
|
|
270
|
+
onCommit: () => onCommit(api),
|
|
271
|
+
onAmend: () => onAmend(api),
|
|
272
|
+
onFixup: () => onFixup(api),
|
|
273
|
+
onCommitMove: (delta) => onCommitMove(api, delta),
|
|
274
|
+
cancelCommit: () => cancelCommit(api),
|
|
275
|
+
startGitCommit: (kind) => startGitCommit(api, kind),
|
|
276
|
+
finishGitCommit: () => finishGitCommit(api),
|
|
277
|
+
onDropCommit: () => onDropCommit(api),
|
|
278
|
+
cancelDropCommit: () => cancelDropCommit(api),
|
|
279
|
+
confirmDropCommit: () => confirmDropCommit(api),
|
|
280
|
+
};
|
|
281
|
+
};
|
|
120
282
|
|
|
121
283
|
module.exports = {
|
|
122
284
|
COMMIT_STATUS,
|
package/lib/session/dispatch.js
CHANGED
|
@@ -19,12 +19,19 @@ const createDispatcher = (options) => {
|
|
|
19
19
|
code: options.composer.onCode,
|
|
20
20
|
reload: options.onReload,
|
|
21
21
|
commit: options.commits.onCommit,
|
|
22
|
+
amend: options.commits.onAmend,
|
|
23
|
+
fixup: options.commits.onFixup,
|
|
22
24
|
branch: options.gitBranches.onBranch,
|
|
23
25
|
pull: options.gitBranches.onPull,
|
|
24
26
|
push: options.gitBranches.onPush,
|
|
25
27
|
newBranch: options.gitBranches.onNewBranch,
|
|
26
28
|
rebase: options.gitBranches.onRebaseBranch,
|
|
27
|
-
drop:
|
|
29
|
+
drop: () => {
|
|
30
|
+
if (options.getPane() === 'commits') {
|
|
31
|
+
return void options.commits.onDropCommit();
|
|
32
|
+
}
|
|
33
|
+
options.gitBranches.onDropBranch();
|
|
34
|
+
},
|
|
28
35
|
open: options.onOpenFile,
|
|
29
36
|
removeTodo: options.composer.removeFocusedTodo,
|
|
30
37
|
quit: options.onQuit,
|
|
@@ -54,6 +61,10 @@ const createDispatcher = (options) => {
|
|
|
54
61
|
if (action === 'next') return void options.onBranchMove(1);
|
|
55
62
|
if (action === 'prev') return void options.onBranchMove(-1);
|
|
56
63
|
}
|
|
64
|
+
if (pane === 'commits') {
|
|
65
|
+
if (action === 'next') return void options.onCommitMove(1);
|
|
66
|
+
if (action === 'prev') return void options.onCommitMove(-1);
|
|
67
|
+
}
|
|
57
68
|
const hidden = disabledActions(pane, options.currentTarget());
|
|
58
69
|
if (hidden.includes(action)) return;
|
|
59
70
|
const handler = handlers[action];
|
|
@@ -67,7 +78,6 @@ const createDispatcher = (options) => {
|
|
|
67
78
|
const createInput = (options) => {
|
|
68
79
|
const confirmations = {
|
|
69
80
|
confirmQuit: options.quit,
|
|
70
|
-
confirmCommit: options.commit,
|
|
71
81
|
confirmUpdate: options.update,
|
|
72
82
|
confirmDrop: options.drop,
|
|
73
83
|
confirmPush: options.push,
|
|
@@ -35,7 +35,7 @@ const showFiles = (options) => {
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
const onEscape = (options) => {
|
|
38
|
-
if (options.nav.pane === 'branches') {
|
|
38
|
+
if (options.nav.pane === 'branches' || options.nav.pane === 'commits') {
|
|
39
39
|
showFiles(options);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
@@ -61,6 +61,7 @@ const onOpenFile = (options) => {
|
|
|
61
61
|
if (options.nav.pane === 'branches') {
|
|
62
62
|
return void options.onCheckoutBranch();
|
|
63
63
|
}
|
|
64
|
+
if (options.nav.pane === 'commits') return;
|
|
64
65
|
if (options.nav.pane !== 'files') {
|
|
65
66
|
if (options.nav.todoOpen) options.composer.editFocusedTodo();
|
|
66
67
|
return;
|
|
@@ -157,6 +158,9 @@ const onScroll = (options, delta) => {
|
|
|
157
158
|
if (options.nav.pane === 'branches') {
|
|
158
159
|
return void options.onBranchMove(delta);
|
|
159
160
|
}
|
|
161
|
+
if (options.nav.pane === 'commits') {
|
|
162
|
+
return void options.onCommitMove(delta);
|
|
163
|
+
}
|
|
160
164
|
if (options.nav.todoOpen && options.composer.todoRowCount() > 1) {
|
|
161
165
|
return void options.composer.moveTodoFocus(delta);
|
|
162
166
|
}
|
|
@@ -186,6 +190,11 @@ const onJump = (options, toEnd) => {
|
|
|
186
190
|
options.onBranchMove(delta);
|
|
187
191
|
return;
|
|
188
192
|
}
|
|
193
|
+
if (options.nav.pane === 'commits') {
|
|
194
|
+
const delta = toEnd ? Number.MAX_SAFE_INTEGER : -Number.MAX_SAFE_INTEGER;
|
|
195
|
+
options.onCommitMove(delta);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
189
198
|
if (options.nav.todoOpen && options.composer.todoRowCount() > 0) {
|
|
190
199
|
const last = options.composer.todoRowCount() - 1;
|
|
191
200
|
const target = toEnd ? last : 0;
|