@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.
- 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 +6 -0
- package/dist/bootstrap/node-bootstrap.mjs.map +1 -1
- 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-constants.d.mts +5 -0
- package/dist/cli/cli-constants.d.mts.map +1 -1
- package/dist/cli/cli-constants.mjs +23 -0
- package/dist/cli/cli-constants.mjs.map +1 -1
- package/dist/cli/cli-e2e.respec.node.mjs +1 -1
- package/dist/cli/cli-e2e.respec.node.mjs.map +1 -1
- package/dist/cli/commands/add-cmd.d.mts.map +1 -1
- package/dist/cli/commands/add-cmd.mjs +33 -28
- package/dist/cli/commands/add-cmd.mjs.map +1 -1
- package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs +70 -0
- package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs.map +1 -1
- 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 +57 -6
- 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 +23 -11
- 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 +24 -21
- package/dist/cli/commands/commit-cmd.mjs.map +1 -1
- 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.node.d.mts +7 -0
- package/dist/cli/commands/reset-restore-cmd.respec.node.d.mts.map +1 -0
- package/dist/cli/commands/reset-restore-cmd.respec.node.mjs +185 -0
- package/dist/cli/commands/reset-restore-cmd.respec.node.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.mjs +24 -0
- package/dist/cli/commands/status-add-cmd.respec.node.mjs.map +1 -1
- package/dist/cli/vcs-cli-main.d.mts.map +1 -1
- package/dist/cli/vcs-cli-main.mjs +29 -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.mjs +11 -6
- package/dist/engine/branch/branch-space.respec.node.mjs.map +1 -1
- 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.node.d.mts +7 -0
- package/dist/engine/item/item.respec.node.d.mts.map +1 -0
- package/dist/engine/item/item.respec.node.mjs +75 -0
- package/dist/engine/item/item.respec.node.mjs.map +1 -0
- package/package.json +3 -3
- package/src/AUTO-GENERATED-version.mts +1 -1
- package/src/bootstrap/node-bootstrap.mts +2 -0
- package/src/cli/cli-arg-parser.mts +15 -0
- package/src/cli/cli-constants.mts +26 -0
- package/src/cli/cli-e2e.respec.node.mts +2 -2
- package/src/cli/commands/add-cmd.mts +36 -26
- package/src/cli/commands/branch-checkout-cmd.respec.node.mts +79 -0
- package/src/cli/commands/branch-cmd.mts +75 -6
- package/src/cli/commands/checkout-cmd.mts +25 -14
- package/src/cli/commands/commit-cmd.mts +30 -23
- package/src/cli/commands/reset-cmd.mts +128 -0
- package/src/cli/commands/reset-restore-cmd.respec.node.mts +222 -0
- package/src/cli/commands/restore-cmd.mts +155 -0
- package/src/cli/commands/status-add-cmd.respec.node.mts +27 -0
- package/src/cli/vcs-cli-main.mts +29 -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 +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.node.mts +92 -0
- package/tsconfig.tsbuildinfo +1 -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
|
@@ -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 || []),
|
|
@@ -182,7 +184,7 @@ export async function executeAddCmd({
|
|
|
182
184
|
throw new Error(`No files matched glob pattern: ${relOrAbs} (E: e23d4c5f6a7b8c9d0e1f2a3b4c5d6e7f)`);
|
|
183
185
|
}
|
|
184
186
|
} else {
|
|
185
|
-
const fullPath = path.resolve(
|
|
187
|
+
const fullPath = path.resolve(targetDir, relOrAbs);
|
|
186
188
|
let stat;
|
|
187
189
|
try {
|
|
188
190
|
stat = await fs.stat(fullPath);
|
|
@@ -191,6 +193,9 @@ export async function executeAddCmd({
|
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
const relPath = path.relative(activeWorktreeDir, fullPath).replace(/\\/g, '/');
|
|
196
|
+
if (relPath.startsWith('..') || path.isAbsolute(relPath)) {
|
|
197
|
+
throw new Error(`Path '${relOrAbs}' is outside of active worktree repository (E: 7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f)`);
|
|
198
|
+
}
|
|
194
199
|
|
|
195
200
|
if (isPathFiltered({ relativePath: relPath, isDirectory: stat.isDirectory(), filterPatterns })) {
|
|
196
201
|
continue;
|
|
@@ -243,31 +248,36 @@ export async function executeAddCmd({
|
|
|
243
248
|
await putInSpace({ ibGib: binIbGib, space: activeSpace });
|
|
244
249
|
await metaspace.registerNewIbGib({ ibGib: binIbGib, space: activeSpace });
|
|
245
250
|
|
|
246
|
-
// 2. Create B2tFSItemIbGib_V1 candidate graph node
|
|
251
|
+
// 2. Create or Evolve B2tFSItemIbGib_V1 candidate graph node
|
|
247
252
|
const fileName = path.basename(absFilePath);
|
|
248
|
-
const fileNameSansExt = path.parse(fileName).name;
|
|
249
|
-
const fileExt = path.parse(fileName).ext.replace(/^\./, '');
|
|
250
253
|
const nameHash = crypto.createHash('sha256').update(fileName).digest('hex');
|
|
251
254
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
255
|
+
let itemRes: TransformResult<IbGib_V1>;
|
|
256
|
+
if (committedItem && committedItem.item) {
|
|
257
|
+
itemRes = await evolveB2tFSItemIbGib({
|
|
258
|
+
existingItem: committedItem.item,
|
|
259
|
+
dataToUpdate: {
|
|
260
|
+
fileHash,
|
|
261
|
+
},
|
|
262
|
+
rel8nsToUpdate: {
|
|
263
|
+
bin: [binAddr],
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
} else {
|
|
267
|
+
itemRes = await createB2tFSItemIbGib({
|
|
258
268
|
fsType: 'file',
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
name: fileName,
|
|
270
|
+
data: {
|
|
271
|
+
nameHash,
|
|
272
|
+
fileHash,
|
|
273
|
+
fileEncoding: 'utf8',
|
|
274
|
+
},
|
|
275
|
+
rel8ns: {
|
|
276
|
+
bin: [binAddr],
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
271
281
|
const itemIbGib = itemRes.newIbGib as B2tFSItemIbGib_V1;
|
|
272
282
|
const itemAddr = getIbGibAddr({ ibGib: itemIbGib });
|
|
273
283
|
await persistTransformResult({ resTransform: itemRes, space: activeSpace });
|
|
@@ -332,13 +342,13 @@ async function addCmd_walkBranchGraph({
|
|
|
332
342
|
space: any;
|
|
333
343
|
metaspace?: any;
|
|
334
344
|
currentRelPath: string;
|
|
335
|
-
outMap: Map<string, { relPath: string; fileHash?: string; fsType: 'file' | 'folder' }>;
|
|
345
|
+
outMap: Map<string, { relPath: string; fileHash?: string; fsType: 'file' | 'folder'; item?: B2tFSItemIbGib_V1 }>;
|
|
336
346
|
}): Promise<void> {
|
|
337
347
|
if (!item || !item.data) { return; }
|
|
338
348
|
|
|
339
349
|
const { fsType, fileHash } = item.data;
|
|
340
350
|
if (currentRelPath) {
|
|
341
|
-
outMap.set(currentRelPath, { relPath: currentRelPath, fileHash, fsType });
|
|
351
|
+
outMap.set(currentRelPath, { relPath: currentRelPath, fileHash, fsType, item });
|
|
342
352
|
}
|
|
343
353
|
|
|
344
354
|
if (fsType === 'folder') {
|
|
@@ -319,4 +319,83 @@ await respecfully(lc, `vcs branch and vcs checkout Command Handlers`, async () =
|
|
|
319
319
|
await fs.rm(testDir, { recursive: true, force: true });
|
|
320
320
|
}
|
|
321
321
|
});
|
|
322
|
+
|
|
323
|
+
await ifWe(lc, `branches single file-root item and projects into file-branch worktree on checkout`, async () => {
|
|
324
|
+
const testDir = path.join(process.cwd(), '.test_branch_checkout_file_root');
|
|
325
|
+
const vcsFolderName = '.vcsgib_test_bc_file';
|
|
326
|
+
try {
|
|
327
|
+
await executeInitCmd({
|
|
328
|
+
targetDir: testDir,
|
|
329
|
+
vcsFolderName,
|
|
330
|
+
quiet: true,
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// Create nested file structure src/utils/math.js and commit on main
|
|
334
|
+
const mathRelPath = 'src/utils/math.js';
|
|
335
|
+
await fs.mkdir(path.join(testDir, 'src', 'utils'), { recursive: true });
|
|
336
|
+
await fs.writeFile(path.join(testDir, mathRelPath), 'export function add(a, b) { return a + b; }', 'utf8');
|
|
337
|
+
|
|
338
|
+
await executeAddCmd({
|
|
339
|
+
paths: [mathRelPath],
|
|
340
|
+
targetDir: testDir,
|
|
341
|
+
vcsFolderName,
|
|
342
|
+
quiet: true,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
await executeCommitCmd({
|
|
346
|
+
message: 'Add math.js',
|
|
347
|
+
targetDir: testDir,
|
|
348
|
+
vcsFolderName,
|
|
349
|
+
quiet: true,
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// Execute branch command for single file math-opt targeting src/utils/math.js
|
|
353
|
+
const branchRes = await executeBranchCmd({
|
|
354
|
+
branchName: 'math-opt',
|
|
355
|
+
itemPath: mathRelPath,
|
|
356
|
+
targetDir: testDir,
|
|
357
|
+
vcsFolderName,
|
|
358
|
+
quiet: true,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
iReckon(lc, branchRes.createdBranchName).willEqual('math-opt');
|
|
362
|
+
|
|
363
|
+
// Attempt branching uncommitted/non-existent item
|
|
364
|
+
let uncommittedErr = false;
|
|
365
|
+
try {
|
|
366
|
+
await executeBranchCmd({
|
|
367
|
+
branchName: 'invalid-file-branch',
|
|
368
|
+
itemPath: 'src/utils/non-existent.js',
|
|
369
|
+
targetDir: testDir,
|
|
370
|
+
vcsFolderName,
|
|
371
|
+
quiet: true,
|
|
372
|
+
});
|
|
373
|
+
} catch (err: any) {
|
|
374
|
+
uncommittedErr = true;
|
|
375
|
+
iReckon(lc, err.message).includes("not found in active branch snapshot");
|
|
376
|
+
}
|
|
377
|
+
iReckon(lc, uncommittedErr).isGonnaBeTrue();
|
|
378
|
+
|
|
379
|
+
// Execute checkout command for math-opt
|
|
380
|
+
const checkoutRes = await executeCheckoutCmd({
|
|
381
|
+
branchName: 'math-opt',
|
|
382
|
+
targetDir: testDir,
|
|
383
|
+
vcsFolderName,
|
|
384
|
+
quiet: true,
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
const expectedWorktree = path.join(testDir, 'b', 'math-opt');
|
|
388
|
+
iReckon(lc, checkoutRes.worktreePath).willEqual(expectedWorktree);
|
|
389
|
+
|
|
390
|
+
// Verify single file projected at expectedWorktree/math.js (my-repo/b/math-opt/math.js)
|
|
391
|
+
const projectedFilePath = path.join(expectedWorktree, 'math.js');
|
|
392
|
+
const fileExists = await fs.stat(projectedFilePath).then(s => s.isFile()).catch(() => false);
|
|
393
|
+
iReckon(lc, fileExists).isGonnaBeTrue();
|
|
394
|
+
|
|
395
|
+
const fileContent = await fs.readFile(projectedFilePath, 'utf8');
|
|
396
|
+
iReckon(lc, fileContent).willEqual('export function add(a, b) { return a + b; }');
|
|
397
|
+
} finally {
|
|
398
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
399
|
+
}
|
|
400
|
+
});
|
|
322
401
|
});
|
|
@@ -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,
|
|
@@ -152,7 +154,7 @@ export async function executeBranchCmd({
|
|
|
152
154
|
const rootItemAddr = activeBranchIbGib?.rel8ns?.b2tfs_item?.at(0);
|
|
153
155
|
|
|
154
156
|
if (!rootItemAddr) {
|
|
155
|
-
throw new Error(`Cannot find active branch root item to fork branch from (E:
|
|
157
|
+
throw new Error(`Cannot find active branch root item to fork branch from (E: 8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c)`);
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
const rootItem = await getIbGibWithMetaspaceFallback({
|
|
@@ -165,6 +167,25 @@ export async function executeBranchCmd({
|
|
|
165
167
|
throw new Error(`Root item node for address '${rootItemAddr}' not found in localSpace (E: 9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e)`);
|
|
166
168
|
}
|
|
167
169
|
|
|
170
|
+
let targetRootItem: B2tFSItemIbGib_V1 = rootItem;
|
|
171
|
+
if (itemPath && itemPath.trim().length > 0) {
|
|
172
|
+
const normalizedItemPath = itemPath.trim().replace(/\\/g, '/').replace(/^\.\//, '');
|
|
173
|
+
const committedBranchItemsMap = new Map<string, B2tFSItemIbGib_V1>();
|
|
174
|
+
await executeBranchCmd_walkBranchGraphForItems({
|
|
175
|
+
item: rootItem,
|
|
176
|
+
space: activeBranchSpace,
|
|
177
|
+
metaspace,
|
|
178
|
+
currentRelPath: '',
|
|
179
|
+
outMap: committedBranchItemsMap,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const targetItemNode = committedBranchItemsMap.get(normalizedItemPath);
|
|
183
|
+
if (!targetItemNode) {
|
|
184
|
+
throw new Error(`Item '${itemPath}' not found in active branch snapshot (E: 8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c)`);
|
|
185
|
+
}
|
|
186
|
+
targetRootItem = targetItemNode;
|
|
187
|
+
}
|
|
188
|
+
|
|
168
189
|
// Instantiate new branch space b2s_<newBranch>
|
|
169
190
|
const { space: newBranchSpace, spaceId: newBranchSpaceId } = await getOrCreateBranchSpace({
|
|
170
191
|
metaspace,
|
|
@@ -172,18 +193,18 @@ export async function executeBranchCmd({
|
|
|
172
193
|
branchName: trimmedBranchName,
|
|
173
194
|
});
|
|
174
195
|
|
|
175
|
-
// Populate new branch space from live dependency graph of
|
|
196
|
+
// Populate new branch space from live dependency graph of targetRootItem
|
|
176
197
|
await populateBranchSpaceFromGraph({
|
|
177
198
|
sourceSpace: activeBranchSpace,
|
|
178
199
|
targetBranchSpace: newBranchSpace,
|
|
179
|
-
rootItemIbGib:
|
|
200
|
+
rootItemIbGib: targetRootItem,
|
|
180
201
|
metaspace,
|
|
181
202
|
});
|
|
182
203
|
|
|
183
204
|
// Create new B2tFSBranchIbGib_V1 branch node inside newBranchSpace
|
|
184
205
|
const newBranchIbGib = await createB2tFSBranchIbGib({
|
|
185
206
|
branchName: trimmedBranchName,
|
|
186
|
-
rootItem,
|
|
207
|
+
rootItem: targetRootItem,
|
|
187
208
|
space: newBranchSpace,
|
|
188
209
|
metaspace,
|
|
189
210
|
});
|
|
@@ -210,7 +231,7 @@ export async function executeBranchCmd({
|
|
|
210
231
|
});
|
|
211
232
|
|
|
212
233
|
if (!quiet) {
|
|
213
|
-
console.log(`Created branch '${trimmedBranchName}' (I:
|
|
234
|
+
console.log(`Created branch '${trimmedBranchName}' (I: 0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5e)`);
|
|
214
235
|
}
|
|
215
236
|
|
|
216
237
|
// Return updated branch list
|
|
@@ -241,3 +262,51 @@ export async function executeBranchCmd({
|
|
|
241
262
|
}
|
|
242
263
|
}
|
|
243
264
|
}
|
|
265
|
+
|
|
266
|
+
// #region executeBranchCmd_walkBranchGraphForItems
|
|
267
|
+
async function executeBranchCmd_walkBranchGraphForItems({
|
|
268
|
+
item,
|
|
269
|
+
space,
|
|
270
|
+
metaspace,
|
|
271
|
+
currentRelPath,
|
|
272
|
+
outMap,
|
|
273
|
+
}: {
|
|
274
|
+
item: B2tFSItemIbGib_V1;
|
|
275
|
+
space: any;
|
|
276
|
+
metaspace?: any;
|
|
277
|
+
currentRelPath: string;
|
|
278
|
+
outMap: Map<string, B2tFSItemIbGib_V1>;
|
|
279
|
+
}): Promise<void> {
|
|
280
|
+
if (!item || !item.data) { return; }
|
|
281
|
+
|
|
282
|
+
const { fsType } = item.data;
|
|
283
|
+
|
|
284
|
+
if (currentRelPath) {
|
|
285
|
+
outMap.set(currentRelPath, item);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (fsType === 'folder') {
|
|
289
|
+
const childAddrs = item.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
290
|
+
for (const childAddr of childAddrs) {
|
|
291
|
+
const childItem = await getIbGibWithMetaspaceFallback({
|
|
292
|
+
addr: childAddr,
|
|
293
|
+
space,
|
|
294
|
+
metaspace,
|
|
295
|
+
}) as B2tFSItemIbGib_V1;
|
|
296
|
+
|
|
297
|
+
if (childItem && childItem.data) {
|
|
298
|
+
const childRelPath = currentRelPath
|
|
299
|
+
? `${currentRelPath}/${childItem.data.name}`
|
|
300
|
+
: childItem.data.name;
|
|
301
|
+
await executeBranchCmd_walkBranchGraphForItems({
|
|
302
|
+
item: childItem,
|
|
303
|
+
space,
|
|
304
|
+
metaspace,
|
|
305
|
+
currentRelPath: childRelPath,
|
|
306
|
+
outMap,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// #endregion executeBranchCmd_walkBranchGraphForItems
|
|
@@ -49,7 +49,7 @@ export async function executeCheckoutCmd({
|
|
|
49
49
|
const lc = `${lcFile}[${executeCheckoutCmd.name}]`;
|
|
50
50
|
try {
|
|
51
51
|
if (logalot) {
|
|
52
|
-
console.log(`${lc} starting... (I:
|
|
52
|
+
console.log(`${lc} starting... (I: 3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8e)`);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const trimmedBranchName = branchName?.trim();
|
|
@@ -68,7 +68,7 @@ export async function executeCheckoutCmd({
|
|
|
68
68
|
try {
|
|
69
69
|
await fs.access(vcsPath);
|
|
70
70
|
} catch {
|
|
71
|
-
throw new Error(`Not an ibgib repository (directory ${vcsPath} does not exist) (E:
|
|
71
|
+
throw new Error(`Not an ibgib repository (directory ${vcsPath} does not exist) (E: 5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0e)`);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// 1. Fetch authoritative repository index from localSpace
|
|
@@ -152,7 +152,9 @@ export async function executeCheckoutCmd({
|
|
|
152
152
|
|
|
153
153
|
await fs.mkdir(worktreePath, { recursive: true });
|
|
154
154
|
|
|
155
|
-
// Retrieve root item and project
|
|
155
|
+
// Retrieve root item and project branch snapshot onto worktree subfolder:
|
|
156
|
+
// If rootItem is a single file, write it directly to worktreePath (my-repo/b/<branchName>/<fileName>).
|
|
157
|
+
// If rootItem is a folder, write child items into worktreePath.
|
|
156
158
|
const rootItem = await getIbGibWithMetaspaceFallback({
|
|
157
159
|
addr: rootItemAddr,
|
|
158
160
|
space: targetBranchSpace,
|
|
@@ -160,21 +162,30 @@ export async function executeCheckoutCmd({
|
|
|
160
162
|
}) as B2tFSItemIbGib_V1;
|
|
161
163
|
|
|
162
164
|
if (rootItem) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
if (rootItem.data?.fsType === 'file') {
|
|
166
|
+
await writeB2tFSItemToFS({
|
|
167
|
+
item: rootItem,
|
|
168
|
+
destPath: worktreePath,
|
|
167
169
|
space: targetBranchSpace,
|
|
168
170
|
metaspace,
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
});
|
|
172
|
+
} else {
|
|
173
|
+
const childAddrs = rootItem.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
174
|
+
for (const childAddr of childAddrs) {
|
|
175
|
+
const childItem = await getIbGibWithMetaspaceFallback({
|
|
176
|
+
addr: childAddr,
|
|
175
177
|
space: targetBranchSpace,
|
|
176
178
|
metaspace,
|
|
177
|
-
});
|
|
179
|
+
}) as B2tFSItemIbGib_V1;
|
|
180
|
+
|
|
181
|
+
if (childItem) {
|
|
182
|
+
await writeB2tFSItemToFS({
|
|
183
|
+
item: childItem,
|
|
184
|
+
destPath: worktreePath,
|
|
185
|
+
space: targetBranchSpace,
|
|
186
|
+
metaspace,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
178
189
|
}
|
|
179
190
|
}
|
|
180
191
|
}
|
|
@@ -24,11 +24,13 @@ import { bootstrapVcsMetaspace } from '../../bootstrap/node-bootstrap.mjs';
|
|
|
24
24
|
import { getOrCreateBranchSpace } from '../../engine/branch/branch-space-helper.mjs';
|
|
25
25
|
import { getB2tFSItemIb } from '../../engine/item/item-atom-helper.mjs';
|
|
26
26
|
import { B2tFSItemIbGib_V1, B2TFS_CHILD_ITEM_REL8N_NAME } from '../../engine/item/item-types.mjs';
|
|
27
|
-
import { getIbGibWithMetaspaceFallback } from '../../engine/item/item-helper.mjs';
|
|
27
|
+
import { getIbGibWithMetaspaceFallback, createB2tFSItemIbGib, evolveB2tFSItemIbGib } from '../../engine/item/item-helper.mjs';
|
|
28
28
|
import { getB2tFSBranchSpaceName } from '../../engine/branch/branch-helper.mjs';
|
|
29
29
|
import { B2tFSBranchIbGib_V1 } from '../../engine/branch/branch-types.mjs';
|
|
30
30
|
import { getB2tFSIndexIbGib, updateB2tFSIndexIbGib, getSpaceQualifiedIbGibAddr } from '../../engine/index/index-helper.mjs';
|
|
31
31
|
import { B2tFSStagedItemRecord } from '../../engine/index/index-types.mjs';
|
|
32
|
+
import { TransformResult } from '@ibgib/ts-gib/dist/types.mjs';
|
|
33
|
+
import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
32
34
|
import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
|
|
33
35
|
|
|
34
36
|
const lcFile = `[commit-cmd]`;
|
|
@@ -244,7 +246,7 @@ async function commitCmd_buildEvolvedRootItem({
|
|
|
244
246
|
metaspace: any;
|
|
245
247
|
repoName: string;
|
|
246
248
|
}): Promise<{ newRootItem: B2tFSItemIbGib_V1; newRootAddr: string }> {
|
|
247
|
-
const itemsByRelPath = new Map<string, { itemAddr: string; fsType: 'file' | 'folder' }>();
|
|
249
|
+
const itemsByRelPath = new Map<string, { itemAddr: string; fsType: 'file' | 'folder'; item?: B2tFSItemIbGib_V1 }>();
|
|
248
250
|
|
|
249
251
|
if (currentRootAddr) {
|
|
250
252
|
const currentRootItem = await getIbGibWithMetaspaceFallback({
|
|
@@ -328,27 +330,34 @@ async function commitCmd_buildEvolvedRootItem({
|
|
|
328
330
|
}
|
|
329
331
|
|
|
330
332
|
const folderName = folderRelPath ? path.basename(folderRelPath) : repoName;
|
|
331
|
-
const diffTxId = await getUUID();
|
|
332
333
|
const nameHash = crypto.createHash('sha256').update(folderName).digest('hex');
|
|
333
334
|
|
|
334
|
-
const
|
|
335
|
-
if (childAddrs.length > 0) {
|
|
336
|
-
rel8ns[B2TFS_CHILD_ITEM_REL8N_NAME] = childAddrs;
|
|
337
|
-
}
|
|
335
|
+
const existingFolderRec = itemsByRelPath.get(folderRelPath);
|
|
338
336
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
337
|
+
let folderRes: TransformResult<IbGib_V1>;
|
|
338
|
+
|
|
339
|
+
if (existingFolderRec && existingFolderRec.item) {
|
|
340
|
+
const oldChildAddrs = existingFolderRec.item.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
341
|
+
const toRemoveChildAddrs = oldChildAddrs.filter(a => !childAddrs.includes(a));
|
|
342
|
+
|
|
343
|
+
folderRes = await evolveB2tFSItemIbGib({
|
|
344
|
+
existingItem: existingFolderRec.item,
|
|
345
|
+
dataToUpdate: {
|
|
346
|
+
nameHash,
|
|
347
|
+
},
|
|
348
|
+
rel8nsToUpdate: childAddrs.length > 0 ? { [B2TFS_CHILD_ITEM_REL8N_NAME]: childAddrs } : undefined,
|
|
349
|
+
rel8nsToRemove: toRemoveChildAddrs.length > 0 ? { [B2TFS_CHILD_ITEM_REL8N_NAME]: toRemoveChildAddrs } : undefined,
|
|
350
|
+
});
|
|
351
|
+
} else {
|
|
352
|
+
folderRes = await createB2tFSItemIbGib({
|
|
345
353
|
fsType: 'folder',
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
354
|
+
name: folderName,
|
|
355
|
+
data: {
|
|
356
|
+
nameHash,
|
|
357
|
+
},
|
|
358
|
+
rel8ns: childAddrs.length > 0 ? { [B2TFS_CHILD_ITEM_REL8N_NAME]: childAddrs } : undefined,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
352
361
|
|
|
353
362
|
const folderItem = folderRes.newIbGib as B2tFSItemIbGib_V1;
|
|
354
363
|
const folderAddr = getIbGibAddr({ ibGib: folderItem });
|
|
@@ -383,16 +392,14 @@ async function commitCmd_walkBranchGraph({
|
|
|
383
392
|
space: any;
|
|
384
393
|
metaspace?: any;
|
|
385
394
|
currentRelPath: string;
|
|
386
|
-
outMap: Map<string, { itemAddr: string; fsType: 'file' | 'folder' }>;
|
|
395
|
+
outMap: Map<string, { itemAddr: string; fsType: 'file' | 'folder'; item?: B2tFSItemIbGib_V1 }>;
|
|
387
396
|
}): Promise<void> {
|
|
388
397
|
if (!item || !item.data) { return; }
|
|
389
398
|
|
|
390
399
|
const { fsType } = item.data;
|
|
391
400
|
const itemAddr = getIbGibAddr({ ibGib: item });
|
|
392
401
|
|
|
393
|
-
|
|
394
|
-
outMap.set(currentRelPath, { itemAddr, fsType });
|
|
395
|
-
}
|
|
402
|
+
outMap.set(currentRelPath, { itemAddr, fsType, item });
|
|
396
403
|
|
|
397
404
|
if (fsType === 'folder') {
|
|
398
405
|
const childAddrs = item.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module reset-cmd
|
|
3
|
+
*
|
|
4
|
+
* Command handler for `vcs reset [path...]`.
|
|
5
|
+
* Unstages specified files (or all files) from active branch index in localSpace.
|
|
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 } from '../../engine/index/index-helper.mjs';
|
|
18
|
+
import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
|
|
19
|
+
|
|
20
|
+
const lcFile = `[reset-cmd]`;
|
|
21
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
22
|
+
|
|
23
|
+
export interface ResetCmdOpts {
|
|
24
|
+
paths?: string[];
|
|
25
|
+
targetDir?: string;
|
|
26
|
+
vcsFolderName?: string;
|
|
27
|
+
all?: boolean;
|
|
28
|
+
yes?: boolean;
|
|
29
|
+
force?: boolean;
|
|
30
|
+
quiet?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ResetCmdResult {
|
|
34
|
+
unstagedPaths: string[];
|
|
35
|
+
stagedCount: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function executeResetCmd({
|
|
39
|
+
paths = [],
|
|
40
|
+
targetDir = process.cwd(),
|
|
41
|
+
vcsFolderName = '.vcsgib',
|
|
42
|
+
all = false,
|
|
43
|
+
yes = false,
|
|
44
|
+
force = false,
|
|
45
|
+
quiet = false,
|
|
46
|
+
}: ResetCmdOpts = {}): Promise<ResetCmdResult> {
|
|
47
|
+
const lc = `${lcFile}[${executeResetCmd.name}]`;
|
|
48
|
+
try {
|
|
49
|
+
if (logalot) {
|
|
50
|
+
console.log(`${lc} starting... (I: 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d)`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const absTargetDir = path.resolve(targetDir);
|
|
54
|
+
|
|
55
|
+
const { metaspace, localSpace, vcsPath, repoRoot } = await bootstrapVcsMetaspace({
|
|
56
|
+
repoPath: absTargetDir,
|
|
57
|
+
vcsFolderName,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Verify repo exists
|
|
61
|
+
try {
|
|
62
|
+
await fs.access(vcsPath);
|
|
63
|
+
} catch {
|
|
64
|
+
throw new Error(`Not an ibgib repository (directory ${vcsPath} does not exist) (E: 2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b)`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Retrieve authoritative B2tFSIndexIbGib_V1 from space
|
|
68
|
+
const indexIbGib = await getB2tFSIndexIbGib({ space: localSpace, vcsPath });
|
|
69
|
+
if (!indexIbGib) {
|
|
70
|
+
throw new Error(`Repository not initialized. Run 'vcs init' first. (E: 3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b)`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const activeBranch = indexIbGib.data?.activeBranch || 'main';
|
|
74
|
+
const activeWorktreeDir = activeBranch === 'main' ? repoRoot : path.join(repoRoot, 'b', activeBranch);
|
|
75
|
+
|
|
76
|
+
const { space: activeSpace } = await getOrCreateBranchSpace({
|
|
77
|
+
metaspace,
|
|
78
|
+
vcsPath,
|
|
79
|
+
branchName: activeBranch,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const skipPrompt = yes || force || quiet || !process.stdin.isTTY;
|
|
83
|
+
if (!skipPrompt) {
|
|
84
|
+
const confirmed = await promptForConfirm({ msg: 'Unstage specified files from index?' });
|
|
85
|
+
if (!confirmed) {
|
|
86
|
+
if (!quiet) {
|
|
87
|
+
console.log('Operation cancelled.');
|
|
88
|
+
}
|
|
89
|
+
const stagedCount = Object.keys(indexIbGib.data?.stagedPaths || {}).length;
|
|
90
|
+
return { unstagedPaths: [], stagedCount };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const unstageRes = await unstagePathsFromIndex({
|
|
95
|
+
indexIbGib,
|
|
96
|
+
paths,
|
|
97
|
+
targetDir,
|
|
98
|
+
activeWorktreeDir,
|
|
99
|
+
vcsPath,
|
|
100
|
+
space: activeSpace,
|
|
101
|
+
metaspace,
|
|
102
|
+
all,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (localSpace !== activeSpace) {
|
|
106
|
+
await putInSpace({ space: localSpace, ibGib: unstageRes.updatedIndex });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!quiet) {
|
|
110
|
+
for (const unstagedPath of unstageRes.unstagedPaths) {
|
|
111
|
+
console.log(`unstaged: ${unstagedPath}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const finalStagedCount = Object.keys(unstageRes.updatedIndex.data?.stagedPaths || {}).length;
|
|
116
|
+
return {
|
|
117
|
+
unstagedPaths: unstageRes.unstagedPaths,
|
|
118
|
+
stagedCount: finalStagedCount,
|
|
119
|
+
};
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error(`${lc} ${extractErrorMsg(error)} (E: 4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b)`);
|
|
122
|
+
throw error;
|
|
123
|
+
} finally {
|
|
124
|
+
if (logalot) {
|
|
125
|
+
console.log(`${lc} complete. (I: 5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c)`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|