@ibgib/vcs-gib 0.0.6 → 0.0.17

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.
Files changed (102) hide show
  1. package/README.md +24 -2
  2. package/VCS_CLI_USER_GUIDE.md +2 -2
  3. package/dist/AUTO-GENERATED-version.d.mts +1 -1
  4. package/dist/AUTO-GENERATED-version.d.mts.map +1 -1
  5. package/dist/AUTO-GENERATED-version.mjs +1 -1
  6. package/dist/AUTO-GENERATED-version.mjs.map +1 -1
  7. package/dist/bootstrap/node-bootstrap.d.mts.map +1 -1
  8. package/dist/bootstrap/node-bootstrap.mjs +6 -0
  9. package/dist/bootstrap/node-bootstrap.mjs.map +1 -1
  10. package/dist/cli/cli-arg-parser.d.mts +3 -0
  11. package/dist/cli/cli-arg-parser.d.mts.map +1 -1
  12. package/dist/cli/cli-arg-parser.mjs +13 -1
  13. package/dist/cli/cli-arg-parser.mjs.map +1 -1
  14. package/dist/cli/cli-constants.d.mts +5 -0
  15. package/dist/cli/cli-constants.d.mts.map +1 -1
  16. package/dist/cli/cli-constants.mjs +23 -0
  17. package/dist/cli/cli-constants.mjs.map +1 -1
  18. package/dist/cli/cli-e2e.respec.node.mjs +1 -1
  19. package/dist/cli/cli-e2e.respec.node.mjs.map +1 -1
  20. package/dist/cli/commands/add-cmd.d.mts.map +1 -1
  21. package/dist/cli/commands/add-cmd.mjs +33 -28
  22. package/dist/cli/commands/add-cmd.mjs.map +1 -1
  23. package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs +70 -0
  24. package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs.map +1 -1
  25. package/dist/cli/commands/branch-cmd.d.mts +2 -1
  26. package/dist/cli/commands/branch-cmd.d.mts.map +1 -1
  27. package/dist/cli/commands/branch-cmd.mjs +57 -6
  28. package/dist/cli/commands/branch-cmd.mjs.map +1 -1
  29. package/dist/cli/commands/checkout-cmd.d.mts.map +1 -1
  30. package/dist/cli/commands/checkout-cmd.mjs +23 -11
  31. package/dist/cli/commands/checkout-cmd.mjs.map +1 -1
  32. package/dist/cli/commands/commit-cmd.d.mts.map +1 -1
  33. package/dist/cli/commands/commit-cmd.mjs +24 -21
  34. package/dist/cli/commands/commit-cmd.mjs.map +1 -1
  35. package/dist/cli/commands/reset-cmd.d.mts +21 -0
  36. package/dist/cli/commands/reset-cmd.d.mts.map +1 -0
  37. package/dist/cli/commands/reset-cmd.mjs +93 -0
  38. package/dist/cli/commands/reset-cmd.mjs.map +1 -0
  39. package/dist/cli/commands/reset-restore-cmd.respec.node.d.mts +7 -0
  40. package/dist/cli/commands/reset-restore-cmd.respec.node.d.mts.map +1 -0
  41. package/dist/cli/commands/reset-restore-cmd.respec.node.mjs +185 -0
  42. package/dist/cli/commands/reset-restore-cmd.respec.node.mjs.map +1 -0
  43. package/dist/cli/commands/restore-cmd.d.mts +22 -0
  44. package/dist/cli/commands/restore-cmd.d.mts.map +1 -0
  45. package/dist/cli/commands/restore-cmd.mjs +115 -0
  46. package/dist/cli/commands/restore-cmd.mjs.map +1 -0
  47. package/dist/cli/commands/status-add-cmd.respec.node.mjs +24 -0
  48. package/dist/cli/commands/status-add-cmd.respec.node.mjs.map +1 -1
  49. package/dist/cli/vcs-cli-main.d.mts.map +1 -1
  50. package/dist/cli/vcs-cli-main.mjs +29 -3
  51. package/dist/cli/vcs-cli-main.mjs.map +1 -1
  52. package/dist/engine/branch/branch-graph-helper.d.mts +12 -3
  53. package/dist/engine/branch/branch-graph-helper.d.mts.map +1 -1
  54. package/dist/engine/branch/branch-graph-helper.mjs +50 -18
  55. package/dist/engine/branch/branch-graph-helper.mjs.map +1 -1
  56. package/dist/engine/branch/branch-space-helper.d.mts +1 -0
  57. package/dist/engine/branch/branch-space-helper.d.mts.map +1 -1
  58. package/dist/engine/branch/branch-space-helper.mjs +1 -0
  59. package/dist/engine/branch/branch-space-helper.mjs.map +1 -1
  60. package/dist/engine/branch/branch-space.respec.node.mjs +11 -6
  61. package/dist/engine/branch/branch-space.respec.node.mjs.map +1 -1
  62. package/dist/engine/index/index-helper.d.mts +35 -0
  63. package/dist/engine/index/index-helper.d.mts.map +1 -1
  64. package/dist/engine/index/index-helper.mjs +241 -0
  65. package/dist/engine/index/index-helper.mjs.map +1 -1
  66. package/dist/engine/item/item-helper.d.mts +29 -3
  67. package/dist/engine/item/item-helper.d.mts.map +1 -1
  68. package/dist/engine/item/item-helper.mjs +234 -56
  69. package/dist/engine/item/item-helper.mjs.map +1 -1
  70. package/dist/engine/item/item.respec.node.d.mts +7 -0
  71. package/dist/engine/item/item.respec.node.d.mts.map +1 -0
  72. package/dist/engine/item/item.respec.node.mjs +75 -0
  73. package/dist/engine/item/item.respec.node.mjs.map +1 -0
  74. package/package.json +3 -3
  75. package/src/AUTO-GENERATED-version.mts +1 -1
  76. package/src/bootstrap/node-bootstrap.mts +2 -0
  77. package/src/cli/cli-arg-parser.mts +15 -0
  78. package/src/cli/cli-constants.mts +26 -0
  79. package/src/cli/cli-e2e.respec.node.mts +2 -2
  80. package/src/cli/commands/add-cmd.mts +36 -26
  81. package/src/cli/commands/branch-checkout-cmd.respec.node.mts +79 -0
  82. package/src/cli/commands/branch-cmd.mts +75 -6
  83. package/src/cli/commands/checkout-cmd.mts +25 -14
  84. package/src/cli/commands/commit-cmd.mts +30 -23
  85. package/src/cli/commands/reset-cmd.mts +128 -0
  86. package/src/cli/commands/reset-restore-cmd.respec.node.mts +222 -0
  87. package/src/cli/commands/restore-cmd.mts +155 -0
  88. package/src/cli/commands/status-add-cmd.respec.node.mts +27 -0
  89. package/src/cli/vcs-cli-main.mts +29 -3
  90. package/src/engine/branch/branch-graph-helper.mts +66 -18
  91. package/src/engine/branch/branch-space-helper.mts +6 -0
  92. package/src/engine/branch/branch-space.respec.node.mts +12 -6
  93. package/src/engine/index/index-helper.mts +324 -0
  94. package/src/engine/item/item-helper.mts +284 -58
  95. package/src/engine/item/item.respec.node.mts +92 -0
  96. package/tsconfig.tsbuildinfo +1 -1
  97. package/test_runs/001-hello-node/20260728_090100_0001-flow-core-main.md +0 -39
  98. package/test_runs/001-hello-node/20260728_090200_0003-flow-branching-worktree.md +0 -54
  99. package/test_runs/001-hello-node/20260728_090300_0002-flow-selective-add.md +0 -45
  100. package/test_runs/001-hello-node/20260728_142100_0007-flow-edge-cases.md +0 -44
  101. package/test_runs/001-hello-node/20260728_142400_0005-flow-hardcoded-ignores.md +0 -36
  102. package/tools/pack-for-test.mjs +0 -73
