guito 0.5.1 → 0.5.3
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 +19 -0
- package/bin/guito-server.js +114 -89
- package/bin/ui/browser/index.html +1 -1
- package/bin/ui/browser/main-A5ZTTMFS.js +5 -0
- package/package.json +2 -1
- package/bin/ui/browser/main-24WBYIHU.js +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Guito are documented in this file. The project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and this changelog is structured around [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
4
|
|
|
5
|
+
## [0.5.3] - 2026-09-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Commit history now loads 500 commits at a time with "Load more" and "Load all" controls, so large repositories open without fetching the entire history up front.
|
|
10
|
+
- Commit search is debounced and now matches commit bodies in addition to messages, authors, and hashes; searching or filtering by a branch loads the full history automatically so results always cover every commit.
|
|
11
|
+
- The history view includes commits from all branches, and server responses are compressed for faster loading in remote workspaces.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Fixed the commit table keeping a stale visible-row limit when switching branches or changing the search query.
|
|
16
|
+
- Fixed the commits endpoint returning an error instead of an empty list for repositories without commits.
|
|
17
|
+
|
|
18
|
+
## [0.5.2] - 2026-09-01
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Fixed VS Code extension server authentication by preserving the session token in the embedded webview URL.
|
|
23
|
+
|
|
5
24
|
## [0.5.1] - 2026-08-31
|
|
6
25
|
|
|
7
26
|
### Added
|
package/bin/guito-server.js
CHANGED
|
@@ -5,6 +5,7 @@ import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
|
5
5
|
import fastify from 'fastify';
|
|
6
6
|
import fastifyStatic from '@fastify/static';
|
|
7
7
|
import fastifyCors from '@fastify/cors';
|
|
8
|
+
import fastifyCompress from '@fastify/compress';
|
|
8
9
|
import { simpleGit } from 'simple-git';
|
|
9
10
|
import { promisify } from 'node:util';
|
|
10
11
|
const execFileAsync = promisify(execFile);
|
|
@@ -15,6 +16,8 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
15
16
|
});
|
|
16
17
|
// Register cors
|
|
17
18
|
await app.register(fastifyCors);
|
|
19
|
+
// Compress JSON responses (commit history payloads are highly repetitive)
|
|
20
|
+
await app.register(fastifyCompress);
|
|
18
21
|
if (apiToken) {
|
|
19
22
|
app.addHook('onRequest', async (request, reply) => {
|
|
20
23
|
const pathname = request.url.split('?', 1)[0];
|
|
@@ -130,16 +133,21 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
130
133
|
app.get('/api/repo', async (_req, resp) => {
|
|
131
134
|
try {
|
|
132
135
|
const root = (await git.revparse(['--show-toplevel'])).trim();
|
|
133
|
-
resp.type('application/json').send({ root, name: basename(root) });
|
|
136
|
+
return resp.type('application/json').send({ root, name: basename(root) });
|
|
134
137
|
}
|
|
135
138
|
catch (err) {
|
|
136
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
139
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
137
140
|
}
|
|
138
141
|
});
|
|
139
142
|
// ==================== Commits ====================
|
|
140
|
-
app.get('/api/commits', async (
|
|
141
|
-
try {
|
|
142
|
-
const
|
|
143
|
+
app.get('/api/commits', async (req, resp) => {
|
|
144
|
+
try {
|
|
145
|
+
const query = (req.query ?? {});
|
|
146
|
+
const limit = Number.parseInt(query.limit ?? '', 10);
|
|
147
|
+
const skip = Number.parseInt(query.skip ?? '', 10);
|
|
148
|
+
// Build simple-git options conditionally: an explicit key with an
|
|
149
|
+
// undefined value would still be emitted as a bare command flag.
|
|
150
|
+
const options = {
|
|
143
151
|
format: {
|
|
144
152
|
hash: '%H',
|
|
145
153
|
date: '%aI',
|
|
@@ -150,27 +158,44 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
150
158
|
author_email: '%aE',
|
|
151
159
|
parents: '%P',
|
|
152
160
|
},
|
|
153
|
-
|
|
161
|
+
'--all': null,
|
|
162
|
+
};
|
|
163
|
+
if (Number.isFinite(limit) && limit > 0) {
|
|
164
|
+
options.maxCount = limit;
|
|
165
|
+
}
|
|
166
|
+
if (Number.isFinite(skip) && skip > 0) {
|
|
167
|
+
options['--skip'] = String(skip);
|
|
168
|
+
}
|
|
169
|
+
const [log, count] = await Promise.all([
|
|
170
|
+
git.log(options),
|
|
171
|
+
git.raw(['rev-list', '--count', '--all']),
|
|
172
|
+
]);
|
|
154
173
|
const commits = log.all.map((commit) => ({
|
|
155
174
|
...commit,
|
|
156
175
|
parents: String(commit.parents ?? '')
|
|
157
176
|
.split(' ')
|
|
158
177
|
.filter(Boolean),
|
|
159
178
|
}));
|
|
160
|
-
resp
|
|
179
|
+
return resp
|
|
180
|
+
.type('application/json')
|
|
181
|
+
.send({ commits, total: Number.parseInt(count, 10) || 0 });
|
|
161
182
|
}
|
|
162
183
|
catch (err) {
|
|
163
|
-
|
|
184
|
+
// A repository without any commits has no history to list.
|
|
185
|
+
if (/does not have any commits yet|unknown revision|bad default revision/i.test(err.message ?? '')) {
|
|
186
|
+
return resp.type('application/json').send({ commits: [], total: 0 });
|
|
187
|
+
}
|
|
188
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
164
189
|
}
|
|
165
190
|
});
|
|
166
191
|
app.post('/api/commit', async (req, resp) => {
|
|
167
192
|
try {
|
|
168
193
|
const { message, description } = req.body;
|
|
169
194
|
await git.commit([message, ...(description ? [description] : [])], { '--allow-empty': null });
|
|
170
|
-
resp.type('application/json').send({ success: true });
|
|
195
|
+
return resp.type('application/json').send({ success: true });
|
|
171
196
|
}
|
|
172
197
|
catch (err) {
|
|
173
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
198
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
174
199
|
}
|
|
175
200
|
});
|
|
176
201
|
app.post('/api/amend', async (req, resp) => {
|
|
@@ -180,57 +205,57 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
180
205
|
'--amend': null,
|
|
181
206
|
'--no-edit': null,
|
|
182
207
|
});
|
|
183
|
-
resp.type('application/json').send({ success: true });
|
|
208
|
+
return resp.type('application/json').send({ success: true });
|
|
184
209
|
}
|
|
185
210
|
catch (err) {
|
|
186
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
211
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
187
212
|
}
|
|
188
213
|
});
|
|
189
214
|
app.post('/api/revert', async (req, resp) => {
|
|
190
215
|
try {
|
|
191
216
|
const { commit } = req.body;
|
|
192
217
|
await git.revert(commit);
|
|
193
|
-
resp.type('application/json').send({ success: true });
|
|
218
|
+
return resp.type('application/json').send({ success: true });
|
|
194
219
|
}
|
|
195
220
|
catch (err) {
|
|
196
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
221
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
197
222
|
}
|
|
198
223
|
});
|
|
199
224
|
app.post('/api/cherry-pick', async (req, resp) => {
|
|
200
225
|
try {
|
|
201
226
|
await git.raw(['cherry-pick', req.body.commit]);
|
|
202
|
-
resp.type('application/json').send({ success: true });
|
|
227
|
+
return resp.type('application/json').send({ success: true });
|
|
203
228
|
}
|
|
204
229
|
catch (err) {
|
|
205
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
230
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
206
231
|
}
|
|
207
232
|
});
|
|
208
233
|
app.post('/api/commit/drop', async (req, resp) => {
|
|
209
234
|
try {
|
|
210
235
|
await git.raw(['reset', '--hard', `${req.body.commit}^`]);
|
|
211
|
-
resp.type('application/json').send({ success: true });
|
|
236
|
+
return resp.type('application/json').send({ success: true });
|
|
212
237
|
}
|
|
213
238
|
catch (err) {
|
|
214
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
239
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
215
240
|
}
|
|
216
241
|
});
|
|
217
242
|
app.post('/api/reset-commit', async (req, resp) => {
|
|
218
243
|
try {
|
|
219
244
|
await git.raw(['reset', '--hard', req.body.commit]);
|
|
220
|
-
resp.type('application/json').send({ success: true });
|
|
245
|
+
return resp.type('application/json').send({ success: true });
|
|
221
246
|
}
|
|
222
247
|
catch (err) {
|
|
223
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
248
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
224
249
|
}
|
|
225
250
|
});
|
|
226
251
|
// ==================== Staging ====================
|
|
227
252
|
app.get('/api/status', async (_req, resp) => {
|
|
228
253
|
try {
|
|
229
254
|
const status = await git.status();
|
|
230
|
-
resp.type('application/json').send(status);
|
|
255
|
+
return resp.type('application/json').send(status);
|
|
231
256
|
}
|
|
232
257
|
catch (err) {
|
|
233
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
258
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
234
259
|
}
|
|
235
260
|
});
|
|
236
261
|
app.post('/api/stage', async (req, resp) => {
|
|
@@ -239,10 +264,10 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
239
264
|
if (Array.isArray(files) && files.length > 0) {
|
|
240
265
|
await git.add(files);
|
|
241
266
|
}
|
|
242
|
-
resp.type('application/json').send({ success: true });
|
|
267
|
+
return resp.type('application/json').send({ success: true });
|
|
243
268
|
}
|
|
244
269
|
catch (err) {
|
|
245
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
270
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
246
271
|
}
|
|
247
272
|
});
|
|
248
273
|
app.post('/api/unstage', async (req, resp) => {
|
|
@@ -251,10 +276,10 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
251
276
|
if (Array.isArray(files) && files.length > 0) {
|
|
252
277
|
await git.reset(['HEAD', ...files]);
|
|
253
278
|
}
|
|
254
|
-
resp.type('application/json').send({ success: true });
|
|
279
|
+
return resp.type('application/json').send({ success: true });
|
|
255
280
|
}
|
|
256
281
|
catch (err) {
|
|
257
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
282
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
258
283
|
}
|
|
259
284
|
});
|
|
260
285
|
app.post('/api/stage-lines', async (req, resp) => {
|
|
@@ -262,10 +287,10 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
262
287
|
const { file, patch } = req.body;
|
|
263
288
|
// Stage specific lines using git add -p equivalent (patch mode)
|
|
264
289
|
await git.raw('add --patch', { input: patch });
|
|
265
|
-
resp.type('application/json').send({ success: true });
|
|
290
|
+
return resp.type('application/json').send({ success: true });
|
|
266
291
|
}
|
|
267
292
|
catch (err) {
|
|
268
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
293
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
269
294
|
}
|
|
270
295
|
});
|
|
271
296
|
// ==================== Branches ====================
|
|
@@ -287,69 +312,69 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
287
312
|
const name = refname.replace(/^refs\/(heads|remotes)\//, '');
|
|
288
313
|
return { name, commit, current: headMarker === '*', remote };
|
|
289
314
|
});
|
|
290
|
-
resp.type('application/json').send(branches);
|
|
315
|
+
return resp.type('application/json').send(branches);
|
|
291
316
|
}
|
|
292
317
|
catch (err) {
|
|
293
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
318
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
294
319
|
}
|
|
295
320
|
});
|
|
296
321
|
app.get('/api/branches', async (_req, resp) => {
|
|
297
322
|
try {
|
|
298
323
|
const branchSummary = await git.branchLocal();
|
|
299
|
-
resp.type('application/json').send(branchSummary);
|
|
324
|
+
return resp.type('application/json').send(branchSummary);
|
|
300
325
|
}
|
|
301
326
|
catch (err) {
|
|
302
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
327
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
303
328
|
}
|
|
304
329
|
});
|
|
305
330
|
app.post('/api/branch/create', async (req, resp) => {
|
|
306
331
|
try {
|
|
307
332
|
const { name, startPoint } = req.body;
|
|
308
333
|
await git.branch([...(startPoint ? [name, startPoint] : [name])]);
|
|
309
|
-
resp.type('application/json').send({ success: true });
|
|
334
|
+
return resp.type('application/json').send({ success: true });
|
|
310
335
|
}
|
|
311
336
|
catch (err) {
|
|
312
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
337
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
313
338
|
}
|
|
314
339
|
});
|
|
315
340
|
app.post('/api/branch/delete', async (req, resp) => {
|
|
316
341
|
try {
|
|
317
342
|
const { name, force } = req.body;
|
|
318
343
|
await git.deleteLocalBranch(name, force);
|
|
319
|
-
resp.type('application/json').send({ success: true });
|
|
344
|
+
return resp.type('application/json').send({ success: true });
|
|
320
345
|
}
|
|
321
346
|
catch (err) {
|
|
322
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
347
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
323
348
|
}
|
|
324
349
|
});
|
|
325
350
|
app.post('/api/branch/delete-remote', async (req, resp) => {
|
|
326
351
|
try {
|
|
327
352
|
const { remote, branch } = req.body;
|
|
328
353
|
await git.push([remote, '--delete', branch]);
|
|
329
|
-
resp.type('application/json').send({ success: true });
|
|
354
|
+
return resp.type('application/json').send({ success: true });
|
|
330
355
|
}
|
|
331
356
|
catch (err) {
|
|
332
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
357
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
333
358
|
}
|
|
334
359
|
});
|
|
335
360
|
app.post('/api/branch/rename', async (req, resp) => {
|
|
336
361
|
try {
|
|
337
362
|
const { oldName, newName } = req.body;
|
|
338
363
|
await git.branch(['-m', oldName, newName]);
|
|
339
|
-
resp.type('application/json').send({ success: true });
|
|
364
|
+
return resp.type('application/json').send({ success: true });
|
|
340
365
|
}
|
|
341
366
|
catch (err) {
|
|
342
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
367
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
343
368
|
}
|
|
344
369
|
});
|
|
345
370
|
app.post('/api/checkout', async (req, resp) => {
|
|
346
371
|
try {
|
|
347
372
|
const { ref } = req.body;
|
|
348
373
|
await git.checkout(ref);
|
|
349
|
-
resp.type('application/json').send({ success: true });
|
|
374
|
+
return resp.type('application/json').send({ success: true });
|
|
350
375
|
}
|
|
351
376
|
catch (err) {
|
|
352
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
377
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
353
378
|
}
|
|
354
379
|
});
|
|
355
380
|
// ==================== Merge & Rebase ====================
|
|
@@ -357,10 +382,10 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
357
382
|
try {
|
|
358
383
|
const { branch } = req.body;
|
|
359
384
|
await git.merge([branch]);
|
|
360
|
-
resp.type('application/json').send({ success: true });
|
|
385
|
+
return resp.type('application/json').send({ success: true });
|
|
361
386
|
}
|
|
362
387
|
catch (err) {
|
|
363
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
388
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
364
389
|
}
|
|
365
390
|
});
|
|
366
391
|
app.get('/api/archive', async (req, resp) => {
|
|
@@ -387,10 +412,10 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
387
412
|
try {
|
|
388
413
|
const { branch } = req.body;
|
|
389
414
|
await git.rebase([branch]);
|
|
390
|
-
resp.type('application/json').send({ success: true });
|
|
415
|
+
return resp.type('application/json').send({ success: true });
|
|
391
416
|
}
|
|
392
417
|
catch (err) {
|
|
393
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
418
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
394
419
|
}
|
|
395
420
|
});
|
|
396
421
|
app.post('/api/squash', async (req, resp) => {
|
|
@@ -398,80 +423,80 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
398
423
|
const { commits } = req.body;
|
|
399
424
|
// Squash: rebase -i with squash operation
|
|
400
425
|
await git.rebase(['-i', 'HEAD~' + commits]);
|
|
401
|
-
resp.type('application/json').send({ success: true });
|
|
426
|
+
return resp.type('application/json').send({ success: true });
|
|
402
427
|
}
|
|
403
428
|
catch (err) {
|
|
404
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
429
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
405
430
|
}
|
|
406
431
|
});
|
|
407
432
|
// ==================== Stash ====================
|
|
408
433
|
app.get('/api/stash/list', async (_req, resp) => {
|
|
409
434
|
try {
|
|
410
435
|
const stashList = await git.stashList();
|
|
411
|
-
resp.type('application/json').send(stashList);
|
|
436
|
+
return resp.type('application/json').send(stashList);
|
|
412
437
|
}
|
|
413
438
|
catch (err) {
|
|
414
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
439
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
415
440
|
}
|
|
416
441
|
});
|
|
417
442
|
app.post('/api/stash/save', async (req, resp) => {
|
|
418
443
|
try {
|
|
419
444
|
const { message } = req.body;
|
|
420
445
|
await git.stash(['save', message || '']);
|
|
421
|
-
resp.type('application/json').send({ success: true });
|
|
446
|
+
return resp.type('application/json').send({ success: true });
|
|
422
447
|
}
|
|
423
448
|
catch (err) {
|
|
424
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
449
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
425
450
|
}
|
|
426
451
|
});
|
|
427
452
|
app.post('/api/stash/apply', async (req, resp) => {
|
|
428
453
|
try {
|
|
429
454
|
const { index } = req.body;
|
|
430
455
|
await git.stash(['apply', `stash@{${index}}`]);
|
|
431
|
-
resp.type('application/json').send({ success: true });
|
|
456
|
+
return resp.type('application/json').send({ success: true });
|
|
432
457
|
}
|
|
433
458
|
catch (err) {
|
|
434
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
459
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
435
460
|
}
|
|
436
461
|
});
|
|
437
462
|
app.post('/api/stash/pop', async (req, resp) => {
|
|
438
463
|
try {
|
|
439
464
|
const { index } = req.body;
|
|
440
465
|
await git.stash(['pop', `stash@{${index}}`]);
|
|
441
|
-
resp.type('application/json').send({ success: true });
|
|
466
|
+
return resp.type('application/json').send({ success: true });
|
|
442
467
|
}
|
|
443
468
|
catch (err) {
|
|
444
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
469
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
445
470
|
}
|
|
446
471
|
});
|
|
447
472
|
app.post('/api/stash/drop', async (req, resp) => {
|
|
448
473
|
try {
|
|
449
474
|
const { index } = req.body;
|
|
450
475
|
await git.stash(['drop', `stash@{${index}}`]);
|
|
451
|
-
resp.type('application/json').send({ success: true });
|
|
476
|
+
return resp.type('application/json').send({ success: true });
|
|
452
477
|
}
|
|
453
478
|
catch (err) {
|
|
454
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
479
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
455
480
|
}
|
|
456
481
|
});
|
|
457
482
|
app.post('/api/stash/show', async (req, resp) => {
|
|
458
483
|
try {
|
|
459
484
|
const { index } = req.body;
|
|
460
485
|
const show = await git.stash(['show', '-p', `stash@{${index}}`]);
|
|
461
|
-
resp.type('application/json').send({ preview: show });
|
|
486
|
+
return resp.type('application/json').send({ preview: show });
|
|
462
487
|
}
|
|
463
488
|
catch (err) {
|
|
464
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
489
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
465
490
|
}
|
|
466
491
|
});
|
|
467
492
|
// ==================== Tags ====================
|
|
468
493
|
app.get('/api/tags', async (_req, resp) => {
|
|
469
494
|
try {
|
|
470
495
|
const tags = await git.tags();
|
|
471
|
-
resp.type('application/json').send(tags);
|
|
496
|
+
return resp.type('application/json').send(tags);
|
|
472
497
|
}
|
|
473
498
|
catch (err) {
|
|
474
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
499
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
475
500
|
}
|
|
476
501
|
});
|
|
477
502
|
app.post('/api/tag/create', async (req, resp) => {
|
|
@@ -483,70 +508,70 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
483
508
|
else {
|
|
484
509
|
await git.tag([name, ...(commit ? [commit] : [])]);
|
|
485
510
|
}
|
|
486
|
-
resp.type('application/json').send({ success: true });
|
|
511
|
+
return resp.type('application/json').send({ success: true });
|
|
487
512
|
}
|
|
488
513
|
catch (err) {
|
|
489
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
514
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
490
515
|
}
|
|
491
516
|
});
|
|
492
517
|
app.post('/api/tag/delete', async (req, resp) => {
|
|
493
518
|
try {
|
|
494
519
|
const { name } = req.body;
|
|
495
520
|
await git.tag(['-d', name]);
|
|
496
|
-
resp.type('application/json').send({ success: true });
|
|
521
|
+
return resp.type('application/json').send({ success: true });
|
|
497
522
|
}
|
|
498
523
|
catch (err) {
|
|
499
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
524
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
500
525
|
}
|
|
501
526
|
});
|
|
502
527
|
// ==================== Remote Operations ====================
|
|
503
528
|
app.get('/api/fetch', async (_req, resp) => {
|
|
504
529
|
try {
|
|
505
530
|
await git.fetch();
|
|
506
|
-
resp.type('application/json').send({ success: true });
|
|
531
|
+
return resp.type('application/json').send({ success: true });
|
|
507
532
|
}
|
|
508
533
|
catch (err) {
|
|
509
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
534
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
510
535
|
}
|
|
511
536
|
});
|
|
512
537
|
app.post('/api/pull', async (req, resp) => {
|
|
513
538
|
try {
|
|
514
539
|
const { remote, branch, rebase } = req.body;
|
|
515
540
|
await git.pull(remote || 'origin', branch || undefined, rebase ? { '--rebase': null } : {});
|
|
516
|
-
resp.type('application/json').send({ success: true });
|
|
541
|
+
return resp.type('application/json').send({ success: true });
|
|
517
542
|
}
|
|
518
543
|
catch (err) {
|
|
519
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
544
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
520
545
|
}
|
|
521
546
|
});
|
|
522
547
|
app.post('/api/push', async (req, resp) => {
|
|
523
548
|
try {
|
|
524
549
|
const { remote, branch, force } = req.body;
|
|
525
550
|
await git.push(remote || 'origin', branch || undefined, force ? { '-f': null } : {});
|
|
526
|
-
resp.type('application/json').send({ success: true });
|
|
551
|
+
return resp.type('application/json').send({ success: true });
|
|
527
552
|
}
|
|
528
553
|
catch (err) {
|
|
529
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
554
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
530
555
|
}
|
|
531
556
|
});
|
|
532
557
|
app.post('/api/sync', async (_req, resp) => {
|
|
533
558
|
try {
|
|
534
559
|
await git.pull('origin', undefined, {});
|
|
535
560
|
await git.push('origin', undefined, {});
|
|
536
|
-
resp.type('application/json').send({ success: true });
|
|
561
|
+
return resp.type('application/json').send({ success: true });
|
|
537
562
|
}
|
|
538
563
|
catch (err) {
|
|
539
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
564
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
540
565
|
}
|
|
541
566
|
});
|
|
542
567
|
app.post('/api/prune', async (req, resp) => {
|
|
543
568
|
try {
|
|
544
569
|
const { remote } = req.body;
|
|
545
570
|
await git.remote(['prune', remote || 'origin']);
|
|
546
|
-
resp.type('application/json').send({ success: true });
|
|
571
|
+
return resp.type('application/json').send({ success: true });
|
|
547
572
|
}
|
|
548
573
|
catch (err) {
|
|
549
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
574
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
550
575
|
}
|
|
551
576
|
});
|
|
552
577
|
// ==================== Diff Viewer ====================
|
|
@@ -566,10 +591,10 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
566
591
|
'-m',
|
|
567
592
|
hash,
|
|
568
593
|
]);
|
|
569
|
-
resp.type('application/json').send({ hash, files: parseUnifiedDiff(rawDiff) });
|
|
594
|
+
return resp.type('application/json').send({ hash, files: parseUnifiedDiff(rawDiff) });
|
|
570
595
|
}
|
|
571
596
|
catch (err) {
|
|
572
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
597
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
573
598
|
}
|
|
574
599
|
});
|
|
575
600
|
// ==================== Working Changes ====================
|
|
@@ -620,7 +645,7 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
620
645
|
}
|
|
621
646
|
const stagedRaw = await git.raw(['diff', '--name-only', '--cached']);
|
|
622
647
|
const unstagedRaw = await git.raw(['diff', '--name-only']);
|
|
623
|
-
resp.type('application/json').send({
|
|
648
|
+
return resp.type('application/json').send({
|
|
624
649
|
files,
|
|
625
650
|
staged: stagedRaw.split('\n').filter(Boolean),
|
|
626
651
|
unstaged: unstagedRaw.split('\n').filter(Boolean),
|
|
@@ -628,7 +653,7 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
628
653
|
});
|
|
629
654
|
}
|
|
630
655
|
catch (err) {
|
|
631
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
656
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
632
657
|
}
|
|
633
658
|
});
|
|
634
659
|
// ==================== File Content ====================
|
|
@@ -665,15 +690,15 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
665
690
|
if (content.includes('\u0000')) {
|
|
666
691
|
return resp.type('application/json').send({ binary: true, content: '' });
|
|
667
692
|
}
|
|
668
|
-
resp.type('application/json').send({ content });
|
|
693
|
+
return resp.type('application/json').send({ content });
|
|
669
694
|
}
|
|
670
695
|
catch {
|
|
671
696
|
// Path did not exist at that revision (added file).
|
|
672
|
-
resp.type('application/json').send({ content: '' });
|
|
697
|
+
return resp.type('application/json').send({ content: '' });
|
|
673
698
|
}
|
|
674
699
|
}
|
|
675
700
|
catch (err) {
|
|
676
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
701
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
677
702
|
}
|
|
678
703
|
});
|
|
679
704
|
// ==================== Discard ====================
|
|
@@ -694,29 +719,29 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
|
|
|
694
719
|
for (const file of removed) {
|
|
695
720
|
await rm(join(root, file), { force: true, recursive: true });
|
|
696
721
|
}
|
|
697
|
-
resp.type('application/json').send({ success: true });
|
|
722
|
+
return resp.type('application/json').send({ success: true });
|
|
698
723
|
}
|
|
699
724
|
catch (err) {
|
|
700
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
725
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
701
726
|
}
|
|
702
727
|
});
|
|
703
728
|
// ==================== Working Tree Actions ====================
|
|
704
729
|
app.post('/api/reset', async (_req, resp) => {
|
|
705
730
|
try {
|
|
706
731
|
await git.raw(['reset', '--hard', 'HEAD']);
|
|
707
|
-
resp.type('application/json').send({ ok: true });
|
|
732
|
+
return resp.type('application/json').send({ ok: true });
|
|
708
733
|
}
|
|
709
734
|
catch (err) {
|
|
710
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
735
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
711
736
|
}
|
|
712
737
|
});
|
|
713
738
|
app.post('/api/clean', async (_req, resp) => {
|
|
714
739
|
try {
|
|
715
740
|
await git.raw(['clean', '-fd']);
|
|
716
|
-
resp.type('application/json').send({ ok: true });
|
|
741
|
+
return resp.type('application/json').send({ ok: true });
|
|
717
742
|
}
|
|
718
743
|
catch (err) {
|
|
719
|
-
resp.status(400).type('application/json').send({ error: err.message });
|
|
744
|
+
return resp.status(400).type('application/json').send({ error: err.message });
|
|
720
745
|
}
|
|
721
746
|
});
|
|
722
747
|
const address = await app.listen({ port, ...(host ? { host } : {}) });
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
<style>:root{--bg:#1e1e1e;--bg-alt:#232323;--bg-hover:#2a2d2e;--border:#3c3c3c;--text:#cccccc;--text-bright:#e8e8e8;--text-dim:#9d9d9d;--accent:#3794ff;--red:#f14c4c;--mono:ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace}*{box-sizing:border-box}html,body{height:100%;margin:0}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:13px;color:var(--text);background:var(--bg);overflow:hidden}</style><link rel="stylesheet" href="styles-I7K2YZTW.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-I7K2YZTW.css"></noscript></head>
|
|
10
10
|
<body>
|
|
11
11
|
<app-root></app-root>
|
|
12
|
-
<script src="polyfills-5CFQRCPP.js" type="module"></script><script src="main-
|
|
12
|
+
<script src="polyfills-5CFQRCPP.js" type="module"></script><script src="main-A5ZTTMFS.js" type="module"></script></body>
|
|
13
13
|
</html>
|