@ibgib/vcs-gib 0.0.17 → 0.0.18
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/dist/AUTO-GENERATED-version.d.mts +1 -1
- package/dist/AUTO-GENERATED-version.mjs +1 -1
- package/dist/bootstrap/node-bootstrap.d.mts.map +1 -1
- package/dist/bootstrap/node-bootstrap.mjs +3 -0
- package/dist/bootstrap/node-bootstrap.mjs.map +1 -1
- package/dist/bootstrap/{node-bootstrap.respec.node.d.mts → node-bootstrap.respec.d.mts} +1 -1
- package/dist/bootstrap/node-bootstrap.respec.d.mts.map +1 -0
- package/dist/bootstrap/{node-bootstrap.respec.node.mjs → node-bootstrap.respec.mjs} +1 -1
- package/dist/bootstrap/node-bootstrap.respec.mjs.map +1 -0
- package/dist/cli/{cli-arg-parser.respec.node.d.mts → cli-arg-parser.respec.d.mts} +1 -1
- package/dist/cli/cli-arg-parser.respec.d.mts.map +1 -0
- package/dist/cli/{cli-arg-parser.respec.node.mjs → cli-arg-parser.respec.mjs} +1 -1
- package/dist/cli/cli-arg-parser.respec.mjs.map +1 -0
- package/dist/cli/cli-constants.d.mts +1 -0
- package/dist/cli/cli-constants.d.mts.map +1 -1
- package/dist/cli/cli-constants.mjs +1 -0
- package/dist/cli/cli-constants.mjs.map +1 -1
- package/dist/cli/{cli-e2e.respec.node.d.mts → cli-e2e.respec.d.mts} +1 -1
- package/dist/cli/cli-e2e.respec.d.mts.map +1 -0
- package/dist/cli/{cli-e2e.respec.node.mjs → cli-e2e.respec.mjs} +1 -1
- package/dist/cli/cli-e2e.respec.mjs.map +1 -0
- package/dist/cli/commands/add-cmd.d.mts.map +1 -1
- package/dist/cli/commands/add-cmd.mjs +2 -2
- package/dist/cli/commands/add-cmd.mjs.map +1 -1
- package/dist/cli/commands/{branch-checkout-cmd.respec.node.d.mts → branch-checkout-cmd.respec.d.mts} +1 -1
- package/dist/cli/commands/branch-checkout-cmd.respec.d.mts.map +1 -0
- package/dist/cli/commands/{branch-checkout-cmd.respec.node.mjs → branch-checkout-cmd.respec.mjs} +103 -9
- package/dist/cli/commands/branch-checkout-cmd.respec.mjs.map +1 -0
- package/dist/cli/commands/branch-cmd.d.mts.map +1 -1
- package/dist/cli/commands/branch-cmd.mjs +2 -2
- package/dist/cli/commands/branch-cmd.mjs.map +1 -1
- package/dist/cli/commands/checkout-cmd.d.mts.map +1 -1
- package/dist/cli/commands/checkout-cmd.mjs +15 -7
- package/dist/cli/commands/checkout-cmd.mjs.map +1 -1
- package/dist/cli/commands/commit-cmd.d.mts.map +1 -1
- package/dist/cli/commands/commit-cmd.mjs +2 -2
- package/dist/cli/commands/commit-cmd.mjs.map +1 -1
- package/dist/cli/commands/{commit-log-cmd.respec.node.d.mts → commit-log-cmd.respec.d.mts} +1 -1
- package/dist/cli/commands/commit-log-cmd.respec.d.mts.map +1 -0
- package/dist/cli/commands/{commit-log-cmd.respec.node.mjs → commit-log-cmd.respec.mjs} +1 -1
- package/dist/cli/commands/commit-log-cmd.respec.mjs.map +1 -0
- package/dist/cli/commands/{init-cmd.respec.node.d.mts → init-cmd.respec.d.mts} +1 -1
- package/dist/cli/commands/init-cmd.respec.d.mts.map +1 -0
- package/dist/cli/commands/{init-cmd.respec.node.mjs → init-cmd.respec.mjs} +1 -1
- package/dist/cli/commands/init-cmd.respec.mjs.map +1 -0
- package/dist/cli/commands/merge-cmd.d.mts +23 -0
- package/dist/cli/commands/merge-cmd.d.mts.map +1 -0
- package/dist/cli/commands/merge-cmd.mjs +224 -0
- package/dist/cli/commands/merge-cmd.mjs.map +1 -0
- package/dist/cli/commands/{reset-restore-cmd.respec.node.d.mts → reset-restore-cmd.respec.d.mts} +1 -1
- package/dist/cli/commands/reset-restore-cmd.respec.d.mts.map +1 -0
- package/dist/cli/commands/{reset-restore-cmd.respec.node.mjs → reset-restore-cmd.respec.mjs} +1 -1
- package/dist/cli/commands/reset-restore-cmd.respec.mjs.map +1 -0
- package/dist/cli/commands/{status-add-cmd.respec.node.d.mts → status-add-cmd.respec.d.mts} +1 -1
- package/dist/cli/commands/status-add-cmd.respec.d.mts.map +1 -0
- package/dist/cli/commands/{status-add-cmd.respec.node.mjs → status-add-cmd.respec.mjs} +1 -1
- package/dist/cli/commands/status-add-cmd.respec.mjs.map +1 -0
- package/dist/cli/vcs-cli-main.d.mts.map +1 -1
- package/dist/cli/vcs-cli-main.mjs +7 -0
- package/dist/cli/vcs-cli-main.mjs.map +1 -1
- package/dist/engine/branch/{branch-space.respec.node.d.mts → branch-space.respec.d.mts} +1 -1
- package/dist/engine/branch/branch-space.respec.d.mts.map +1 -0
- package/dist/engine/branch/{branch-space.respec.node.mjs → branch-space.respec.mjs} +1 -1
- package/dist/engine/branch/branch-space.respec.mjs.map +1 -0
- package/dist/engine/diff/{line-diff-helper.respec.node.d.mts → line-diff-helper.respec.d.mts} +1 -1
- package/dist/engine/diff/line-diff-helper.respec.d.mts.map +1 -0
- package/dist/engine/diff/{line-diff-helper.respec.node.mjs → line-diff-helper.respec.mjs} +1 -1
- package/dist/engine/diff/line-diff-helper.respec.mjs.map +1 -0
- package/dist/engine/filter/{glob-helper.respec.node.d.mts → glob-helper.respec.d.mts} +1 -1
- package/dist/engine/filter/glob-helper.respec.d.mts.map +1 -0
- package/dist/engine/filter/{glob-helper.respec.node.mjs → glob-helper.respec.mjs} +1 -1
- package/dist/engine/filter/glob-helper.respec.mjs.map +1 -0
- package/dist/engine/item/{item.respec.node.d.mts → item.respec.d.mts} +1 -1
- package/dist/engine/item/item.respec.d.mts.map +1 -0
- package/dist/engine/item/{item.respec.node.mjs → item.respec.mjs} +1 -1
- package/dist/engine/item/item.respec.mjs.map +1 -0
- package/dist/engine/merge/b2tfs-3way-merge-strategy.d.mts +38 -0
- package/dist/engine/merge/b2tfs-3way-merge-strategy.d.mts.map +1 -0
- package/dist/engine/merge/b2tfs-3way-merge-strategy.mjs +593 -0
- package/dist/engine/merge/b2tfs-3way-merge-strategy.mjs.map +1 -0
- package/dist/engine/merge/b2tfs-merge-strategy.respec.d.mts +7 -0
- package/dist/engine/merge/b2tfs-merge-strategy.respec.d.mts.map +1 -0
- package/dist/engine/merge/b2tfs-merge-strategy.respec.mjs +335 -0
- package/dist/engine/merge/b2tfs-merge-strategy.respec.mjs.map +1 -0
- package/dist/respec-gib.node.mjs +1 -1
- package/dist/respec-gib.node.mjs.map +1 -1
- package/dist/{vcs-gib.respec.node.d.mts → vcs-gib.respec.d.mts} +1 -1
- package/dist/vcs-gib.respec.d.mts.map +1 -0
- package/dist/{vcs-gib.respec.node.mjs → vcs-gib.respec.mjs} +1 -1
- package/dist/vcs-gib.respec.mjs.map +1 -0
- package/package.json +3 -3
- package/src/AUTO-GENERATED-version.mts +1 -1
- package/src/bootstrap/node-bootstrap.mts +4 -0
- package/src/cli/cli-constants.mts +1 -0
- package/src/cli/commands/add-cmd.mts +5 -3
- package/src/cli/commands/{branch-checkout-cmd.respec.node.mts → branch-checkout-cmd.respec.mts} +112 -9
- package/src/cli/commands/branch-cmd.mts +3 -2
- package/src/cli/commands/checkout-cmd.mts +23 -9
- package/src/cli/commands/commit-cmd.mts +5 -3
- package/src/cli/commands/merge-cmd.mts +289 -0
- package/src/cli/vcs-cli-main.mts +7 -0
- package/src/engine/merge/b2tfs-3way-merge-strategy.mts +725 -0
- package/src/engine/merge/b2tfs-merge-strategy.respec.mts +438 -0
- package/src/respec-gib.node.mts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/bootstrap/node-bootstrap.respec.node.d.mts.map +0 -1
- package/dist/bootstrap/node-bootstrap.respec.node.mjs.map +0 -1
- package/dist/cli/cli-arg-parser.respec.node.d.mts.map +0 -1
- package/dist/cli/cli-arg-parser.respec.node.mjs.map +0 -1
- package/dist/cli/cli-e2e.respec.node.d.mts.map +0 -1
- package/dist/cli/cli-e2e.respec.node.mjs.map +0 -1
- package/dist/cli/commands/branch-checkout-cmd.respec.node.d.mts.map +0 -1
- package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs.map +0 -1
- package/dist/cli/commands/commit-log-cmd.respec.node.d.mts.map +0 -1
- package/dist/cli/commands/commit-log-cmd.respec.node.mjs.map +0 -1
- package/dist/cli/commands/init-cmd.respec.node.d.mts.map +0 -1
- package/dist/cli/commands/init-cmd.respec.node.mjs.map +0 -1
- package/dist/cli/commands/reset-restore-cmd.respec.node.d.mts.map +0 -1
- package/dist/cli/commands/reset-restore-cmd.respec.node.mjs.map +0 -1
- package/dist/cli/commands/status-add-cmd.respec.node.d.mts.map +0 -1
- package/dist/cli/commands/status-add-cmd.respec.node.mjs.map +0 -1
- package/dist/engine/branch/branch-space.respec.node.d.mts.map +0 -1
- package/dist/engine/branch/branch-space.respec.node.mjs.map +0 -1
- package/dist/engine/diff/line-diff-helper.respec.node.d.mts.map +0 -1
- package/dist/engine/diff/line-diff-helper.respec.node.mjs.map +0 -1
- package/dist/engine/filter/glob-helper.respec.node.d.mts.map +0 -1
- package/dist/engine/filter/glob-helper.respec.node.mjs.map +0 -1
- package/dist/engine/item/item.respec.node.d.mts.map +0 -1
- package/dist/engine/item/item.respec.node.mjs.map +0 -1
- package/dist/vcs-gib.respec.node.d.mts.map +0 -1
- package/dist/vcs-gib.respec.node.mjs.map +0 -1
- /package/src/bootstrap/{node-bootstrap.respec.node.mts → node-bootstrap.respec.mts} +0 -0
- /package/src/cli/{cli-arg-parser.respec.node.mts → cli-arg-parser.respec.mts} +0 -0
- /package/src/cli/{cli-e2e.respec.node.mts → cli-e2e.respec.mts} +0 -0
- /package/src/cli/commands/{commit-log-cmd.respec.node.mts → commit-log-cmd.respec.mts} +0 -0
- /package/src/cli/commands/{init-cmd.respec.node.mts → init-cmd.respec.mts} +0 -0
- /package/src/cli/commands/{reset-restore-cmd.respec.node.mts → reset-restore-cmd.respec.mts} +0 -0
- /package/src/cli/commands/{status-add-cmd.respec.node.mts → status-add-cmd.respec.mts} +0 -0
- /package/src/engine/branch/{branch-space.respec.node.mts → branch-space.respec.mts} +0 -0
- /package/src/engine/diff/{line-diff-helper.respec.node.mts → line-diff-helper.respec.mts} +0 -0
- /package/src/engine/filter/{glob-helper.respec.node.mts → glob-helper.respec.mts} +0 -0
- /package/src/engine/item/{item.respec.node.mts → item.respec.mts} +0 -0
- /package/src/{vcs-gib.respec.node.mts → vcs-gib.respec.mts} +0 -0
package/src/cli/commands/{branch-checkout-cmd.respec.node.mts → branch-checkout-cmd.respec.mts}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module branch-checkout-cmd.respec
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Unit tests for `vcs branch` and `vcs checkout` command handlers & worktree projections.
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -8,7 +8,8 @@ import path from 'node:path';
|
|
|
8
8
|
import fs from 'node:fs/promises';
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
-
respecfully, ifWe, iReckon
|
|
11
|
+
respecfully, ifWe, iReckon,
|
|
12
|
+
ifWeMight
|
|
12
13
|
} from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
|
|
13
14
|
|
|
14
15
|
import { executeInitCmd } from './init-cmd.mjs';
|
|
@@ -16,13 +17,14 @@ import { executeAddCmd } from './add-cmd.mjs';
|
|
|
16
17
|
import { executeCommitCmd } from './commit-cmd.mjs';
|
|
17
18
|
import { executeBranchCmd } from './branch-cmd.mjs';
|
|
18
19
|
import { executeCheckoutCmd } from './checkout-cmd.mjs';
|
|
20
|
+
import { executeMergeCmd } from './merge-cmd.mjs';
|
|
19
21
|
import { executeStatusCmd } from './status-cmd.mjs';
|
|
20
22
|
|
|
21
23
|
const lc = `[apps/vcs-gib/src/cli/commands/branch-checkout-cmd.respec.node.mts]`;
|
|
22
24
|
|
|
23
|
-
await respecfully(lc, `vcs branch and
|
|
25
|
+
await respecfully(lc, `vcs branch, checkout, and merge Command Handlers`, async () => {
|
|
24
26
|
|
|
25
|
-
await
|
|
27
|
+
await ifWeMight(lc, `lists default branch main for new repository`, async () => {
|
|
26
28
|
const testDir = path.join(process.cwd(), '.test_branch_checkout_1');
|
|
27
29
|
const vcsFolderName = '.vcsgib_test_bc_1';
|
|
28
30
|
try {
|
|
@@ -46,7 +48,7 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
46
48
|
}
|
|
47
49
|
});
|
|
48
50
|
|
|
49
|
-
await
|
|
51
|
+
await ifWeMight(lc, `creates new branch from active branch root item and rejects duplicates`, async () => {
|
|
50
52
|
const testDir = path.join(process.cwd(), '.test_branch_checkout_2');
|
|
51
53
|
const vcsFolderName = '.vcsgib_test_bc_2';
|
|
52
54
|
try {
|
|
@@ -110,7 +112,7 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
110
112
|
}
|
|
111
113
|
});
|
|
112
114
|
|
|
113
|
-
await
|
|
115
|
+
await ifWeMight(lc, `switches active branch with checkout and projects branch snapshot onto worktree subfolder`, async () => {
|
|
114
116
|
const testDir = path.join(process.cwd(), '.test_branch_checkout_3');
|
|
115
117
|
const vcsFolderName = '.vcsgib_test_bc_3';
|
|
116
118
|
try {
|
|
@@ -236,7 +238,7 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
236
238
|
}
|
|
237
239
|
});
|
|
238
240
|
|
|
239
|
-
await
|
|
241
|
+
await ifWeMight(lc, `rejects checkout when branch does not exist or branchName missing`, async () => {
|
|
240
242
|
const testDir = path.join(process.cwd(), '.test_branch_checkout_4');
|
|
241
243
|
const vcsFolderName = '.vcsgib_test_bc_4';
|
|
242
244
|
try {
|
|
@@ -278,7 +280,7 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
278
280
|
}
|
|
279
281
|
});
|
|
280
282
|
|
|
281
|
-
await
|
|
283
|
+
await ifWeMight(lc, `lists branches silently on secondary branch without error noise`, async () => {
|
|
282
284
|
const testDir = path.join(process.cwd(), '.test_branch_checkout_secondary');
|
|
283
285
|
const vcsFolderName = '.vcsgib_test_bc_sec';
|
|
284
286
|
try {
|
|
@@ -320,7 +322,7 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
320
322
|
}
|
|
321
323
|
});
|
|
322
324
|
|
|
323
|
-
await
|
|
325
|
+
await ifWeMight(lc, `branches single file-root item and projects into file-branch worktree on checkout`, async () => {
|
|
324
326
|
const testDir = path.join(process.cwd(), '.test_branch_checkout_file_root');
|
|
325
327
|
const vcsFolderName = '.vcsgib_test_bc_file';
|
|
326
328
|
try {
|
|
@@ -398,4 +400,105 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
398
400
|
await fs.rm(testDir, { recursive: true, force: true });
|
|
399
401
|
}
|
|
400
402
|
});
|
|
403
|
+
|
|
404
|
+
await ifWeMight(lc, `performs vcs merge end-to-end between main and secondary branch`, async () => {
|
|
405
|
+
const testDir = path.join(process.cwd(), '.test_vcs_merge_e2e');
|
|
406
|
+
const vcsFolderName = '.vcsgib_test_merge_e2e';
|
|
407
|
+
try {
|
|
408
|
+
await executeInitCmd({
|
|
409
|
+
targetDir: testDir,
|
|
410
|
+
vcsFolderName,
|
|
411
|
+
quiet: true,
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// 1. Initial commit on main
|
|
415
|
+
const initialContent = "line 1\nline 2\nline 3";
|
|
416
|
+
await fs.writeFile(path.join(testDir, 'app.ts'), initialContent, 'utf8');
|
|
417
|
+
await executeAddCmd({
|
|
418
|
+
paths: [path.join(testDir, 'app.ts')],
|
|
419
|
+
targetDir: testDir,
|
|
420
|
+
vcsFolderName,
|
|
421
|
+
quiet: true,
|
|
422
|
+
});
|
|
423
|
+
await executeCommitCmd({
|
|
424
|
+
message: 'Initial commit on main',
|
|
425
|
+
targetDir: testDir,
|
|
426
|
+
vcsFolderName,
|
|
427
|
+
quiet: true,
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// 2. Create secondary branch feature-merge
|
|
431
|
+
await executeBranchCmd({
|
|
432
|
+
branchName: 'feature-merge',
|
|
433
|
+
targetDir: testDir,
|
|
434
|
+
vcsFolderName,
|
|
435
|
+
quiet: true,
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
// 3. Checkout feature-merge branch and make a commit (modify line 3)
|
|
439
|
+
await executeCheckoutCmd({
|
|
440
|
+
branchName: 'feature-merge',
|
|
441
|
+
targetDir: testDir,
|
|
442
|
+
vcsFolderName,
|
|
443
|
+
quiet: true,
|
|
444
|
+
});
|
|
445
|
+
const featureWorktree = path.join(testDir, 'b', 'feature-merge');
|
|
446
|
+
const featureContent = "line 1\nline 2\nline 3 modified by secondary";
|
|
447
|
+
await fs.writeFile(path.join(featureWorktree, 'app.ts'), featureContent, 'utf8');
|
|
448
|
+
await executeAddCmd({
|
|
449
|
+
paths: [path.join(featureWorktree, 'app.ts')],
|
|
450
|
+
targetDir: testDir,
|
|
451
|
+
vcsFolderName,
|
|
452
|
+
quiet: true,
|
|
453
|
+
});
|
|
454
|
+
await executeCommitCmd({
|
|
455
|
+
message: 'Update app.ts on feature-merge',
|
|
456
|
+
targetDir: testDir,
|
|
457
|
+
vcsFolderName,
|
|
458
|
+
quiet: true,
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// 4. Checkout main branch and make a commit (modify line 1)
|
|
462
|
+
await executeCheckoutCmd({
|
|
463
|
+
branchName: 'main',
|
|
464
|
+
targetDir: testDir,
|
|
465
|
+
vcsFolderName,
|
|
466
|
+
quiet: true,
|
|
467
|
+
});
|
|
468
|
+
const mainContent = "line 1 modified by main\nline 2\nline 3";
|
|
469
|
+
await fs.writeFile(path.join(testDir, 'app.ts'), mainContent, 'utf8');
|
|
470
|
+
await executeAddCmd({
|
|
471
|
+
paths: [path.join(testDir, 'app.ts')],
|
|
472
|
+
targetDir: testDir,
|
|
473
|
+
vcsFolderName,
|
|
474
|
+
quiet: true,
|
|
475
|
+
});
|
|
476
|
+
await executeCommitCmd({
|
|
477
|
+
message: 'Update app.ts on main',
|
|
478
|
+
targetDir: testDir,
|
|
479
|
+
vcsFolderName,
|
|
480
|
+
quiet: true,
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// 5. Execute vcs merge feature-merge into main
|
|
484
|
+
const mergeRes = await executeMergeCmd({
|
|
485
|
+
targetBranchName: 'feature-merge',
|
|
486
|
+
targetDir: testDir,
|
|
487
|
+
vcsFolderName,
|
|
488
|
+
quiet: true,
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
iReckon(lc, mergeRes.activeBranch).willEqual('main');
|
|
492
|
+
iReckon(lc, mergeRes.targetBranch).willEqual('feature-merge');
|
|
493
|
+
|
|
494
|
+
// 6. Verify projected file on physical worktree disk contains merged lines
|
|
495
|
+
const mergedAppTs = await fs.readFile(path.join(testDir, 'app.ts'), 'utf8');
|
|
496
|
+
iReckon(lc, mergedAppTs).includes('line 1 modified by main');
|
|
497
|
+
iReckon(lc, mergedAppTs).includes('line 2');
|
|
498
|
+
iReckon(lc, mergedAppTs).includes('line 3 modified by secondary');
|
|
499
|
+
} finally {
|
|
500
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
501
|
+
}
|
|
502
|
+
});
|
|
401
503
|
});
|
|
504
|
+
|
|
@@ -124,7 +124,7 @@ export async function executeBranchCmd({
|
|
|
124
124
|
const branches: BranchInfo[] = [];
|
|
125
125
|
for (const [name, bNode] of branchMap.entries()) {
|
|
126
126
|
const addr = getIbGibAddr({ ibGib: bNode });
|
|
127
|
-
const rootItemAddr = bNode.rel8ns?.b2tfs_item?.at(
|
|
127
|
+
const rootItemAddr = bNode.rel8ns?.b2tfs_item?.at(-1);
|
|
128
128
|
const isActive = name === activeBranchName;
|
|
129
129
|
branches.push({
|
|
130
130
|
name,
|
|
@@ -142,6 +142,7 @@ export async function executeBranchCmd({
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
return { branches };
|
|
145
|
+
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
// CREATE BRANCH
|
|
@@ -151,7 +152,7 @@ export async function executeBranchCmd({
|
|
|
151
152
|
|
|
152
153
|
// Find active branch root item to fork from
|
|
153
154
|
const activeBranchIbGib = branchMap.get(activeBranchName) || branchIbGibs.at(0);
|
|
154
|
-
const rootItemAddr = activeBranchIbGib?.rel8ns?.b2tfs_item?.at(
|
|
155
|
+
const rootItemAddr = activeBranchIbGib?.rel8ns?.b2tfs_item?.at(-1);
|
|
155
156
|
|
|
156
157
|
if (!rootItemAddr) {
|
|
157
158
|
throw new Error(`Cannot find active branch root item to fork branch from (E: 8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c)`);
|
|
@@ -11,7 +11,8 @@ import fs from 'node:fs/promises';
|
|
|
11
11
|
import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
12
12
|
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
13
13
|
import { getIbGibsFromCache_fallbackToSpaces } from '@ibgib/core-gib/dist/common/other/ibgib-helper.mjs';
|
|
14
|
-
import { putInSpace } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
|
|
14
|
+
import { putInSpace, getLatestAddrs } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
|
|
15
|
+
|
|
15
16
|
|
|
16
17
|
import { bootstrapVcsMetaspace } from '../../bootstrap/node-bootstrap.mjs';
|
|
17
18
|
import { B2tFSBranchIbGib_V1 } from '../../engine/branch/branch-types.mjs';
|
|
@@ -100,21 +101,15 @@ export async function executeCheckoutCmd({
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
// Find target branch node
|
|
103
|
-
const targetBranchIbGib = branchIbGibs.
|
|
104
|
+
const targetBranchIbGib = branchIbGibs.findLast(
|
|
104
105
|
(b) => b?.data?.name === trimmedBranchName,
|
|
105
106
|
);
|
|
106
107
|
|
|
108
|
+
|
|
107
109
|
if (!targetBranchIbGib) {
|
|
108
110
|
throw new Error(`Branch '${trimmedBranchName}' does not exist (E: 7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a)`);
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
const targetBranchAddr = getIbGibAddr({ ibGib: targetBranchIbGib });
|
|
112
|
-
const rootItemAddr = targetBranchIbGib.rel8ns?.b2tfs_item?.at(0);
|
|
113
|
-
|
|
114
|
-
if (!rootItemAddr) {
|
|
115
|
-
throw new Error(`Branch '${trimmedBranchName}' does not have a valid root item address (E: 8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b)`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
113
|
// 3. Resolve target branch space b2s_<branchName>
|
|
119
114
|
const targetBranchSpaceRes = await getOrCreateBranchSpace({
|
|
120
115
|
metaspace,
|
|
@@ -123,6 +118,25 @@ export async function executeCheckoutCmd({
|
|
|
123
118
|
});
|
|
124
119
|
const targetBranchSpace = targetBranchSpaceRes.space;
|
|
125
120
|
|
|
121
|
+
const targetBranchAddr = getIbGibAddr({ ibGib: targetBranchIbGib });
|
|
122
|
+
const targetBranchTjpAddr = targetBranchIbGib.rel8ns?.tjp?.at(0) || targetBranchAddr;
|
|
123
|
+
const latestTargetBranchRes = await getLatestAddrs({ space: targetBranchSpace, addrs: [targetBranchTjpAddr] });
|
|
124
|
+
const latestTargetBranchAddr = (latestTargetBranchRes?.data as any)?.latestAddrs?.[0] || targetBranchAddr;
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
const latestTargetBranchIbGib = (await getIbGibWithMetaspaceFallback({
|
|
128
|
+
addr: latestTargetBranchAddr,
|
|
129
|
+
space: targetBranchSpace,
|
|
130
|
+
metaspace,
|
|
131
|
+
})) as B2tFSBranchIbGib_V1 || targetBranchIbGib;
|
|
132
|
+
|
|
133
|
+
const rootItemAddr = latestTargetBranchIbGib.rel8ns?.b2tfs_item?.at(-1);
|
|
134
|
+
|
|
135
|
+
if (!rootItemAddr) {
|
|
136
|
+
throw new Error(`Branch '${trimmedBranchName}' does not have a valid root item address (E: 8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b)`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
126
140
|
await putInSpace({ space: targetBranchSpace, ibGib: targetBranchIbGib });
|
|
127
141
|
|
|
128
142
|
// Update activeBranch in B2tFSIndexIbGib_V1 in targetBranchSpace and localSpace
|
|
@@ -129,16 +129,18 @@ export async function executeCommitCmd({
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
currentBranchIbGib = branchIbGibs.
|
|
132
|
+
currentBranchIbGib = branchIbGibs.findLast(
|
|
133
133
|
(b) => (b as B2tFSBranchIbGib_V1)?.data?.name === branchName,
|
|
134
|
-
) as B2tFSBranchIbGib_V1 || (branchIbGibs.at(
|
|
134
|
+
) as B2tFSBranchIbGib_V1 || (branchIbGibs.at(-1) as B2tFSBranchIbGib_V1);
|
|
135
|
+
|
|
135
136
|
|
|
136
137
|
if (currentBranchIbGib) {
|
|
137
138
|
currentBranchAddr = getIbGibAddr({ ibGib: currentBranchIbGib });
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
const currentRootAddr = currentBranchIbGib?.rel8ns?.b2tfs_item?.at(
|
|
142
|
+
const currentRootAddr = currentBranchIbGib?.rel8ns?.b2tfs_item?.at(-1);
|
|
143
|
+
|
|
142
144
|
|
|
143
145
|
// 1. Create CommentIbGib_V1 commit comment node in activeSpace
|
|
144
146
|
const commentRes = await createCommentIbGib({
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module merge-cmd
|
|
3
|
+
*
|
|
4
|
+
* Command handler for `vcs merge <branchName>`.
|
|
5
|
+
* Merges target branch into active branch using SyncSagaCoordinator sync and 3-way graft merge strategy.
|
|
6
|
+
* Projects merged branch snapshot onto active branch physical worktree path.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import fs from 'node:fs/promises';
|
|
11
|
+
|
|
12
|
+
import { clone, extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
13
|
+
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
14
|
+
import { rel8 } from '@ibgib/ts-gib/dist/V1/transforms/rel8.mjs';
|
|
15
|
+
import { putInSpace, getLatestAddrs, getFromSpace, registerNewIbGib } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
|
|
16
|
+
import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
|
|
17
|
+
import { SyncPeerInnerspace_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs';
|
|
18
|
+
import { SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs';
|
|
19
|
+
import { SyncConflictStrategy } from '@ibgib/core-gib/dist/sync/sync-constants.mjs';
|
|
20
|
+
import { GraftPreference } from '@ibgib/core-gib/dist/sync/graft-info/graft-info-types.mjs';
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
import { bootstrapVcsMetaspace } from '../../bootstrap/node-bootstrap.mjs';
|
|
24
|
+
import { B2tFSBranchIbGib_V1 } from '../../engine/branch/branch-types.mjs';
|
|
25
|
+
import { getOrCreateBranchSpace } from '../../engine/branch/branch-space-helper.mjs';
|
|
26
|
+
import { B2tFSItemIbGib_V1, B2TFS_CHILD_ITEM_REL8N_NAME } from '../../engine/item/item-types.mjs';
|
|
27
|
+
import { writeB2tFSItemToFS, getIbGibWithMetaspaceFallback } from '../../engine/item/item-helper.mjs';
|
|
28
|
+
import { getB2tFSIndexIbGib, updateB2tFSIndexIbGib } from '../../engine/index/index-helper.mjs';
|
|
29
|
+
import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
|
|
30
|
+
|
|
31
|
+
const lcFile = `[merge-cmd]`;
|
|
32
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
33
|
+
|
|
34
|
+
export interface MergeCmdOpts {
|
|
35
|
+
targetBranchName?: string;
|
|
36
|
+
targetDir?: string;
|
|
37
|
+
vcsFolderName?: string;
|
|
38
|
+
quiet?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface MergeCmdResult {
|
|
42
|
+
activeBranch: string;
|
|
43
|
+
targetBranch: string;
|
|
44
|
+
activeSpaceId: string;
|
|
45
|
+
targetSpaceId: string;
|
|
46
|
+
mergedBranchAddr?: string;
|
|
47
|
+
worktreePath: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function executeMergeCmd({
|
|
51
|
+
targetBranchName,
|
|
52
|
+
targetDir = process.cwd(),
|
|
53
|
+
vcsFolderName = '.vcsgib',
|
|
54
|
+
quiet = false,
|
|
55
|
+
}: MergeCmdOpts = {}): Promise<MergeCmdResult> {
|
|
56
|
+
const lc = `${lcFile}[${executeMergeCmd.name}]`;
|
|
57
|
+
try {
|
|
58
|
+
if (logalot) {
|
|
59
|
+
console.log(`${lc} starting... (I: 4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f)`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const trimmedTargetBranch = targetBranchName?.trim();
|
|
63
|
+
if (!trimmedTargetBranch) {
|
|
64
|
+
throw new Error(`Branch name is required for merge (E: 5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a)`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const absTargetDir = path.resolve(targetDir);
|
|
68
|
+
|
|
69
|
+
const { metaspace, localSpace, repoRoot, vcsPath } = await bootstrapVcsMetaspace({
|
|
70
|
+
repoPath: absTargetDir,
|
|
71
|
+
vcsFolderName,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Verify repo exists
|
|
75
|
+
try {
|
|
76
|
+
await fs.access(vcsPath);
|
|
77
|
+
} catch {
|
|
78
|
+
throw new Error(`Not an ibgib repository (directory ${vcsPath} does not exist) (E: 6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b)`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 1. Fetch authoritative repository index from localSpace
|
|
82
|
+
const indexIbGib = await getB2tFSIndexIbGib({ space: localSpace, vcsPath });
|
|
83
|
+
if (!indexIbGib) {
|
|
84
|
+
throw new Error(`Repository index B2tFSIndexIbGib_V1 not found in localSpace (E: 7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c)`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const activeBranchName = indexIbGib.data?.activeBranch || 'main';
|
|
88
|
+
|
|
89
|
+
if (activeBranchName === trimmedTargetBranch) {
|
|
90
|
+
throw new Error(`Cannot merge branch '${trimmedTargetBranch}' into itself (E: 8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d)`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 2. Fetch all registered branch ibgibs
|
|
94
|
+
const branchAddrs = [
|
|
95
|
+
...(indexIbGib.rel8ns?.branch || []),
|
|
96
|
+
...(indexIbGib.rel8ns?.branch_tjp || []),
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
let branchIbGibs: B2tFSBranchIbGib_V1[] = [];
|
|
100
|
+
if (branchAddrs.length > 0) {
|
|
101
|
+
for (const bAddr of branchAddrs) {
|
|
102
|
+
const bIbGib = await getIbGibWithMetaspaceFallback({
|
|
103
|
+
addr: bAddr,
|
|
104
|
+
space: localSpace,
|
|
105
|
+
metaspace,
|
|
106
|
+
});
|
|
107
|
+
if (bIbGib) {
|
|
108
|
+
branchIbGibs.push(bIbGib as B2tFSBranchIbGib_V1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Resolve active branch node & target branch node
|
|
114
|
+
const activeBranchIbGib = branchIbGibs.findLast(
|
|
115
|
+
(b) => b?.data?.name === activeBranchName,
|
|
116
|
+
);
|
|
117
|
+
if (!activeBranchIbGib) {
|
|
118
|
+
throw new Error(`Active branch '${activeBranchName}' not found in repository (E: 9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e)`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const targetBranchIbGib = branchIbGibs.findLast(
|
|
122
|
+
(b) => b?.data?.name === trimmedTargetBranch,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (!targetBranchIbGib) {
|
|
126
|
+
throw new Error(`Branch '${trimmedTargetBranch}' does not exist (E: 0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f)`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 3. Resolve active branch space & target branch space
|
|
130
|
+
const activeSpaceRes = await getOrCreateBranchSpace({
|
|
131
|
+
metaspace,
|
|
132
|
+
vcsPath,
|
|
133
|
+
branchName: activeBranchName,
|
|
134
|
+
});
|
|
135
|
+
const activeSpace = activeSpaceRes.space;
|
|
136
|
+
|
|
137
|
+
const targetSpaceRes = await getOrCreateBranchSpace({
|
|
138
|
+
metaspace,
|
|
139
|
+
vcsPath,
|
|
140
|
+
branchName: trimmedTargetBranch,
|
|
141
|
+
});
|
|
142
|
+
const targetSpace = targetSpaceRes.space;
|
|
143
|
+
|
|
144
|
+
await putInSpace({ space: activeSpace, ibGib: activeBranchIbGib });
|
|
145
|
+
await putInSpace({ space: targetSpace, ibGib: targetBranchIbGib });
|
|
146
|
+
|
|
147
|
+
// Resolve latest branch tip inside targetSpace (in case commits occurred on target branch)
|
|
148
|
+
const targetBranchTjpAddr = targetBranchIbGib.rel8ns?.tjp?.at(0) || getIbGibAddr({ ibGib: targetBranchIbGib });
|
|
149
|
+
const latestTargetBranchRes = await getLatestAddrs({ space: targetSpace, addrs: [targetBranchTjpAddr] });
|
|
150
|
+
const latestTargetBranchAddr = (latestTargetBranchRes?.data as any)?.latestAddrs?.[0] || getIbGibAddr({ ibGib: targetBranchIbGib });
|
|
151
|
+
|
|
152
|
+
const latestTargetBranchIbGib = (await getIbGibWithMetaspaceFallback({
|
|
153
|
+
addr: latestTargetBranchAddr,
|
|
154
|
+
space: targetSpace,
|
|
155
|
+
metaspace,
|
|
156
|
+
})) as B2tFSBranchIbGib_V1 || targetBranchIbGib;
|
|
157
|
+
|
|
158
|
+
const targetRootAddr = latestTargetBranchIbGib.rel8ns?.b2tfs_item?.at(-1);
|
|
159
|
+
|
|
160
|
+
if (!targetRootAddr) {
|
|
161
|
+
throw new Error(`Target branch '${trimmedTargetBranch}' has no valid root item address (E: 3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e)`);
|
|
162
|
+
}
|
|
163
|
+
const targetRootItem = await getIbGibWithMetaspaceFallback({
|
|
164
|
+
addr: targetRootAddr,
|
|
165
|
+
space: targetSpace,
|
|
166
|
+
metaspace,
|
|
167
|
+
});
|
|
168
|
+
if (!targetRootItem) {
|
|
169
|
+
throw new Error(`Target root item '${targetRootAddr}' not found in target space (E: 4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f)`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 4. Setup SyncPeerInnerspace and SyncSagaCoordinator syncing target branch space into active branch space
|
|
173
|
+
const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
|
|
174
|
+
await peer.initialized;
|
|
175
|
+
await peer.initializeOpts({
|
|
176
|
+
localMetaspace: metaspace,
|
|
177
|
+
localSpace: targetSpace,
|
|
178
|
+
receiverSpace: activeSpace,
|
|
179
|
+
receiverCoordinator: new SyncSagaCoordinator(),
|
|
180
|
+
receiverMetaspace: metaspace,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const senderCoordinator = new SyncSagaCoordinator();
|
|
184
|
+
const syncSaga = await senderCoordinator.sync({
|
|
185
|
+
peer,
|
|
186
|
+
localSpace: targetSpace,
|
|
187
|
+
metaspace,
|
|
188
|
+
domainIbGibs: [targetRootItem],
|
|
189
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
190
|
+
graftPreference: GraftPreference.receiver,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
await syncSaga.done;
|
|
197
|
+
|
|
198
|
+
// 5. Query activeSpace for updated active branch node & root item evolved natively by sync graft strategy
|
|
199
|
+
const activeBranchTjpAddr = activeBranchIbGib.rel8ns?.tjp?.at(0) || getIbGibAddr({ ibGib: activeBranchIbGib });
|
|
200
|
+
const latestBranchRes = await getLatestAddrs({ space: activeSpace, addrs: [activeBranchTjpAddr] });
|
|
201
|
+
const mergedBranchAddr = (latestBranchRes?.data as any)?.latestAddrs?.[0] || getIbGibAddr({ ibGib: activeBranchIbGib });
|
|
202
|
+
|
|
203
|
+
const mergedBranchIbGib = (await getIbGibWithMetaspaceFallback({
|
|
204
|
+
addr: mergedBranchAddr,
|
|
205
|
+
space: activeSpace,
|
|
206
|
+
metaspace,
|
|
207
|
+
})) as B2tFSBranchIbGib_V1 || activeBranchIbGib;
|
|
208
|
+
|
|
209
|
+
const mergedRootItemAddr = mergedBranchIbGib.rel8ns?.b2tfs_item?.at(-1);
|
|
210
|
+
|
|
211
|
+
// Update indexIbGib to reference new merged branch node
|
|
212
|
+
await updateB2tFSIndexIbGib({
|
|
213
|
+
space: activeSpace,
|
|
214
|
+
metaspace,
|
|
215
|
+
indexIbGib,
|
|
216
|
+
rel8nsToUpdate: {
|
|
217
|
+
branch: [mergedBranchAddr],
|
|
218
|
+
},
|
|
219
|
+
vcsPath,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
// 6. Project merged branch snapshot files onto physical worktree disk
|
|
224
|
+
const isDefaultBranch = activeBranchName === 'main';
|
|
225
|
+
const worktreePath = isDefaultBranch
|
|
226
|
+
? repoRoot
|
|
227
|
+
: path.join(repoRoot, 'b', activeBranchName);
|
|
228
|
+
|
|
229
|
+
await fs.mkdir(worktreePath, { recursive: true });
|
|
230
|
+
|
|
231
|
+
if (mergedRootItemAddr) {
|
|
232
|
+
const mergedRootItem = await getIbGibWithMetaspaceFallback({
|
|
233
|
+
addr: mergedRootItemAddr,
|
|
234
|
+
space: activeSpace,
|
|
235
|
+
metaspace,
|
|
236
|
+
}) as B2tFSItemIbGib_V1;
|
|
237
|
+
|
|
238
|
+
if (mergedRootItem) {
|
|
239
|
+
if (mergedRootItem.data?.fsType === 'file') {
|
|
240
|
+
await writeB2tFSItemToFS({
|
|
241
|
+
item: mergedRootItem,
|
|
242
|
+
destPath: worktreePath,
|
|
243
|
+
space: activeSpace,
|
|
244
|
+
metaspace,
|
|
245
|
+
});
|
|
246
|
+
} else {
|
|
247
|
+
const childAddrs = mergedRootItem.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
248
|
+
for (const childAddr of childAddrs) {
|
|
249
|
+
const childItem = await getIbGibWithMetaspaceFallback({
|
|
250
|
+
addr: childAddr,
|
|
251
|
+
space: activeSpace,
|
|
252
|
+
metaspace,
|
|
253
|
+
}) as B2tFSItemIbGib_V1;
|
|
254
|
+
|
|
255
|
+
if (childItem) {
|
|
256
|
+
await writeB2tFSItemToFS({
|
|
257
|
+
item: childItem,
|
|
258
|
+
destPath: worktreePath,
|
|
259
|
+
space: activeSpace,
|
|
260
|
+
metaspace,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (!quiet) {
|
|
269
|
+
console.log(`Successfully merged branch '${trimmedTargetBranch}' into '${activeBranchName}' (I: 1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a)`);
|
|
270
|
+
console.log(` Worktree projection: ${worktreePath}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
activeBranch: activeBranchName,
|
|
275
|
+
targetBranch: trimmedTargetBranch,
|
|
276
|
+
activeSpaceId: activeSpaceRes.spaceId,
|
|
277
|
+
targetSpaceId: targetSpaceRes.spaceId,
|
|
278
|
+
mergedBranchAddr: getIbGibAddr({ ibGib: mergedBranchIbGib }),
|
|
279
|
+
worktreePath,
|
|
280
|
+
};
|
|
281
|
+
} catch (error) {
|
|
282
|
+
console.error(`${lc} ${extractErrorMsg(error)} (E: 2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b)`);
|
|
283
|
+
throw error;
|
|
284
|
+
} finally {
|
|
285
|
+
if (logalot) {
|
|
286
|
+
console.log(`${lc} complete. (I: 3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c)`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
package/src/cli/vcs-cli-main.mts
CHANGED
|
@@ -17,6 +17,7 @@ import { executeCommitCmd } from './commands/commit-cmd.mjs';
|
|
|
17
17
|
import { executeLogCmd } from './commands/log-cmd.mjs';
|
|
18
18
|
import { executeBranchCmd } from './commands/branch-cmd.mjs';
|
|
19
19
|
import { executeCheckoutCmd } from './commands/checkout-cmd.mjs';
|
|
20
|
+
import { executeMergeCmd } from './commands/merge-cmd.mjs';
|
|
20
21
|
import { executeResetCmd } from './commands/reset-cmd.mjs';
|
|
21
22
|
import { executeRestoreCmd } from './commands/restore-cmd.mjs';
|
|
22
23
|
import { AUTO_GENERATED_VERSION } from '../AUTO-GENERATED-version.mjs';
|
|
@@ -44,6 +45,7 @@ Commands:
|
|
|
44
45
|
log Show commit logs
|
|
45
46
|
branch [name] List or create branches
|
|
46
47
|
checkout <branch> Switch to a specified branch and project worktree
|
|
48
|
+
merge <branch> Merge specified branch into active branch
|
|
47
49
|
reset [path...] Unstage specified files from index (-a, --all for all)
|
|
48
50
|
restore [path...] Restore working tree files or unstage (--staged)
|
|
49
51
|
|
|
@@ -120,6 +122,11 @@ export async function main({
|
|
|
120
122
|
await executeCheckoutCmd({ branchName });
|
|
121
123
|
break;
|
|
122
124
|
}
|
|
125
|
+
case VCS_SUBCOMMANDS.MERGE: {
|
|
126
|
+
const targetBranchName = parsed.positionals[0] || parsed.flags.branchName;
|
|
127
|
+
await executeMergeCmd({ targetBranchName });
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
123
130
|
case VCS_SUBCOMMANDS.RESET: {
|
|
124
131
|
await executeResetCmd({
|
|
125
132
|
paths: parsed.positionals,
|