@@ -0,0 +1,222 @@
1
+ /**
2
+ * @module reset-restore-cmd.respec
3
+ *
4
+ * Unit tests for `vcs reset` and `vcs restore` command handlers.
5
+ */
6
+
7
+ import path from 'node:path';
8
+ import fs from 'node:fs/promises';
9
+
10
+ import {
11
+ respecfully, ifWe, iReckon
12
+ } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
13
+
14
+ import { executeInitCmd } from './init-cmd.mjs';
15
+ import { executeAddCmd } from './add-cmd.mjs';
16
+ import { executeCommitCmd } from './commit-cmd.mjs';
17
+ import { executeStatusCmd } from './status-cmd.mjs';
18
+ import { executeResetCmd } from './reset-cmd.mjs';
19
+ import { executeRestoreCmd } from './restore-cmd.mjs';
20
+
21
+ const lc = `[apps/vcs-gib/src/cli/commands/reset-restore-cmd.respec.node.mts]`;
22
+
23
+ await respecfully(lc, `vcs reset and vcs restore Command Handlers`, async () => {
24
+
25
+ await ifWe(lc, `vcs reset clears staged file from index while keeping disk file edits intact`, async () => {
26
+ const testDir = path.join(process.cwd(), '.test_reset_1');
27
+ const vcsFolderName = '.vcsgib_test_reset_1';
28
+ try {
29
+ await executeInitCmd({
30
+ targetDir: testDir,
31
+ vcsFolderName,
32
+ quiet: true,
33
+ });
34
+
35
+ await fs.writeFile(path.join(testDir, 'foo.txt'), 'Hello Foo', 'utf8');
36
+
37
+ await executeAddCmd({
38
+ paths: ['foo.txt'],
39
+ targetDir: testDir,
40
+ vcsFolderName,
41
+ quiet: true,
42
+ });
43
+
44
+ let statusRes = await executeStatusCmd({
45
+ targetDir: testDir,
46
+ vcsFolderName,
47
+ quiet: true,
48
+ });
49
+ iReckon(lc, statusRes.staged.map(x => x.path)).includes('foo.txt');
50
+
51
+ // Modify file on disk after staging
52
+ await fs.writeFile(path.join(testDir, 'foo.txt'), 'Hello Foo Modified', 'utf8');
53
+
54
+ // Execute reset
55
+ const resetRes = await executeResetCmd({
56
+ paths: ['foo.txt'],
57
+ targetDir: testDir,
58
+ vcsFolderName,
59
+ quiet: true,
60
+ });
61
+
62
+ iReckon(lc, resetRes.unstagedPaths).includes('foo.txt');
63
+
64
+ statusRes = await executeStatusCmd({
65
+ targetDir: testDir,
66
+ vcsFolderName,
67
+ quiet: true,
68
+ });
69
+
70
+ // Verify file is no longer staged
71
+ iReckon(lc, statusRes.staged.map(x => x.path)).not.includes('foo.txt');
72
+ iReckon(lc, statusRes.untracked.map(x => x.path)).includes('foo.txt');
73
+
74
+ // Verify disk content is still intact
75
+ const diskContent = await fs.readFile(path.join(testDir, 'foo.txt'), 'utf8');
76
+ iReckon(lc, diskContent).willEqual('Hello Foo Modified');
77
+ } finally {
78
+ await fs.rm(testDir, { recursive: true, force: true });
79
+ }
80
+ });
81
+
82
+ await ifWe(lc, `vcs restore --staged unstages file from index while keeping disk edits intact`, async () => {
83
+ const testDir = path.join(process.cwd(), '.test_restore_staged');
84
+ const vcsFolderName = '.vcsgib_test_restore_staged';
85
+ try {
86
+ await executeInitCmd({
87
+ targetDir: testDir,
88
+ vcsFolderName,
89
+ quiet: true,
90
+ });
91
+
92
+ await fs.writeFile(path.join(testDir, 'bar.txt'), 'Initial Bar', 'utf8');
93
+
94
+ await executeAddCmd({
95
+ paths: ['bar.txt'],
96
+ targetDir: testDir,
97
+ vcsFolderName,
98
+ quiet: true,
99
+ });
100
+
101
+ await fs.writeFile(path.join(testDir, 'bar.txt'), 'Edited Bar', 'utf8');
102
+
103
+ const restoreRes = await executeRestoreCmd({
104
+ paths: ['bar.txt'],
105
+ targetDir: testDir,
106
+ vcsFolderName,
107
+ staged: true,
108
+ quiet: true,
109
+ });
110
+
111
+ iReckon(lc, restoreRes.unstagedPaths).includes('bar.txt');
112
+
113
+ const statusRes = await executeStatusCmd({
114
+ targetDir: testDir,
115
+ vcsFolderName,
116
+ quiet: true,
117
+ });
118
+
119
+ iReckon(lc, statusRes.staged.map(x => x.path)).not.includes('bar.txt');
120
+
121
+ const diskContent = await fs.readFile(path.join(testDir, 'bar.txt'), 'utf8');
122
+ iReckon(lc, diskContent).willEqual('Edited Bar');
123
+ } finally {
124
+ await fs.rm(testDir, { recursive: true, force: true });
125
+ }
126
+ });
127
+
128
+ await ifWe(lc, `vcs restore <file> reverts modified disk file back to committed snapshot content`, async () => {
129
+ const testDir = path.join(process.cwd(), '.test_restore_worktree');
130
+ const vcsFolderName = '.vcsgib_test_restore_worktree';
131
+ try {
132
+ await executeInitCmd({
133
+ targetDir: testDir,
134
+ vcsFolderName,
135
+ quiet: true,
136
+ });
137
+
138
+ await fs.writeFile(path.join(testDir, 'committed.txt'), 'Original Committed Content', 'utf8');
139
+
140
+ await executeAddCmd({
141
+ paths: ['committed.txt'],
142
+ targetDir: testDir,
143
+ vcsFolderName,
144
+ quiet: true,
145
+ });
146
+
147
+ await executeCommitCmd({
148
+ message: 'Initial commit',
149
+ targetDir: testDir,
150
+ vcsFolderName,
151
+ quiet: true,
152
+ });
153
+
154
+ // Modify file on disk
155
+ await fs.writeFile(path.join(testDir, 'committed.txt'), 'Modified Bad Content', 'utf8');
156
+
157
+ // Restore worktree file
158
+ const restoreRes = await executeRestoreCmd({
159
+ paths: ['committed.txt'],
160
+ targetDir: testDir,
161
+ vcsFolderName,
162
+ quiet: true,
163
+ });
164
+
165
+ iReckon(lc, restoreRes.restoredPaths).includes('committed.txt');
166
+
167
+ // Verify disk content is reverted back to committed snapshot content
168
+ const diskContent = await fs.readFile(path.join(testDir, 'committed.txt'), 'utf8');
169
+ iReckon(lc, diskContent).willEqual('Original Committed Content');
170
+ } finally {
171
+ await fs.rm(testDir, { recursive: true, force: true });
172
+ }
173
+ });
174
+
175
+ await ifWe(lc, `vcs reset --all unstages all files from index`, async () => {
176
+ const testDir = path.join(process.cwd(), '.test_reset_all');
177
+ const vcsFolderName = '.vcsgib_test_reset_all';
178
+ try {
179
+ await executeInitCmd({
180
+ targetDir: testDir,
181
+ vcsFolderName,
182
+ quiet: true,
183
+ });
184
+
185
+ await fs.writeFile(path.join(testDir, 'f1.txt'), 'F1', 'utf8');
186
+ await fs.writeFile(path.join(testDir, 'f2.txt'), 'F2', 'utf8');
187
+
188
+ await executeAddCmd({
189
+ all: true,
190
+ targetDir: testDir,
191
+ vcsFolderName,
192
+ quiet: true,
193
+ });
194
+
195
+ let statusRes = await executeStatusCmd({
196
+ targetDir: testDir,
197
+ vcsFolderName,
198
+ quiet: true,
199
+ });
200
+ iReckon(lc, statusRes.staged.length).willEqual(2);
201
+
202
+ const resetRes = await executeResetCmd({
203
+ all: true,
204
+ targetDir: testDir,
205
+ vcsFolderName,
206
+ quiet: true,
207
+ });
208
+
209
+ iReckon(lc, resetRes.unstagedPaths.length).willEqual(2);
210
+
211
+ statusRes = await executeStatusCmd({
212
+ targetDir: testDir,
213
+ vcsFolderName,
214
+ quiet: true,
215
+ });
216
+ iReckon(lc, statusRes.staged.length).willEqual(0);
217
+ } finally {
218
+ await fs.rm(testDir, { recursive: true, force: true });
219
+ }
220
+ });
221
+
222
+ });
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @module restore-cmd
3
+ *
4
+ * Command handler for `vcs restore [path...]`.
5
+ * Restores working tree files from committed branch snapshot, or unstages files if `--staged` is set.
6
+ */
7
+
8
+ import path from 'node:path';
9
+ import fs from 'node:fs/promises';
10
+
11
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
12
+ import { promptForConfirm } from '@ibgib/helper-gib/dist/helpers/node-helper.mjs';
13
+ import { putInSpace } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
14
+
15
+ import { bootstrapVcsMetaspace } from '../../bootstrap/node-bootstrap.mjs';
16
+ import { getOrCreateBranchSpace } from '../../engine/branch/branch-space-helper.mjs';
17
+ import { getB2tFSIndexIbGib, unstagePathsFromIndex, restoreWorktreePathsFromSnapshot } from '../../engine/index/index-helper.mjs';
18
+ import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
19
+
20
+ const lcFile = `[restore-cmd]`;
21
+ const logalot = GLOBAL_LOG_A_LOT;
22
+
23
+ export interface RestoreCmdOpts {
24
+ paths?: string[];
25
+ targetDir?: string;
26
+ vcsFolderName?: string;
27
+ staged?: boolean;
28
+ worktree?: boolean;
29
+ yes?: boolean;
30
+ force?: boolean;
31
+ quiet?: boolean;
32
+ }
33
+
34
+ export interface RestoreCmdResult {
35
+ unstagedPaths?: string[];
36
+ restoredPaths?: string[];
37
+ }
38
+
39
+ export async function executeRestoreCmd({
40
+ paths = [],
41
+ targetDir = process.cwd(),
42
+ vcsFolderName = '.vcsgib',
43
+ staged = false,
44
+ worktree = false,
45
+ yes = false,
46
+ force = false,
47
+ quiet = false,
48
+ }: RestoreCmdOpts = {}): Promise<RestoreCmdResult> {
49
+ const lc = `${lcFile}[${executeRestoreCmd.name}]`;
50
+ try {
51
+ if (logalot) {
52
+ console.log(`${lc} starting... (I: 6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1e)`);
53
+ }
54
+
55
+ const absTargetDir = path.resolve(targetDir);
56
+
57
+ const { metaspace, localSpace, vcsPath, repoRoot } = await bootstrapVcsMetaspace({
58
+ repoPath: absTargetDir,
59
+ vcsFolderName,
60
+ });
61
+
62
+ // Verify repo exists
63
+ try {
64
+ await fs.access(vcsPath);
65
+ } catch {
66
+ throw new Error(`Not an ibgib repository (directory ${vcsPath} does not exist) (E: 7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2e)`);
67
+ }
68
+
69
+ // Retrieve authoritative B2tFSIndexIbGib_V1 from space
70
+ const indexIbGib = await getB2tFSIndexIbGib({ space: localSpace, vcsPath });
71
+ if (!indexIbGib) {
72
+ throw new Error(`Repository not initialized. Run 'vcs init' first. (E: 8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3e)`);
73
+ }
74
+
75
+ const activeBranch = indexIbGib.data?.activeBranch || 'main';
76
+ const activeWorktreeDir = activeBranch === 'main' ? repoRoot : path.join(repoRoot, 'b', activeBranch);
77
+
78
+ const { space: activeSpace } = await getOrCreateBranchSpace({
79
+ metaspace,
80
+ vcsPath,
81
+ branchName: activeBranch,
82
+ });
83
+
84
+ const skipPrompt = yes || force || quiet || !process.stdin.isTTY;
85
+ if (!skipPrompt) {
86
+ const msg = staged
87
+ ? 'Unstage specified files from index?'
88
+ : 'Revert working tree files to committed snapshot?';
89
+ const confirmed = await promptForConfirm({ msg });
90
+ if (!confirmed) {
91
+ if (!quiet) {
92
+ console.log('Operation cancelled.');
93
+ }
94
+ return { unstagedPaths: [], restoredPaths: [] };
95
+ }
96
+ }
97
+
98
+ let unstagedPaths: string[] | undefined;
99
+ let restoredPaths: string[] | undefined;
100
+
101
+ if (staged) {
102
+ const unstageRes = await unstagePathsFromIndex({
103
+ indexIbGib,
104
+ paths,
105
+ targetDir,
106
+ activeWorktreeDir,
107
+ vcsPath,
108
+ space: activeSpace,
109
+ metaspace,
110
+ });
111
+
112
+ if (localSpace !== activeSpace) {
113
+ await putInSpace({ space: localSpace, ibGib: unstageRes.updatedIndex });
114
+ }
115
+
116
+ unstagedPaths = unstageRes.unstagedPaths;
117
+ if (!quiet) {
118
+ for (const p of unstagedPaths) {
119
+ console.log(`unstaged: ${p}`);
120
+ }
121
+ }
122
+ }
123
+
124
+ if (!staged || worktree) {
125
+ const restoreRes = await restoreWorktreePathsFromSnapshot({
126
+ paths,
127
+ targetDir,
128
+ activeWorktreeDir,
129
+ activeBranchSpace: activeSpace,
130
+ metaspace,
131
+ indexIbGib,
132
+ vcsPath,
133
+ });
134
+
135
+ restoredPaths = restoreRes.restoredPaths;
136
+ if (!quiet) {
137
+ for (const p of restoredPaths) {
138
+ console.log(`restored: ${p}`);
139
+ }
140
+ }
141
+ }
142
+
143
+ return {
144
+ unstagedPaths,
145
+ restoredPaths,
146
+ };
147
+ } catch (error) {
148
+ console.error(`${lc} ${extractErrorMsg(error)} (E: 9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4e)`);
149
+ throw error;
150
+ } finally {
151
+ if (logalot) {
152
+ console.log(`${lc} complete. (I: 0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5e)`);
153
+ }
154
+ }
155
+ }
@@ -243,4 +243,31 @@ await respecfully(lc, `vcs status and vcs add Command Handlers`, async () => {
243
243
  await fs.rm(testDir, { recursive: true, force: true });
244
244
  }
245
245
  });
