@ibgib/vcs-gib 0.0.6 → 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/README.md +24 -2
- package/VCS_CLI_USER_GUIDE.md +2 -2
- package/dist/AUTO-GENERATED-version.d.mts +1 -1
- package/dist/AUTO-GENERATED-version.d.mts.map +1 -1
- package/dist/AUTO-GENERATED-version.mjs +1 -1
- package/dist/AUTO-GENERATED-version.mjs.map +1 -1
- package/dist/bootstrap/node-bootstrap.d.mts.map +1 -1
- package/dist/bootstrap/node-bootstrap.mjs +9 -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.d.mts +3 -0
- package/dist/cli/cli-arg-parser.d.mts.map +1 -1
- package/dist/cli/cli-arg-parser.mjs +13 -1
- package/dist/cli/cli-arg-parser.mjs.map +1 -1
- 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 +6 -0
- package/dist/cli/cli-constants.d.mts.map +1 -1
- package/dist/cli/cli-constants.mjs +24 -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} +2 -2
- 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 +35 -30
- 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} +172 -8
- package/dist/cli/commands/branch-checkout-cmd.respec.mjs.map +1 -0
- package/dist/cli/commands/branch-cmd.d.mts +2 -1
- package/dist/cli/commands/branch-cmd.d.mts.map +1 -1
- package/dist/cli/commands/branch-cmd.mjs +59 -8
- 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 +38 -18
- 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 +26 -23
- 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-cmd.d.mts +21 -0
- package/dist/cli/commands/reset-cmd.d.mts.map +1 -0
- package/dist/cli/commands/reset-cmd.mjs +93 -0
- package/dist/cli/commands/reset-cmd.mjs.map +1 -0
- package/dist/cli/commands/reset-restore-cmd.respec.d.mts +7 -0
- package/dist/cli/commands/reset-restore-cmd.respec.d.mts.map +1 -0
- package/dist/cli/commands/reset-restore-cmd.respec.mjs +185 -0
- package/dist/cli/commands/reset-restore-cmd.respec.mjs.map +1 -0
- package/dist/cli/commands/restore-cmd.d.mts +22 -0
- package/dist/cli/commands/restore-cmd.d.mts.map +1 -0
- package/dist/cli/commands/restore-cmd.mjs +115 -0
- package/dist/cli/commands/restore-cmd.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} +25 -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 +36 -3
- package/dist/cli/vcs-cli-main.mjs.map +1 -1
- package/dist/engine/branch/branch-graph-helper.d.mts +12 -3
- package/dist/engine/branch/branch-graph-helper.d.mts.map +1 -1
- package/dist/engine/branch/branch-graph-helper.mjs +50 -18
- package/dist/engine/branch/branch-graph-helper.mjs.map +1 -1
- package/dist/engine/branch/branch-space-helper.d.mts +1 -0
- package/dist/engine/branch/branch-space-helper.d.mts.map +1 -1
- package/dist/engine/branch/branch-space-helper.mjs +1 -0
- package/dist/engine/branch/branch-space-helper.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} +12 -7
- 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/index/index-helper.d.mts +35 -0
- package/dist/engine/index/index-helper.d.mts.map +1 -1
- package/dist/engine/index/index-helper.mjs +241 -0
- package/dist/engine/index/index-helper.mjs.map +1 -1
- package/dist/engine/item/item-helper.d.mts +29 -3
- package/dist/engine/item/item-helper.d.mts.map +1 -1
- package/dist/engine/item/item-helper.mjs +234 -56
- package/dist/engine/item/item-helper.mjs.map +1 -1
- package/dist/engine/item/item.respec.d.mts +7 -0
- package/dist/engine/item/item.respec.d.mts.map +1 -0
- package/dist/engine/item/item.respec.mjs +75 -0
- 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 +6 -0
- package/src/cli/cli-arg-parser.mts +15 -0
- package/src/cli/cli-constants.mts +27 -0
- package/src/cli/{cli-e2e.respec.node.mts → cli-e2e.respec.mts} +2 -2
- package/src/cli/commands/add-cmd.mts +41 -29
- package/src/cli/commands/{branch-checkout-cmd.respec.node.mts → branch-checkout-cmd.respec.mts} +190 -8
- package/src/cli/commands/branch-cmd.mts +78 -8
- package/src/cli/commands/checkout-cmd.mts +48 -23
- package/src/cli/commands/commit-cmd.mts +35 -26
- package/src/cli/commands/merge-cmd.mts +289 -0
- package/src/cli/commands/reset-cmd.mts +128 -0
- package/src/cli/commands/reset-restore-cmd.respec.mts +222 -0
- package/src/cli/commands/restore-cmd.mts +155 -0
- package/src/cli/commands/{status-add-cmd.respec.node.mts → status-add-cmd.respec.mts} +27 -0
- package/src/cli/vcs-cli-main.mts +36 -3
- package/src/engine/branch/branch-graph-helper.mts +66 -18
- package/src/engine/branch/branch-space-helper.mts +6 -0
- package/src/engine/branch/{branch-space.respec.node.mts → branch-space.respec.mts} +12 -6
- package/src/engine/index/index-helper.mts +324 -0
- package/src/engine/item/item-helper.mts +284 -58
- package/src/engine/item/item.respec.mts +92 -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/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/vcs-gib.respec.node.d.mts.map +0 -1
- package/dist/vcs-gib.respec.node.mjs.map +0 -1
- package/test_runs/001-hello-node/20260728_090100_0001-flow-core-main.md +0 -39
- package/test_runs/001-hello-node/20260728_090200_0003-flow-branching-worktree.md +0 -54
- package/test_runs/001-hello-node/20260728_090300_0002-flow-selective-add.md +0 -45
- package/test_runs/001-hello-node/20260728_142100_0007-flow-edge-cases.md +0 -44
- package/test_runs/001-hello-node/20260728_142400_0005-flow-hardcoded-ignores.md +0 -36
- package/tools/pack-for-test.mjs +0 -73
- /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/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/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/{vcs-gib.respec.node.mts → vcs-gib.respec.mts} +0 -0
|
@@ -22,11 +22,13 @@ import { bootstrapVcsMetaspace } from '../../bootstrap/node-bootstrap.mjs';
|
|
|
22
22
|
import { getOrCreateBranchSpace } from '../../engine/branch/branch-space-helper.mjs';
|
|
23
23
|
import { getB2tFSItemIb } from '../../engine/item/item-atom-helper.mjs';
|
|
24
24
|
import { B2tFSItemIbGib_V1, B2TFS_CHILD_ITEM_REL8N_NAME } from '../../engine/item/item-types.mjs';
|
|
25
|
-
import { getIbGibWithMetaspaceFallback } from '../../engine/item/item-helper.mjs';
|
|
25
|
+
import { getIbGibWithMetaspaceFallback, createB2tFSItemIbGib, evolveB2tFSItemIbGib } from '../../engine/item/item-helper.mjs';
|
|
26
26
|
import { B2tFSBranchIbGib_V1 } from '../../engine/branch/branch-types.mjs';
|
|
27
27
|
import { isPathFiltered, parseFilterFileContent, globToRegExp } from '../../engine/filter/glob-helper.mjs';
|
|
28
28
|
import { getB2tFSIndexIbGib, updateB2tFSIndexIbGib } from '../../engine/index/index-helper.mjs';
|
|
29
29
|
import { B2tFSStagedItemRecord } from '../../engine/index/index-types.mjs';
|
|
30
|
+
import { TransformResult } from '@ibgib/ts-gib/dist/types.mjs';
|
|
31
|
+
import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
30
32
|
import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
|
|
31
33
|
|
|
32
34
|
const lcFile = `[add-cmd]`;
|
|
@@ -97,7 +99,7 @@ export async function executeAddCmd({
|
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
// Walk active branch graph items to find committed files in snapshot
|
|
100
|
-
const committedBranchItemsMap = new Map<string, { relPath: string; fileHash?: string; fsType: 'file' | 'folder' }>();
|
|
102
|
+
const committedBranchItemsMap = new Map<string, { relPath: string; fileHash?: string; fsType: 'file' | 'folder'; item?: B2tFSItemIbGib_V1 }>();
|
|
101
103
|
const branchAddrs = [
|
|
102
104
|
...(indexIbGib?.rel8ns?.branch || []),
|
|
103
105
|
...(indexIbGib?.rel8ns?.branch_tjp || []),
|
|
@@ -116,11 +118,13 @@ export async function executeAddCmd({
|
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
const activeBranchIbGib = branchIbGibs.
|
|
121
|
+
const activeBranchIbGib = branchIbGibs.findLast(
|
|
120
122
|
(b) => (b as B2tFSBranchIbGib_V1)?.data?.name === activeBranch,
|
|
121
|
-
) as B2tFSBranchIbGib_V1 || (branchIbGibs.at(
|
|
123
|
+
) as B2tFSBranchIbGib_V1 || (branchIbGibs.at(-1) as B2tFSBranchIbGib_V1);
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
const rootItemAddr = activeBranchIbGib?.rel8ns?.b2tfs_item?.at(-1);
|
|
122
127
|
|
|
123
|
-
const rootItemAddr = activeBranchIbGib?.rel8ns?.b2tfs_item?.at(0);
|
|
124
128
|
if (rootItemAddr) {
|
|
125
129
|
const rootItem = await getIbGibWithMetaspaceFallback({
|
|
126
130
|
addr: rootItemAddr,
|
|
@@ -182,7 +186,7 @@ export async function executeAddCmd({
|
|
|
182
186
|
throw new Error(`No files matched glob pattern: ${relOrAbs} (E: e23d4c5f6a7b8c9d0e1f2a3b4c5d6e7f)`);
|
|
183
187
|
}
|
|
184
188
|
} else {
|
|
185
|
-
const fullPath = path.resolve(
|
|
189
|
+
const fullPath = path.resolve(targetDir, relOrAbs);
|
|
186
190
|
let stat;
|
|
187
191
|
try {
|
|
188
192
|
stat = await fs.stat(fullPath);
|
|
@@ -191,6 +195,9 @@ export async function executeAddCmd({
|
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
const relPath = path.relative(activeWorktreeDir, fullPath).replace(/\\/g, '/');
|
|
198
|
+
if (relPath.startsWith('..') || path.isAbsolute(relPath)) {
|
|
199
|
+
throw new Error(`Path '${relOrAbs}' is outside of active worktree repository (E: 7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f)`);
|
|
200
|
+
}
|
|
194
201
|
|
|
195
202
|
if (isPathFiltered({ relativePath: relPath, isDirectory: stat.isDirectory(), filterPatterns })) {
|
|
196
203
|
continue;
|
|
@@ -243,31 +250,36 @@ export async function executeAddCmd({
|
|
|
243
250
|
await putInSpace({ ibGib: binIbGib, space: activeSpace });
|
|
244
251
|
await metaspace.registerNewIbGib({ ibGib: binIbGib, space: activeSpace });
|
|
245
252
|
|
|
246
|
-
// 2. Create B2tFSItemIbGib_V1 candidate graph node
|
|
253
|
+
// 2. Create or Evolve B2tFSItemIbGib_V1 candidate graph node
|
|
247
254
|
const fileName = path.basename(absFilePath);
|
|
248
|
-
const fileNameSansExt = path.parse(fileName).name;
|
|
249
|
-
const fileExt = path.parse(fileName).ext.replace(/^\./, '');
|
|
250
255
|
const nameHash = crypto.createHash('sha256').update(fileName).digest('hex');
|
|
251
256
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
257
|
+
let itemRes: TransformResult<IbGib_V1>;
|
|
258
|
+
if (committedItem && committedItem.item) {
|
|
259
|
+
itemRes = await evolveB2tFSItemIbGib({
|
|
260
|
+
existingItem: committedItem.item,
|
|
261
|
+
dataToUpdate: {
|
|
262
|
+
fileHash,
|
|
263
|
+
},
|
|
264
|
+
rel8nsToUpdate: {
|
|
265
|
+
bin: [binAddr],
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
} else {
|
|
269
|
+
itemRes = await createB2tFSItemIbGib({
|
|
258
270
|
fsType: 'file',
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
+
name: fileName,
|
|
272
|
+
data: {
|
|
273
|
+
nameHash,
|
|
274
|
+
fileHash,
|
|
275
|
+
fileEncoding: 'utf8',
|
|
276
|
+
},
|
|
277
|
+
rel8ns: {
|
|
278
|
+
bin: [binAddr],
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
271
283
|
const itemIbGib = itemRes.newIbGib as B2tFSItemIbGib_V1;
|
|
272
284
|
const itemAddr = getIbGibAddr({ ibGib: itemIbGib });
|
|
273
285
|
await persistTransformResult({ resTransform: itemRes, space: activeSpace });
|
|
@@ -332,13 +344,13 @@ async function addCmd_walkBranchGraph({
|
|
|
332
344
|
space: any;
|
|
333
345
|
metaspace?: any;
|
|
334
346
|
currentRelPath: string;
|
|
335
|
-
outMap: Map<string, { relPath: string; fileHash?: string; fsType: 'file' | 'folder' }>;
|
|
347
|
+
outMap: Map<string, { relPath: string; fileHash?: string; fsType: 'file' | 'folder'; item?: B2tFSItemIbGib_V1 }>;
|
|
336
348
|
}): Promise<void> {
|
|
337
349
|
if (!item || !item.data) { return; }
|
|
338
350
|
|
|
339
351
|
const { fsType, fileHash } = item.data;
|
|
340
352
|
if (currentRelPath) {
|
|
341
|
-
outMap.set(currentRelPath, { relPath: currentRelPath, fileHash, fsType });
|
|
353
|
+
outMap.set(currentRelPath, { relPath: currentRelPath, fileHash, fsType, item });
|
|
342
354
|
}
|
|
343
355
|
|
|
344
356
|
if (fsType === 'folder') {
|
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 {
|
|
@@ -319,4 +321,184 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
319
321
|
await fs.rm(testDir, { recursive: true, force: true });
|
|
320
322
|
}
|
|
321
323
|
});
|
|
324
|
+
|
|
325
|
+
await ifWeMight(lc, `branches single file-root item and projects into file-branch worktree on checkout`, async () => {
|
|
326
|
+
const testDir = path.join(process.cwd(), '.test_branch_checkout_file_root');
|
|
327
|
+
const vcsFolderName = '.vcsgib_test_bc_file';
|
|
328
|
+
try {
|
|
329
|
+
await executeInitCmd({
|
|
330
|
+
targetDir: testDir,
|
|
331
|
+
vcsFolderName,
|
|
332
|
+
quiet: true,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Create nested file structure src/utils/math.js and commit on main
|
|
336
|
+
const mathRelPath = 'src/utils/math.js';
|
|
337
|
+
await fs.mkdir(path.join(testDir, 'src', 'utils'), { recursive: true });
|
|
338
|
+
await fs.writeFile(path.join(testDir, mathRelPath), 'export function add(a, b) { return a + b; }', 'utf8');
|
|
339
|
+
|
|
340
|
+
await executeAddCmd({
|
|
341
|
+
paths: [mathRelPath],
|
|
342
|
+
targetDir: testDir,
|
|
343
|
+
vcsFolderName,
|
|
344
|
+
quiet: true,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
await executeCommitCmd({
|
|
348
|
+
message: 'Add math.js',
|
|
349
|
+
targetDir: testDir,
|
|
350
|
+
vcsFolderName,
|
|
351
|
+
quiet: true,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Execute branch command for single file math-opt targeting src/utils/math.js
|
|
355
|
+
const branchRes = await executeBranchCmd({
|
|
356
|
+
branchName: 'math-opt',
|
|
357
|
+
itemPath: mathRelPath,
|
|
358
|
+
targetDir: testDir,
|
|
359
|
+
vcsFolderName,
|
|
360
|
+
quiet: true,
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
iReckon(lc, branchRes.createdBranchName).willEqual('math-opt');
|
|
364
|
+
|
|
365
|
+
// Attempt branching uncommitted/non-existent item
|
|
366
|
+
let uncommittedErr = false;
|
|
367
|
+
try {
|
|
368
|
+
await executeBranchCmd({
|
|
369
|
+
branchName: 'invalid-file-branch',
|
|
370
|
+
itemPath: 'src/utils/non-existent.js',
|
|
371
|
+
targetDir: testDir,
|
|
372
|
+
vcsFolderName,
|
|
373
|
+
quiet: true,
|
|
374
|
+
});
|
|
375
|
+
} catch (err: any) {
|
|
376
|
+
uncommittedErr = true;
|
|
377
|
+
iReckon(lc, err.message).includes("not found in active branch snapshot");
|
|
378
|
+
}
|
|
379
|
+
iReckon(lc, uncommittedErr).isGonnaBeTrue();
|
|
380
|
+
|
|
381
|
+
// Execute checkout command for math-opt
|
|
382
|
+
const checkoutRes = await executeCheckoutCmd({
|
|
383
|
+
branchName: 'math-opt',
|
|
384
|
+
targetDir: testDir,
|
|
385
|
+
vcsFolderName,
|
|
386
|
+
quiet: true,
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
const expectedWorktree = path.join(testDir, 'b', 'math-opt');
|
|
390
|
+
iReckon(lc, checkoutRes.worktreePath).willEqual(expectedWorktree);
|
|
391
|
+
|
|
392
|
+
// Verify single file projected at expectedWorktree/math.js (my-repo/b/math-opt/math.js)
|
|
393
|
+
const projectedFilePath = path.join(expectedWorktree, 'math.js');
|
|
394
|
+
const fileExists = await fs.stat(projectedFilePath).then(s => s.isFile()).catch(() => false);
|
|
395
|
+
iReckon(lc, fileExists).isGonnaBeTrue();
|
|
396
|
+
|
|
397
|
+
const fileContent = await fs.readFile(projectedFilePath, 'utf8');
|
|
398
|
+
iReckon(lc, fileContent).willEqual('export function add(a, b) { return a + b; }');
|
|
399
|
+
} finally {
|
|
400
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
401
|
+
}
|
|
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
|
+
});
|
|
322
503
|
});
|
|
504
|
+
|
|
@@ -18,7 +18,7 @@ import { B2tFSBranchIbGib_V1 } from '../../engine/branch/branch-types.mjs';
|
|
|
18
18
|
import { createB2tFSBranchIbGib } from '../../engine/branch/branch-helper.mjs';
|
|
19
19
|
import { getOrCreateBranchSpace } from '../../engine/branch/branch-space-helper.mjs';
|
|
20
20
|
import { populateBranchSpaceFromGraph } from '../../engine/branch/branch-graph-helper.mjs';
|
|
21
|
-
import { B2tFSItemIbGib_V1 } from '../../engine/item/item-types.mjs';
|
|
21
|
+
import { B2tFSItemIbGib_V1, B2TFS_CHILD_ITEM_REL8N_NAME } from '../../engine/item/item-types.mjs';
|
|
22
22
|
import { getIbGibWithMetaspaceFallback } from '../../engine/item/item-helper.mjs';
|
|
23
23
|
import { getB2tFSIndexIbGib, updateB2tFSIndexIbGib, getSpaceQualifiedIbGibAddr } from '../../engine/index/index-helper.mjs';
|
|
24
24
|
import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
|
|
@@ -28,6 +28,7 @@ const logalot = GLOBAL_LOG_A_LOT;
|
|
|
28
28
|
|
|
29
29
|
export interface BranchCmdOpts {
|
|
30
30
|
branchName?: string;
|
|
31
|
+
itemPath?: string;
|
|
31
32
|
targetDir?: string;
|
|
32
33
|
vcsFolderName?: string;
|
|
33
34
|
quiet?: boolean;
|
|
@@ -48,6 +49,7 @@ export interface BranchCmdResult {
|
|
|
48
49
|
|
|
49
50
|
export async function executeBranchCmd({
|
|
50
51
|
branchName,
|
|
52
|
+
itemPath,
|
|
51
53
|
targetDir = process.cwd(),
|
|
52
54
|
vcsFolderName = '.vcsgib',
|
|
53
55
|
quiet = false,
|
|
@@ -122,7 +124,7 @@ export async function executeBranchCmd({
|
|
|
122
124
|
const branches: BranchInfo[] = [];
|
|
123
125
|
for (const [name, bNode] of branchMap.entries()) {
|
|
124
126
|
const addr = getIbGibAddr({ ibGib: bNode });
|
|
125
|
-
const rootItemAddr = bNode.rel8ns?.b2tfs_item?.at(
|
|
127
|
+
const rootItemAddr = bNode.rel8ns?.b2tfs_item?.at(-1);
|
|
126
128
|
const isActive = name === activeBranchName;
|
|
127
129
|
branches.push({
|
|
128
130
|
name,
|
|
@@ -140,6 +142,7 @@ export async function executeBranchCmd({
|
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
return { branches };
|
|
145
|
+
|
|
143
146
|
}
|
|
144
147
|
|
|
145
148
|
// CREATE BRANCH
|
|
@@ -149,10 +152,10 @@ export async function executeBranchCmd({
|
|
|
149
152
|
|
|
150
153
|
// Find active branch root item to fork from
|
|
151
154
|
const activeBranchIbGib = branchMap.get(activeBranchName) || branchIbGibs.at(0);
|
|
152
|
-
const rootItemAddr = activeBranchIbGib?.rel8ns?.b2tfs_item?.at(
|
|
155
|
+
const rootItemAddr = activeBranchIbGib?.rel8ns?.b2tfs_item?.at(-1);
|
|
153
156
|
|
|
154
157
|
if (!rootItemAddr) {
|
|
155
|
-
throw new Error(`Cannot find active branch root item to fork branch from (E:
|
|
158
|
+
throw new Error(`Cannot find active branch root item to fork branch from (E: 8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c)`);
|
|
156
159
|
}
|
|
157
160
|
|
|
158
161
|
const rootItem = await getIbGibWithMetaspaceFallback({
|
|
@@ -165,6 +168,25 @@ export async function executeBranchCmd({
|
|
|
165
168
|
throw new Error(`Root item node for address '${rootItemAddr}' not found in localSpace (E: 9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e)`);
|
|
166
169
|
}
|
|
167
170
|
|
|
171
|
+
let targetRootItem: B2tFSItemIbGib_V1 = rootItem;
|
|
172
|
+
if (itemPath && itemPath.trim().length > 0) {
|
|
173
|
+
const normalizedItemPath = itemPath.trim().replace(/\\/g, '/').replace(/^\.\//, '');
|
|
174
|
+
const committedBranchItemsMap = new Map<string, B2tFSItemIbGib_V1>();
|
|
175
|
+
await executeBranchCmd_walkBranchGraphForItems({
|
|
176
|
+
item: rootItem,
|
|
177
|
+
space: activeBranchSpace,
|
|
178
|
+
metaspace,
|
|
179
|
+
currentRelPath: '',
|
|
180
|
+
outMap: committedBranchItemsMap,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const targetItemNode = committedBranchItemsMap.get(normalizedItemPath);
|
|
184
|
+
if (!targetItemNode) {
|
|
185
|
+
throw new Error(`Item '${itemPath}' not found in active branch snapshot (E: 8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c)`);
|
|
186
|
+
}
|
|
187
|
+
targetRootItem = targetItemNode;
|
|
188
|
+
}
|
|
189
|
+
|
|
168
190
|
// Instantiate new branch space b2s_<newBranch>
|
|
169
191
|
const { space: newBranchSpace, spaceId: newBranchSpaceId } = await getOrCreateBranchSpace({
|
|
170
192
|
metaspace,
|
|
@@ -172,18 +194,18 @@ export async function executeBranchCmd({
|
|
|
172
194
|
branchName: trimmedBranchName,
|
|
173
195
|
});
|
|
174
196
|
|
|
175
|
-
// Populate new branch space from live dependency graph of
|
|
197
|
+
// Populate new branch space from live dependency graph of targetRootItem
|
|
176
198
|
await populateBranchSpaceFromGraph({
|
|
177
199
|
sourceSpace: activeBranchSpace,
|
|
178
200
|
targetBranchSpace: newBranchSpace,
|
|
179
|
-
rootItemIbGib:
|
|
201
|
+
rootItemIbGib: targetRootItem,
|
|
180
202
|
metaspace,
|
|
181
203
|
});
|
|
182
204
|
|
|
183
205
|
// Create new B2tFSBranchIbGib_V1 branch node inside newBranchSpace
|
|
184
206
|
const newBranchIbGib = await createB2tFSBranchIbGib({
|
|
185
207
|
branchName: trimmedBranchName,
|
|
186
|
-
rootItem,
|
|
208
|
+
rootItem: targetRootItem,
|
|
187
209
|
space: newBranchSpace,
|
|
188
210
|
metaspace,
|
|
189
211
|
});
|
|
@@ -210,7 +232,7 @@ export async function executeBranchCmd({
|
|
|
210
232
|
});
|
|
211
233
|
|
|
212
234
|
if (!quiet) {
|
|
213
|
-
console.log(`Created branch '${trimmedBranchName}' (I:
|
|
235
|
+
console.log(`Created branch '${trimmedBranchName}' (I: 0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5e)`);
|
|
214
236
|
}
|
|
215
237
|
|
|
216
238
|
// Return updated branch list
|
|
@@ -241,3 +263,51 @@ export async function executeBranchCmd({
|
|
|
241
263
|
}
|
|
242
264
|
}
|
|
243
265
|
}
|
|
266
|
+
|
|
267
|
+
// #region executeBranchCmd_walkBranchGraphForItems
|
|
268
|
+
async function executeBranchCmd_walkBranchGraphForItems({
|
|
269
|
+
item,
|
|
270
|
+
space,
|
|
271
|
+
metaspace,
|
|
272
|
+
currentRelPath,
|
|
273
|
+
outMap,
|
|
274
|
+
}: {
|
|
275
|
+
item: B2tFSItemIbGib_V1;
|
|
276
|
+
space: any;
|
|
277
|
+
metaspace?: any;
|
|
278
|
+
currentRelPath: string;
|
|
279
|
+
outMap: Map<string, B2tFSItemIbGib_V1>;
|
|
280
|
+
}): Promise<void> {
|
|
281
|
+
if (!item || !item.data) { return; }
|
|
282
|
+
|
|
283
|
+
const { fsType } = item.data;
|
|
284
|
+
|
|
285
|
+
if (currentRelPath) {
|
|
286
|
+
outMap.set(currentRelPath, item);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (fsType === 'folder') {
|
|
290
|
+
const childAddrs = item.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
291
|
+
for (const childAddr of childAddrs) {
|
|
292
|
+
const childItem = await getIbGibWithMetaspaceFallback({
|
|
293
|
+
addr: childAddr,
|
|
294
|
+
space,
|
|
295
|
+
metaspace,
|
|
296
|
+
}) as B2tFSItemIbGib_V1;
|
|
297
|
+
|
|
298
|
+
if (childItem && childItem.data) {
|
|
299
|
+
const childRelPath = currentRelPath
|
|
300
|
+
? `${currentRelPath}/${childItem.data.name}`
|
|
301
|
+
: childItem.data.name;
|
|
302
|
+
await executeBranchCmd_walkBranchGraphForItems({
|
|
303
|
+
item: childItem,
|
|
304
|
+
space,
|
|
305
|
+
metaspace,
|
|
306
|
+
currentRelPath: childRelPath,
|
|
307
|
+
outMap,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// #endregion executeBranchCmd_walkBranchGraphForItems
|
|
@@ -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';
|
|
@@ -49,7 +50,7 @@ export async function executeCheckoutCmd({
|
|
|
49
50
|
const lc = `${lcFile}[${executeCheckoutCmd.name}]`;
|
|
50
51
|
try {
|
|
51
52
|
if (logalot) {
|
|
52
|
-
console.log(`${lc} starting... (I:
|
|
53
|
+
console.log(`${lc} starting... (I: 3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8e)`);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
const trimmedBranchName = branchName?.trim();
|
|
@@ -68,7 +69,7 @@ export async function executeCheckoutCmd({
|
|
|
68
69
|
try {
|
|
69
70
|
await fs.access(vcsPath);
|
|
70
71
|
} catch {
|
|
71
|
-
throw new Error(`Not an ibgib repository (directory ${vcsPath} does not exist) (E:
|
|
72
|
+
throw new Error(`Not an ibgib repository (directory ${vcsPath} does not exist) (E: 5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0e)`);
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
// 1. Fetch authoritative repository index from localSpace
|
|
@@ -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
|
|
@@ -152,7 +166,9 @@ export async function executeCheckoutCmd({
|
|
|
152
166
|
|
|
153
167
|
await fs.mkdir(worktreePath, { recursive: true });
|
|
154
168
|
|
|
155
|
-
// Retrieve root item and project
|
|
169
|
+
// Retrieve root item and project branch snapshot onto worktree subfolder:
|
|
170
|
+
// If rootItem is a single file, write it directly to worktreePath (my-repo/b/<branchName>/<fileName>).
|
|
171
|
+
// If rootItem is a folder, write child items into worktreePath.
|
|
156
172
|
const rootItem = await getIbGibWithMetaspaceFallback({
|
|
157
173
|
addr: rootItemAddr,
|
|
158
174
|
space: targetBranchSpace,
|
|
@@ -160,21 +176,30 @@ export async function executeCheckoutCmd({
|
|
|
160
176
|
}) as B2tFSItemIbGib_V1;
|
|
161
177
|
|
|
162
178
|
if (rootItem) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
179
|
+
if (rootItem.data?.fsType === 'file') {
|
|
180
|
+
await writeB2tFSItemToFS({
|
|
181
|
+
item: rootItem,
|
|
182
|
+
destPath: worktreePath,
|
|
167
183
|
space: targetBranchSpace,
|
|
168
184
|
metaspace,
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
185
|
+
});
|
|
186
|
+
} else {
|
|
187
|
+
const childAddrs = rootItem.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
188
|
+
for (const childAddr of childAddrs) {
|
|
189
|
+
const childItem = await getIbGibWithMetaspaceFallback({
|
|
190
|
+
addr: childAddr,
|
|
175
191
|
space: targetBranchSpace,
|
|
176
192
|
metaspace,
|
|
177
|
-
});
|
|
193
|
+
}) as B2tFSItemIbGib_V1;
|
|
194
|
+
|
|
195
|
+
if (childItem) {
|
|
196
|
+
await writeB2tFSItemToFS({
|
|
197
|
+
item: childItem,
|
|
198
|
+
destPath: worktreePath,
|
|
199
|
+
space: targetBranchSpace,
|
|
200
|
+
metaspace,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
178
203
|
}
|
|
179
204
|
}
|
|
180
205
|
}
|