246
+
247
+ await ifWe(lc, `stages relative file paths correctly when targetDir is a subdirectory`, async () => {
248
+ const testDir = path.join(process.cwd(), '.test_status_add_subdir');
249
+ const vcsFolderName = '.vcsgib_test_subdir';
250
+ try {
251
+ await executeInitCmd({
252
+ targetDir: testDir,
253
+ vcsFolderName,
254
+ quiet: true,
255
+ });
256
+
257
+ const subDir = path.join(testDir, 'src', 'utils');
258
+ await fs.mkdir(subDir, { recursive: true });
259
+ await fs.writeFile(path.join(subDir, 'math.js'), 'export const add = (a, b) => a + b;', 'utf8');
260
+
261
+ const addRes = await executeAddCmd({
262
+ paths: ['math.js'],
263
+ targetDir: subDir,
264
+ vcsFolderName,
265
+ quiet: true,
266
+ });
267
+
268
+ iReckon(lc, addRes.stagedPaths).includes('src/utils/math.js');
269
+ } finally {
270
+ await fs.rm(testDir, { recursive: true, force: true });
271
+ }
272
+ });
246
273
  });
@@ -17,6 +17,8 @@ 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 { executeResetCmd } from './commands/reset-cmd.mjs';
21
+ import { executeRestoreCmd } from './commands/restore-cmd.mjs';
20
22
  import { AUTO_GENERATED_VERSION } from '../AUTO-GENERATED-version.mjs';
21
23
  import { GLOBAL_LOG_A_LOT } from '../vcs-gib-constants.mjs';
22
24
 
@@ -42,13 +44,18 @@ Commands:
42
44
  log Show commit logs
43
45
  branch [name] List or create branches
44
46
  checkout <branch> Switch to a specified branch and project worktree
47
+ reset [path...] Unstage specified files from index (-a, --all for all)
48
+ restore [path...] Restore working tree files or unstage (--staged)
45
49
 
46
50
  Flags:
47
51
  -h, --help Show help information
48
52
  -v, --version Show version information
49
53
  -m <message> Commit message
50
54
  -b <branch> Target branch name
51
- -a, --all Stage all tracked/untracked files (for add)
55
+ -a, --all Stage all tracked/untracked files (for add/reset)
56
+ -s, --staged Unstage specified files from index (for restore)
57
+ -w, --worktree Revert physical working tree files (for restore)
58
+ -y, --yes Automatically confirm interactive prompts
52
59
  -f, --force Force operation execution
53
60
  `;
54
61
  console.log(helpText.trim());
@@ -64,7 +71,7 @@ export async function main({
64
71
  const lc = `${lcFile}[${main.name}]`;
65
72
  try {
66
73
  if (logalot) {
67
- console.log(`${lc} starting... (I: 4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d)`);
74
+ console.log(`${lc} starting... (I: 4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e)`);
68
75
  }
69
76
 
70
77
  const parsed = parseVcsArgs(argv);
@@ -113,6 +120,25 @@ export async function main({
113
120
  await executeCheckoutCmd({ branchName });
114
121
  break;
115
122
  }
123
+ case VCS_SUBCOMMANDS.RESET: {
124
+ await executeResetCmd({
125
+ paths: parsed.positionals,
126
+ all: parsed.flags.all,
127
+ yes: parsed.flags.yes,
128
+ force: parsed.flags.force,
129
+ });
130
+ break;
131
+ }
132
+ case VCS_SUBCOMMANDS.RESTORE: {
133
+ await executeRestoreCmd({
134
+ paths: parsed.positionals,
135
+ staged: parsed.flags.staged,
136
+ worktree: parsed.flags.worktree,
137
+ yes: parsed.flags.yes,
138
+ force: parsed.flags.force,
139
+ });
140
+ break;
141
+ }
116
142
  case VCS_SUBCOMMANDS.VERSION: {
117
143
  showVersion();
118
144
  break;
@@ -126,7 +152,7 @@ export async function main({
126
152
 
127
153
  return 0;
128
154
  } catch (error) {
129
- console.error(`Error: ${extractErrorMsg(error)} (E: 8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c)`);
155
+ console.error(`Error: ${extractErrorMsg(error)} (E: 8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d)`);
130
156
  return 1;
131
157
  } finally {
132
158
  if (logalot) {
@@ -1,17 +1,20 @@
1
1
  /**
2
2
  * @module branch-graph-helper
3
3
  *
4
- * Helper for extracting dependency graphs and populating branch spaces.
4
+ * Helper for populating branch spaces via SyncSagaCoordinator.
5
5
  */
6
6
 
7
- import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
7
+ import { clone, extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
8
8
  import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
9
- import { getDependencyGraph } from '@ibgib/core-gib/dist/common/other/graph-helper.mjs';
10
9
  import { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';
11
- import { putInSpace } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
12
10
  import { MetaspaceService } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs';
11
+ import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
12
+ import { SyncPeerInnerspace_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs';
13
+ import { SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs';
13
14
 
14
15
  import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
16
+ import { B2tFSBranchIbGib_V1 } from './branch-types.mjs';
17
+ import { createB2tFSBranchIbGib } from './branch-helper.mjs';
15
18
 
16
19
  const lcFile = `[branch-graph-helper]`;
17
20
  const logalot = GLOBAL_LOG_A_LOT;
@@ -20,44 +23,88 @@ export interface PopulateBranchSpaceFromGraphOpts {
20
23
  sourceSpace: IbGibSpaceAny;
21
24
  targetBranchSpace: IbGibSpaceAny;
22
25
  rootItemIbGib: IbGib_V1;
26
+ branchName?: string;
23
27
  metaspace?: MetaspaceService;
24
28
  }
25
29
 
30
+ export interface PopulateBranchSpaceFromGraphResult {
31
+ syncedCount: number;
32
+ branchIbGib?: B2tFSBranchIbGib_V1;
33
+ }
34
+
26
35
  /**
27
- * Extracts the live dependency graph of rootItemIbGib from sourceSpace and persists all ibgibs into targetBranchSpace.
36
+ * Executes SSM (Space - Sync - Metadata) for branch space initialization:
37
+ * 1. Space: Target branch space targetBranchSpace (b2s_<branchName>).
38
+ * 2. Sync: Syncs rootItemIbGib from sourceSpace -> targetBranchSpace using SyncSagaCoordinator.
39
+ * 3. Metadata: Creates B2tFSBranchIbGib_V1 metadata node in targetBranchSpace pointing to rootItem.
28
40
  */
29
41
  export async function populateBranchSpaceFromGraph({
30
42
  sourceSpace,
31
43
  targetBranchSpace,
32
44
  rootItemIbGib,
45
+ branchName,
33
46
  metaspace,
34
- }: PopulateBranchSpaceFromGraphOpts): Promise<void> {
47
+ }: PopulateBranchSpaceFromGraphOpts): Promise<PopulateBranchSpaceFromGraphResult> {
35
48
  const lc = `${lcFile}[${populateBranchSpaceFromGraph.name}]`;
36
49
  try {
37
50
  if (logalot) {
38
51
  console.log(`${lc} starting... (I: 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d)`);
39
52
  }
40
53
 
41
- if (!sourceSpace || !targetBranchSpace || !rootItemIbGib) {
42
- throw new Error(`sourceSpace, targetBranchSpace, and rootItemIbGib are required (E: 2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e)`);
54
+ if (!sourceSpace || !targetBranchSpace || !rootItemIbGib || !metaspace) {
55
+ throw new Error(`sourceSpace, targetBranchSpace, rootItemIbGib, and metaspace are required (E: 2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e)`);
43
56
  }
44
57
 
45
- const graph = await getDependencyGraph({
46
- ibGib: rootItemIbGib,
47
- space: sourceSpace,
48
- live: true,
58
+ // 1. Space: targetBranchSpace provided/instantiated
59
+
60
+ // 2. Sync: Execute SyncSagaCoordinator space-to-space sync (sourceSpace -> targetBranchSpace)
61
+ const senderCoordinator = new SyncSagaCoordinator();
62
+ const receiverCoordinator = new SyncSagaCoordinator();
63
+
64
+ const peer = new SyncPeerInnerspace_V1(clone(SYNC_PEER_INNERSPACE_DEFAULT_DATA_V1));
65
+ await peer.initialized;
66
+ await peer.initializeOpts({
67
+ localMetaspace: metaspace,
68
+ localSpace: sourceSpace,
69
+ receiverSpace: targetBranchSpace,
70
+ receiverCoordinator,
71
+ receiverMetaspace: metaspace,
49
72
  });
50
73
 
51
- for (const [addr, ibGib] of Object.entries(graph)) {
52
- await putInSpace({ space: targetBranchSpace, ibGib });
53
- if (metaspace) {
54
- await metaspace.registerNewIbGib({ ibGib, space: targetBranchSpace });
55
- }
74
+ const resSync = await senderCoordinator.sync({
75
+ peer,
76
+ localSpace: sourceSpace,
77
+ metaspace,
78
+ domainIbGibs: [rootItemIbGib],
79
+ });
80
+
81
+ await resSync.done;
82
+
83
+ if (logalot) {
84
+ console.log(`${lc} SyncSagaCoordinator sync initiated for ${rootItemIbGib.ib} (I: 3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f)`);
85
+ }
86
+
87
+ const syncedCount = 1;
88
+
89
+ // 3. Metadata: Create B2tFSBranchIbGib_V1 metadata node in targetBranchSpace pointing to rootItem
90
+ let branchIbGib: B2tFSBranchIbGib_V1 | undefined;
91
+ if (branchName && metaspace) {
92
+ branchIbGib = await createB2tFSBranchIbGib({
93
+ branchName,
94
+ rootItem: rootItemIbGib as any,
95
+ space: targetBranchSpace,
96
+ metaspace,
97
+ });
56
98
  }
57
99
 
58
100
  if (logalot) {
59
- console.log(`${lc} Populated target branch space with ${Object.keys(graph).length} ibgibs (I: 3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f)`);
101
+ console.log(`${lc} Populated target branch space via SyncSagaCoordinator (I: 4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f)`);
60
102
  }
103
+
104
+ return {
105
+ syncedCount,
106
+ branchIbGib,
107
+ };
61
108
  } catch (error) {
62
109
  console.error(`${lc} ${extractErrorMsg(error)} (E: 4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a)`);
63
110
  throw error;
@@ -67,3 +114,4 @@ export async function populateBranchSpaceFromGraph({
67
114
  }
68
115
  }
69
116
  }
117
+
@@ -14,6 +14,12 @@ import { putInSpace } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs'
14
14
  import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
15
15
  import { getB2tFSBranchSpaceName } from './branch-helper.mjs';
16
16
 
17
+ export {
18
+ populateBranchSpaceFromGraph,
19
+ PopulateBranchSpaceFromGraphOpts,
20
+ PopulateBranchSpaceFromGraphResult,
21
+ } from './branch-graph-helper.mjs';
22
+
17
23
  const lcFile = `[branch-space-helper]`;
18
24
  const logalot = GLOBAL_LOG_A_LOT;
19
25
 
@@ -136,20 +136,26 @@ await respecfully(lc, `Branch Space & Graph Helper Respecs`, async () => {
136
136
  branchName: 'main',
137
137
  });
138
138
 
139
- // Populate target branch space from source localSpace graph
140
- await populateBranchSpaceFromGraph({
139
+ // Populate target branch space from source localSpace graph and create branch metadata node (SSM)
140
+ const popResult = await populateBranchSpaceFromGraph({
141
141
  sourceSpace: localSpace,
142
142
  targetBranchSpace,
143
143
  rootItemIbGib: rootItem,
144
+ branchName: 'main',
144
145
  metaspace,
145
146
  });
146
147
 
148
+ iReckon(lc, popResult.syncedCount > 0).isGonnaBeTrue();
149
+ iReckon(lc, popResult.branchIbGib).isGonnaBeTruthy();
150
+ iReckon(lc, popResult.branchIbGib?.data?.name).willEqual('main');
151
+ iReckon(lc, popResult.branchIbGib?.rel8ns?.b2tfs_item).includes(rootAddr);
152
+
147
153
  // Verify items exist in targetBranchSpace
148
- const rootGet = await getFromSpace({ space: targetBranchSpace, addr: rootAddr });
149
- iReckon(lc, rootGet).isGonnaBeTruthy();
154
+ const rootGet = await getFromSpace({ space: targetBranchSpace, addrs: [rootAddr] });
155
+ iReckon(lc, rootGet?.ibGibs?.length === 1).isGonnaBeTrue();
150
156
 
151
- const childGet = await getFromSpace({ space: targetBranchSpace, addr: childAddr });
152
- iReckon(lc, childGet).isGonnaBeTruthy();
157
+ const childGet = await getFromSpace({ space: targetBranchSpace, addrs: [childAddr] });
158
+ iReckon(lc, childGet?.ibGibs?.length === 1).isGonnaBeTrue();
153
159
  } finally {
154
160
  await fs.rm(testDir, { recursive: true, force: true });
155
161
  }