@ibgib/vcs-gib 0.0.6
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 +94 -0
- package/VCS_CLI_USER_GUIDE.md +198 -0
- package/dist/AUTO-GENERATED-version.d.mts +6 -0
- package/dist/AUTO-GENERATED-version.d.mts.map +1 -0
- package/dist/AUTO-GENERATED-version.mjs +6 -0
- package/dist/AUTO-GENERATED-version.mjs.map +1 -0
- package/dist/assumptions.respec.d.mts +2 -0
- package/dist/assumptions.respec.d.mts.map +1 -0
- package/dist/assumptions.respec.mjs +41 -0
- package/dist/assumptions.respec.mjs.map +1 -0
- package/dist/bootstrap/node-bootstrap.d.mts +35 -0
- package/dist/bootstrap/node-bootstrap.d.mts.map +1 -0
- package/dist/bootstrap/node-bootstrap.mjs +165 -0
- package/dist/bootstrap/node-bootstrap.mjs.map +1 -0
- package/dist/bootstrap/node-bootstrap.respec.node.d.mts +7 -0
- package/dist/bootstrap/node-bootstrap.respec.node.d.mts.map +1 -0
- package/dist/bootstrap/node-bootstrap.respec.node.mjs +28 -0
- package/dist/bootstrap/node-bootstrap.respec.node.mjs.map +1 -0
- package/dist/cli/cli-arg-parser.d.mts +27 -0
- package/dist/cli/cli-arg-parser.d.mts.map +1 -0
- package/dist/cli/cli-arg-parser.mjs +96 -0
- package/dist/cli/cli-arg-parser.mjs.map +1 -0
- package/dist/cli/cli-arg-parser.respec.node.d.mts +7 -0
- package/dist/cli/cli-arg-parser.respec.node.d.mts.map +1 -0
- package/dist/cli/cli-arg-parser.respec.node.mjs +35 -0
- package/dist/cli/cli-arg-parser.respec.node.mjs.map +1 -0
- package/dist/cli/cli-constants.d.mts +26 -0
- package/dist/cli/cli-constants.d.mts.map +1 -0
- package/dist/cli/cli-constants.mjs +67 -0
- package/dist/cli/cli-constants.mjs.map +1 -0
- package/dist/cli/cli-e2e.respec.node.d.mts +8 -0
- package/dist/cli/cli-e2e.respec.node.d.mts.map +1 -0
- package/dist/cli/cli-e2e.respec.node.mjs +263 -0
- package/dist/cli/cli-e2e.respec.node.mjs.map +1 -0
- package/dist/cli/commands/add-cmd.d.mts +20 -0
- package/dist/cli/commands/add-cmd.d.mts.map +1 -0
- package/dist/cli/commands/add-cmd.mjs +333 -0
- package/dist/cli/commands/add-cmd.mjs.map +1 -0
- package/dist/cli/commands/branch-checkout-cmd.respec.node.d.mts +7 -0
- package/dist/cli/commands/branch-checkout-cmd.respec.node.d.mts.map +1 -0
- package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs +288 -0
- package/dist/cli/commands/branch-checkout-cmd.respec.node.mjs.map +1 -0
- package/dist/cli/commands/branch-cmd.d.mts +25 -0
- package/dist/cli/commands/branch-cmd.d.mts.map +1 -0
- package/dist/cli/commands/branch-cmd.mjs +187 -0
- package/dist/cli/commands/branch-cmd.mjs.map +1 -0
- package/dist/cli/commands/checkout-cmd.d.mts +21 -0
- package/dist/cli/commands/checkout-cmd.d.mts.map +1 -0
- package/dist/cli/commands/checkout-cmd.mjs +154 -0
- package/dist/cli/commands/checkout-cmd.mjs.map +1 -0
- package/dist/cli/commands/commit-cmd.d.mts +23 -0
- package/dist/cli/commands/commit-cmd.d.mts.map +1 -0
- package/dist/cli/commands/commit-cmd.mjs +326 -0
- package/dist/cli/commands/commit-cmd.mjs.map +1 -0
- package/dist/cli/commands/commit-log-cmd.respec.node.d.mts +7 -0
- package/dist/cli/commands/commit-log-cmd.respec.node.d.mts.map +1 -0
- package/dist/cli/commands/commit-log-cmd.respec.node.mjs +251 -0
- package/dist/cli/commands/commit-log-cmd.respec.node.mjs.map +1 -0
- package/dist/cli/commands/init-cmd.d.mts +20 -0
- package/dist/cli/commands/init-cmd.d.mts.map +1 -0
- package/dist/cli/commands/init-cmd.mjs +119 -0
- package/dist/cli/commands/init-cmd.mjs.map +1 -0
- package/dist/cli/commands/init-cmd.respec.node.d.mts +7 -0
- package/dist/cli/commands/init-cmd.respec.node.d.mts.map +1 -0
- package/dist/cli/commands/init-cmd.respec.node.mjs +40 -0
- package/dist/cli/commands/init-cmd.respec.node.mjs.map +1 -0
- package/dist/cli/commands/log-cmd.d.mts +27 -0
- package/dist/cli/commands/log-cmd.d.mts.map +1 -0
- package/dist/cli/commands/log-cmd.mjs +146 -0
- package/dist/cli/commands/log-cmd.mjs.map +1 -0
- package/dist/cli/commands/status-add-cmd.respec.node.d.mts +7 -0
- package/dist/cli/commands/status-add-cmd.respec.node.d.mts.map +1 -0
- package/dist/cli/commands/status-add-cmd.respec.node.mjs +215 -0
- package/dist/cli/commands/status-add-cmd.respec.node.mjs.map +1 -0
- package/dist/cli/commands/status-cmd.d.mts +25 -0
- package/dist/cli/commands/status-cmd.d.mts.map +1 -0
- package/dist/cli/commands/status-cmd.mjs +286 -0
- package/dist/cli/commands/status-cmd.mjs.map +1 -0
- package/dist/cli/vcs-cli-main.d.mts +14 -0
- package/dist/cli/vcs-cli-main.d.mts.map +1 -0
- package/dist/cli/vcs-cli-main.mjs +136 -0
- package/dist/cli/vcs-cli-main.mjs.map +1 -0
- package/dist/engine/branch/branch-graph-helper.d.mts +19 -0
- package/dist/engine/branch/branch-graph-helper.d.mts.map +1 -0
- package/dist/engine/branch/branch-graph-helper.mjs +49 -0
- package/dist/engine/branch/branch-graph-helper.mjs.map +1 -0
- package/dist/engine/branch/branch-helper.d.mts +26 -0
- package/dist/engine/branch/branch-helper.d.mts.map +1 -0
- package/dist/engine/branch/branch-helper.mjs +57 -0
- package/dist/engine/branch/branch-helper.mjs.map +1 -0
- package/dist/engine/branch/branch-space-helper.d.mts +22 -0
- package/dist/engine/branch/branch-space-helper.d.mts.map +1 -0
- package/dist/engine/branch/branch-space-helper.mjs +77 -0
- package/dist/engine/branch/branch-space-helper.mjs.map +1 -0
- package/dist/engine/branch/branch-space.respec.node.d.mts +8 -0
- package/dist/engine/branch/branch-space.respec.node.d.mts.map +1 -0
- package/dist/engine/branch/branch-space.respec.node.mjs +138 -0
- package/dist/engine/branch/branch-space.respec.node.mjs.map +1 -0
- package/dist/engine/branch/branch-types.d.mts +26 -0
- package/dist/engine/branch/branch-types.d.mts.map +1 -0
- package/dist/engine/branch/branch-types.mjs +7 -0
- package/dist/engine/branch/branch-types.mjs.map +1 -0
- package/dist/engine/diff/line-diff-helper.d.mts +76 -0
- package/dist/engine/diff/line-diff-helper.d.mts.map +1 -0
- package/dist/engine/diff/line-diff-helper.mjs +144 -0
- package/dist/engine/diff/line-diff-helper.mjs.map +1 -0
- package/dist/engine/diff/line-diff-helper.respec.node.d.mts +7 -0
- package/dist/engine/diff/line-diff-helper.respec.node.d.mts.map +1 -0
- package/dist/engine/diff/line-diff-helper.respec.node.mjs +66 -0
- package/dist/engine/diff/line-diff-helper.respec.node.mjs.map +1 -0
- package/dist/engine/filter/glob-helper.d.mts +51 -0
- package/dist/engine/filter/glob-helper.d.mts.map +1 -0
- package/dist/engine/filter/glob-helper.mjs +132 -0
- package/dist/engine/filter/glob-helper.mjs.map +1 -0
- package/dist/engine/filter/glob-helper.respec.node.d.mts +7 -0
- package/dist/engine/filter/glob-helper.respec.node.d.mts.map +1 -0
- package/dist/engine/filter/glob-helper.respec.node.mjs +78 -0
- package/dist/engine/filter/glob-helper.respec.node.mjs.map +1 -0
- package/dist/engine/index/index-helper.d.mts +78 -0
- package/dist/engine/index/index-helper.d.mts.map +1 -0
- package/dist/engine/index/index-helper.mjs +289 -0
- package/dist/engine/index/index-helper.mjs.map +1 -0
- package/dist/engine/index/index-types.d.mts +63 -0
- package/dist/engine/index/index-types.d.mts.map +1 -0
- package/dist/engine/index/index-types.mjs +7 -0
- package/dist/engine/index/index-types.mjs.map +1 -0
- package/dist/engine/item/item-atom-helper.d.mts +20 -0
- package/dist/engine/item/item-atom-helper.d.mts.map +1 -0
- package/dist/engine/item/item-atom-helper.mjs +30 -0
- package/dist/engine/item/item-atom-helper.mjs.map +1 -0
- package/dist/engine/item/item-helper.d.mts +37 -0
- package/dist/engine/item/item-helper.d.mts.map +1 -0
- package/dist/engine/item/item-helper.mjs +194 -0
- package/dist/engine/item/item-helper.mjs.map +1 -0
- package/dist/engine/item/item-types.d.mts +127 -0
- package/dist/engine/item/item-types.d.mts.map +1 -0
- package/dist/engine/item/item-types.mjs +16 -0
- package/dist/engine/item/item-types.mjs.map +1 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +7 -0
- package/dist/index.mjs.map +1 -0
- package/dist/respec-gib.node.d.mts +7 -0
- package/dist/respec-gib.node.d.mts.map +1 -0
- package/dist/respec-gib.node.mjs +11 -0
- package/dist/respec-gib.node.mjs.map +1 -0
- package/dist/vcs-gib-constants.d.mts +7 -0
- package/dist/vcs-gib-constants.d.mts.map +1 -0
- package/dist/vcs-gib-constants.mjs +7 -0
- package/dist/vcs-gib-constants.mjs.map +1 -0
- package/dist/vcs-gib.respec.node.d.mts +8 -0
- package/dist/vcs-gib.respec.node.d.mts.map +1 -0
- package/dist/vcs-gib.respec.node.mjs +82 -0
- package/dist/vcs-gib.respec.node.mjs.map +1 -0
- package/generate-version-file.js +20 -0
- package/package.json +28 -0
- package/src/AUTO-GENERATED-version.mts +5 -0
- package/src/assumptions.respec.mts +50 -0
- package/src/bootstrap/node-bootstrap.mts +198 -0
- package/src/bootstrap/node-bootstrap.respec.node.mts +35 -0
- package/src/cli/cli-arg-parser.mts +119 -0
- package/src/cli/cli-arg-parser.respec.node.mts +45 -0
- package/src/cli/cli-constants.mts +77 -0
- package/src/cli/cli-e2e.respec.node.mts +318 -0
- package/src/cli/commands/add-cmd.mts +415 -0
- package/src/cli/commands/branch-checkout-cmd.respec.node.mts +322 -0
- package/src/cli/commands/branch-cmd.mts +243 -0
- package/src/cli/commands/checkout-cmd.mts +202 -0
- package/src/cli/commands/commit-cmd.mts +421 -0
- package/src/cli/commands/commit-log-cmd.respec.node.mts +276 -0
- package/src/cli/commands/init-cmd.mts +152 -0
- package/src/cli/commands/init-cmd.respec.node.mts +49 -0
- package/src/cli/commands/log-cmd.mts +197 -0
- package/src/cli/commands/status-add-cmd.respec.node.mts +246 -0
- package/src/cli/commands/status-cmd.mts +366 -0
- package/src/cli/vcs-cli-main.mts +153 -0
- package/src/engine/branch/branch-graph-helper.mts +69 -0
- package/src/engine/branch/branch-helper.mts +79 -0
- package/src/engine/branch/branch-space-helper.mts +104 -0
- package/src/engine/branch/branch-space.respec.node.mts +158 -0
- package/src/engine/branch/branch-types.mts +29 -0
- package/src/engine/diff/line-diff-helper.mts +210 -0
- package/src/engine/diff/line-diff-helper.respec.node.mts +84 -0
- package/src/engine/filter/glob-helper.mts +165 -0
- package/src/engine/filter/glob-helper.respec.node.mts +94 -0
- package/src/engine/index/index-helper.mts +378 -0
- package/src/engine/index/index-types.mts +66 -0
- package/src/engine/item/item-atom-helper.mts +30 -0
- package/src/engine/item/item-helper.mts +239 -0
- package/src/engine/item/item-types.mts +136 -0
- package/src/index.mts +7 -0
- package/src/respec-gib.node.mts +12 -0
- package/src/vcs-gib-constants.mts +7 -0
- package/src/vcs-gib.respec.node.mts +96 -0
- package/test_runs/001-hello-node/20260728_090100_0001-flow-core-main.md +39 -0
- package/test_runs/001-hello-node/20260728_090200_0003-flow-branching-worktree.md +54 -0
- package/test_runs/001-hello-node/20260728_090300_0002-flow-selective-add.md +45 -0
- package/test_runs/001-hello-node/20260728_142100_0007-flow-edge-cases.md +44 -0
- package/test_runs/001-hello-node/20260728_142400_0005-flow-hardcoded-ignores.md +36 -0
- package/tools/pack-for-test.mjs +73 -0
- package/tsconfig.json +18 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vcs-gib.respec.node.d.mts","sourceRoot":"","sources":["../src/vcs-gib.respec.node.mts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module vcs-gib.respec.node
|
|
3
|
+
*
|
|
4
|
+
* Full Engine Cycle Integration Tests for @ibgib/vcs-gib.
|
|
5
|
+
* Tests Metaspace bootstrap, canonical ib atoms, item creation, branch spaces, and index tracking.
|
|
6
|
+
*/
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import { respecfully, ifWe, iReckon } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
|
|
10
|
+
import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
|
|
11
|
+
import { Factory_V1 } from '@ibgib/ts-gib/dist/V1/factory.mjs';
|
|
12
|
+
import { bootstrapVcsMetaspace } from './bootstrap/node-bootstrap.mjs';
|
|
13
|
+
import { getB2tFSItemIb } from './engine/item/item-atom-helper.mjs';
|
|
14
|
+
import { createB2tFSBranchIbGib, getB2tFSBranchSpaceName } from './engine/branch/branch-helper.mjs';
|
|
15
|
+
import { createB2tFSIndexIbGib, getSpaceQualifiedIbGibAddr, parseSpaceQualifiedIbGibAddr } from './engine/index/index-helper.mjs';
|
|
16
|
+
const lc = `[apps/vcs-gib/src/vcs-gib.respec.node.mts]`;
|
|
17
|
+
await respecfully(lc, `vcs-gib Full Engine Cycle`, async () => {
|
|
18
|
+
await respecfully(lc, `Canonical ib Atoms`, async () => {
|
|
19
|
+
await ifWe(lc, `formats canonical space-delimited ib atom strings`, async () => {
|
|
20
|
+
const ib = getB2tFSItemIb('file', 'index.mts', 'hash123');
|
|
21
|
+
iReckon(lc, ib).includes('b2tfs_item file index.mts v1 hash123');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
await respecfully(lc, `Space-Qualified Addresses`, async () => {
|
|
25
|
+
await ifWe(lc, `formats and parses space-qualified addresses`, async () => {
|
|
26
|
+
const sq = getSpaceQualifiedIbGibAddr('space_a', 'item^gib123');
|
|
27
|
+
iReckon(lc, sq).willEqual('v:1^spaceId:space_a^item^gib123');
|
|
28
|
+
const parsed = parseSpaceQualifiedIbGibAddr(sq);
|
|
29
|
+
iReckon(lc, parsed?.spaceId).willEqual('space_a');
|
|
30
|
+
iReckon(lc, parsed?.ibGibAddr).willEqual('item^gib123');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
await respecfully(lc, `Branch Spaces & Index Tracking`, async () => {
|
|
34
|
+
await ifWe(lc, `initializes metaspace, creates branch, and registers index`, async () => {
|
|
35
|
+
const testDir = path.join(process.cwd(), '.test_cycle_repo');
|
|
36
|
+
try {
|
|
37
|
+
const { metaspace, localSpace } = await bootstrapVcsMetaspace({
|
|
38
|
+
repoPath: testDir,
|
|
39
|
+
vcsFolderName: '.vcsgib_cycle_test',
|
|
40
|
+
defaultSpaceName: 'test_space',
|
|
41
|
+
});
|
|
42
|
+
// Create root folder item
|
|
43
|
+
const itemRes = await Factory_V1.firstGen({
|
|
44
|
+
parentIbGib: ROOT,
|
|
45
|
+
ib: getB2tFSItemIb('folder', 'root', 'root_hash'),
|
|
46
|
+
data: {
|
|
47
|
+
name: 'root',
|
|
48
|
+
nameHash: 'root_hash',
|
|
49
|
+
fsType: 'folder',
|
|
50
|
+
diffTransactionId: 'tx_123',
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const rootItem = itemRes.newIbGib;
|
|
54
|
+
// Create Branch IbGib
|
|
55
|
+
const branchName = 'main';
|
|
56
|
+
const branchSpaceName = getB2tFSBranchSpaceName(branchName);
|
|
57
|
+
iReckon(lc, branchSpaceName).willEqual('b2s_main');
|
|
58
|
+
const branchIbGib = await createB2tFSBranchIbGib({
|
|
59
|
+
branchName,
|
|
60
|
+
rootItem,
|
|
61
|
+
space: localSpace,
|
|
62
|
+
metaspace,
|
|
63
|
+
});
|
|
64
|
+
iReckon(lc, branchIbGib.data?.name).willEqual('main');
|
|
65
|
+
// Create Index IbGib
|
|
66
|
+
const indexIbGib = await createB2tFSIndexIbGib({
|
|
67
|
+
spaceId: 'local_space_uuid',
|
|
68
|
+
activeSpaceId: 'local_space_uuid',
|
|
69
|
+
space: localSpace,
|
|
70
|
+
metaspace,
|
|
71
|
+
});
|
|
72
|
+
iReckon(lc, indexIbGib.data?.mySpaceId).willEqual('local_space_uuid');
|
|
73
|
+
iReckon(lc, indexIbGib.data?.staged_item).willEqual([]);
|
|
74
|
+
iReckon(lc, indexIbGib.rel8ns?.staged_item).isGonnaBeFalsy();
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=vcs-gib.respec.node.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vcs-gib.respec.node.mjs","sourceRoot":"","sources":["../src/vcs-gib.respec.node.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const packageJsonPath = path.join(__dirname, 'package.json');
|
|
9
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
10
|
+
|
|
11
|
+
const versionContent = `/**
|
|
12
|
+
* @module AUTO-GENERATED-version
|
|
13
|
+
* Auto-generated version constant. Do NOT edit directly.
|
|
14
|
+
*/
|
|
15
|
+
export const AUTO_GENERATED_VERSION = '${pkg.version}';
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const outputPath = path.join(__dirname, 'src', 'AUTO-GENERATED-version.mts');
|
|
19
|
+
fs.writeFileSync(outputPath, versionContent, 'utf8');
|
|
20
|
+
console.log(`[generate-version-file] Updated ${outputPath} to version ${pkg.version}`);
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ibgib/vcs-gib",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"ibgib": "dist/cli/vcs-cli-main.mjs",
|
|
10
|
+
"vcs": "dist/cli/vcs-cli-main.mjs"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"test": "node dist/respec-gib.node.mjs",
|
|
15
|
+
"test:node:nobuild": "node dist/respec-gib.node.mjs",
|
|
16
|
+
"generate-version": "node generate-version-file.js",
|
|
17
|
+
"build:for:test": "node tools/pack-for-test.mjs",
|
|
18
|
+
"pack": "npm pack --pack-destination=\"./published\"",
|
|
19
|
+
"prepare:publish": "npm version patch && node ../../build/dist/concrete-build/build-vcs-gib.mjs --prod && npm run pack"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@ibgib/helper-gib": "^0.0.36",
|
|
23
|
+
"@ibgib/ts-gib": "^0.5.33",
|
|
24
|
+
"@ibgib/encrypt-gib": "^0.2.37",
|
|
25
|
+
"@ibgib/core-gib": "^0.1.69",
|
|
26
|
+
"@ibgib/node-gib": "^0.0.13"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ifWe, iReckon, respecfully
|
|
3
|
+
} from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
|
|
4
|
+
import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
5
|
+
|
|
6
|
+
const maam = `[${import.meta.url}]`, sir = maam;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* wrapper that uses crypto.subtle under the hood (i.e. doesn't hash using ts-gib)
|
|
10
|
+
*
|
|
11
|
+
* notes:
|
|
12
|
+
*
|
|
13
|
+
* * i did in fact copy this from ts-gib though, but we're testing simply that the
|
|
14
|
+
* context (node/browser/whatever) has this since it's integral to all things ibgib.
|
|
15
|
+
*/
|
|
16
|
+
async function cryptoSubtleHash({
|
|
17
|
+
s,
|
|
18
|
+
algorithm = 'SHA-256',
|
|
19
|
+
}: {
|
|
20
|
+
s: string,
|
|
21
|
+
algorithm?: string,
|
|
22
|
+
}): Promise<string> {
|
|
23
|
+
let { subtle } = globalThis.crypto;
|
|
24
|
+
if (!s) { throw new Error(`[${cryptoSubtleHash.name}] s is required`) }
|
|
25
|
+
if (!algorithm) { throw new Error(`[${cryptoSubtleHash.name}] algorithm is required`) }
|
|
26
|
+
try {
|
|
27
|
+
const msgUint8 = new TextEncoder().encode(s);
|
|
28
|
+
const buffer = await subtle.digest(algorithm, msgUint8);
|
|
29
|
+
const asArray = Array.from(new Uint8Array(buffer));
|
|
30
|
+
return asArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.error(e.message ?? e);
|
|
33
|
+
throw e;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
await respecfully(sir, `non-ts-gib isomorphic crypto hashing`, async () => {
|
|
38
|
+
|
|
39
|
+
await ifWe(sir, `should digest simple string consistently using crypto.subtle directly `, async () => {
|
|
40
|
+
let h = await cryptoSubtleHash({ s: '42' });
|
|
41
|
+
iReckon(sir, h).asTo('42').isGonnaBe('73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await ifWe(sir, `should digest simple stringified ibgib consistently using crypto.subtle directly `, async () => {
|
|
45
|
+
let ibgib: IbGib_V1 = { ib: 'ib', gib: 'gib' };
|
|
46
|
+
let h = await cryptoSubtleHash({ s: JSON.stringify(ibgib) }); // doesn't use ts-gib but consistent stringifying json is important
|
|
47
|
+
iReckon(sir, h).asTo('ib^gib').isGonnaBe('cbad0694a257358c044611ea1fa88ace71a01a9b8409d2354d0387d8043f7671');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-bootstrap
|
|
3
|
+
*
|
|
4
|
+
* Rapid Node Metaspace bootstrap helper aligned with space-gib startup principles.
|
|
5
|
+
* Moves execution from CLI start to "ibgib environment" rapidly without process.chdir() hacks.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import fs from 'node:fs/promises';
|
|
10
|
+
|
|
11
|
+
import { clone, delay } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
12
|
+
import { getGib } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
|
|
13
|
+
import { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';
|
|
14
|
+
import { updateBootstrapIbGib } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
|
|
15
|
+
import { Metaspace_Nodespace } from '@ibgib/node-gib/dist/witness/space/metaspace/metaspace-nodespace/metaspace-nodespace.mjs';
|
|
16
|
+
import { NodeFilesystemSpace_V1 } from '@ibgib/node-gib/dist/witness/space/node-filesystem-space/node-filesystem-space-v1.mjs';
|
|
17
|
+
import { DEFAULT_NODE_FILESYSTEM_SPACE_DATA_V1 } from '@ibgib/node-gib/dist/witness/space/node-filesystem-space/node-filesystem-space-types.mjs';
|
|
18
|
+
import { fnCreateNewLocalSpace, fnDtoToSpace_nodeFilesystem } from '@ibgib/node-gib/dist/witness/space/metaspace/metaspace-nodespace/metaspace-nodespace-helper.mjs';
|
|
19
|
+
|
|
20
|
+
import { GLOBAL_LOG_A_LOT } from '../vcs-gib-constants.mjs';
|
|
21
|
+
|
|
22
|
+
const lcFile = `[node-bootstrap]`;
|
|
23
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
24
|
+
|
|
25
|
+
export interface BootstrapVcsMetaspaceOpts {
|
|
26
|
+
/**
|
|
27
|
+
* Absolute or relative path to target repository directory. Defaults to process.cwd()
|
|
28
|
+
*/
|
|
29
|
+
repoPath?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Subfolder for vcs-gib metadata storage. Defaults to '.vcsgib'
|
|
32
|
+
*/
|
|
33
|
+
vcsFolderName?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Default space name for non-interactive headless testing. Defaults to 'vcs_space'
|
|
36
|
+
*/
|
|
37
|
+
defaultSpaceName?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface BootstrapVcsMetaspaceResult {
|
|
41
|
+
metaspace: Metaspace_Nodespace;
|
|
42
|
+
localSpace: IbGibSpaceAny;
|
|
43
|
+
vcsPath: string;
|
|
44
|
+
repoRoot: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Bootstraps Metaspace_Nodespace and initializes the local repository space.
|
|
49
|
+
* Moves execution into the ibgib environment rapidly without process.chdir() directory hacks.
|
|
50
|
+
* Performs upward discovery of .vcsgib metadata folder.
|
|
51
|
+
*/
|
|
52
|
+
export async function bootstrapVcsMetaspace(
|
|
53
|
+
opts: BootstrapVcsMetaspaceOpts = {}
|
|
54
|
+
): Promise<BootstrapVcsMetaspaceResult> {
|
|
55
|
+
const lc = `${lcFile}[${bootstrapVcsMetaspace.name}]`;
|
|
56
|
+
try {
|
|
57
|
+
if (logalot) { console.log(`${lc} starting... (I: 9f8a0b1c2d3e4f5a6b7c8d9e0f1a2b3c)`); }
|
|
58
|
+
const {
|
|
59
|
+
repoPath = process.cwd(),
|
|
60
|
+
vcsFolderName = '.vcsgib',
|
|
61
|
+
} = opts;
|
|
62
|
+
|
|
63
|
+
let currentDir = path.resolve(repoPath);
|
|
64
|
+
let foundVcsPath: string | undefined;
|
|
65
|
+
let repoRoot = currentDir;
|
|
66
|
+
|
|
67
|
+
while (true) {
|
|
68
|
+
const candidateVcsPath = path.join(currentDir, vcsFolderName);
|
|
69
|
+
let exists = false;
|
|
70
|
+
try {
|
|
71
|
+
const stat = await fs.stat(candidateVcsPath);
|
|
72
|
+
if (stat.isDirectory()) {
|
|
73
|
+
exists = true;
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
exists = false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (exists) {
|
|
80
|
+
foundVcsPath = candidateVcsPath;
|
|
81
|
+
repoRoot = currentDir;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const parentDir = path.dirname(currentDir);
|
|
86
|
+
if (parentDir === currentDir) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
currentDir = parentDir;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const vcsPath = foundVcsPath || path.resolve(repoPath, vcsFolderName);
|
|
93
|
+
if (!foundVcsPath) {
|
|
94
|
+
repoRoot = path.resolve(repoPath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const safeRepoDir = path.basename(repoRoot).replace(/[^a-zA-Z0-9_\-]/g, '_');
|
|
98
|
+
const defaultSpaceName = opts.defaultSpaceName || `vcs_${safeRepoDir}`;
|
|
99
|
+
|
|
100
|
+
if (logalot) { console.log(`${lc} initializing vcsMetaspace at vcsPath: ${vcsPath}, repoRoot: ${repoRoot} (I: 4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c9d)`); }
|
|
101
|
+
|
|
102
|
+
// Read localSpaceId from index projection if repository has been initialized
|
|
103
|
+
let localSpaceId: string | undefined;
|
|
104
|
+
try {
|
|
105
|
+
const projFile = path.join(vcsPath, 'vcs_index_projection.json');
|
|
106
|
+
const projRaw = await fs.readFile(projFile, 'utf8');
|
|
107
|
+
const projData = JSON.parse(projRaw);
|
|
108
|
+
if (projData && projData.spaceId) {
|
|
109
|
+
localSpaceId = projData.spaceId;
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
// Projection file missing before init
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Instantiate Metaspace_Nodespace
|
|
116
|
+
const metaspace = new Metaspace_Nodespace(undefined);
|
|
117
|
+
metaspace.fnUpdateBootstrap = async (newSpace) => {
|
|
118
|
+
await updateBootstrapIbGib({ zeroSpace: metaspace.zeroSpace, space: newSpace });
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
await metaspace.initialize({
|
|
122
|
+
spaceName: defaultSpaceName,
|
|
123
|
+
metaspaceFactory: {
|
|
124
|
+
fnZeroSpaceFactory: () => {
|
|
125
|
+
const zeroSpaceData = {
|
|
126
|
+
...clone(DEFAULT_NODE_FILESYSTEM_SPACE_DATA_V1),
|
|
127
|
+
baseDir: vcsPath,
|
|
128
|
+
};
|
|
129
|
+
const zeroSpace = new NodeFilesystemSpace_V1(zeroSpaceData);
|
|
130
|
+
zeroSpace.gib = 'gib';
|
|
131
|
+
return zeroSpace;
|
|
132
|
+
},
|
|
133
|
+
fnDefaultLocalSpaceFactory: async (spaceOpts) => {
|
|
134
|
+
const space = await fnCreateNewLocalSpace(spaceOpts);
|
|
135
|
+
if (space && space.data) {
|
|
136
|
+
space.data.baseDir = vcsPath;
|
|
137
|
+
space.gib = await getGib({ ibGib: space, hasTjp: true });
|
|
138
|
+
}
|
|
139
|
+
return space;
|
|
140
|
+
},
|
|
141
|
+
fnDtoToSpace: async (spaceDto) => {
|
|
142
|
+
const space = await fnDtoToSpace_nodeFilesystem(spaceDto);
|
|
143
|
+
if (space && space.data) {
|
|
144
|
+
space.data.baseDir = vcsPath;
|
|
145
|
+
}
|
|
146
|
+
return space;
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
getFnAlert: () => async ({ title, msg }) => {
|
|
150
|
+
if (logalot) { console.log(`${lc} [Alert] ${title}: ${msg} (I: 7e6f5d4c3b2a1f0e9d8c7b6a5f4e3d2c)`); }
|
|
151
|
+
},
|
|
152
|
+
getFnPrompt: () => async ({ title, msg }) => {
|
|
153
|
+
if (logalot) { console.log(`${lc} [Prompt] ${title}: ${msg} (I: 2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e)`); }
|
|
154
|
+
return defaultSpaceName;
|
|
155
|
+
},
|
|
156
|
+
getFnPromptPassword: () => async (title, msg) => {
|
|
157
|
+
if (logalot) { console.log(`${lc} [PromptPwd] ${title}: ${msg} (I: 5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c)`); }
|
|
158
|
+
return null;
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
while (!metaspace.initialized) {
|
|
163
|
+
await delay(10);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const localSpace = await metaspace.getLocalUserSpace({
|
|
167
|
+
localSpaceId,
|
|
168
|
+
lock: false,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
if (!localSpace) {
|
|
172
|
+
throw new Error(`Failed to initialize localUserSpace in metaspace (E: 8192a472c9104b2c)`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (localSpace.data && localSpace.data.baseDir !== vcsPath) {
|
|
176
|
+
localSpace.data.baseDir = vcsPath;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await localSpace.initialized;
|
|
180
|
+
|
|
181
|
+
if (logalot) {
|
|
182
|
+
const spaceName = localSpace.data?.name || localSpace.ib;
|
|
183
|
+
console.log(`${lc} Metaspace ready. LocalSpace name/ib: ${spaceName} (I: 1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f)`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
metaspace,
|
|
188
|
+
localSpace,
|
|
189
|
+
vcsPath,
|
|
190
|
+
repoRoot,
|
|
191
|
+
};
|
|
192
|
+
} catch (error: any) {
|
|
193
|
+
console.error(`${lc} ${error?.message || error} (E: 8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d)`);
|
|
194
|
+
throw error;
|
|
195
|
+
} finally {
|
|
196
|
+
if (logalot) { console.log(`${lc} complete. (I: 3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a)`); }
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-bootstrap.respec
|
|
3
|
+
*
|
|
4
|
+
* Unit tests for rapid Node Metaspace bootstrap helper.
|
|
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 { bootstrapVcsMetaspace } from './node-bootstrap.mjs';
|
|
15
|
+
|
|
16
|
+
const lc = `[apps/vcs-gib/src/bootstrap/node-bootstrap.respec.node.mts]`;
|
|
17
|
+
|
|
18
|
+
await respecfully(lc, `Node Metaspace Bootstrap`, async () => {
|
|
19
|
+
|
|
20
|
+
await ifWe(lc, `bootstraps metaspace and local space rapidly without errors`, async () => {
|
|
21
|
+
const testDir = path.join(process.cwd(), '.test_bootstrap_repo');
|
|
22
|
+
try {
|
|
23
|
+
const { metaspace, localSpace, vcsPath } = await bootstrapVcsMetaspace({
|
|
24
|
+
repoPath: testDir,
|
|
25
|
+
vcsFolderName: '.vcsgib_test',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
iReckon(lc, metaspace.initialized).isGonnaBeTrue();
|
|
29
|
+
iReckon(lc, localSpace).isGonnaBeTruthy();
|
|
30
|
+
iReckon(lc, vcsPath).includes('.vcsgib_test');
|
|
31
|
+
} finally {
|
|
32
|
+
await fs.rm(testDir, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module cli-arg-parser
|
|
3
|
+
*
|
|
4
|
+
* Native, zero-dependency command line argument parser for vcs CLI commands.
|
|
5
|
+
* Refactored to use RCLIParamInfo constants and VCS_SUBCOMMANDS definitions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { RCLIParamInfo } from '@ibgib/helper-gib/dist/rcli/rcli-types.mjs';
|
|
9
|
+
import {
|
|
10
|
+
VCS_SUBCOMMANDS,
|
|
11
|
+
VCS_PARAM_MESSAGE,
|
|
12
|
+
VCS_PARAM_BRANCH,
|
|
13
|
+
VCS_PARAM_ALL,
|
|
14
|
+
VCS_PARAM_FORCE,
|
|
15
|
+
VCS_PARAM_VERBOSE,
|
|
16
|
+
VCS_PARAM_HELP,
|
|
17
|
+
VCS_PARAM_SHARE_IGNORED,
|
|
18
|
+
} from './cli-constants.mjs';
|
|
19
|
+
|
|
20
|
+
export type VcsSubcommand = typeof VCS_SUBCOMMANDS[keyof typeof VCS_SUBCOMMANDS];
|
|
21
|
+
|
|
22
|
+
export interface ParsedVcsArgs {
|
|
23
|
+
command: VcsSubcommand;
|
|
24
|
+
positionals: string[];
|
|
25
|
+
flags: {
|
|
26
|
+
message?: string;
|
|
27
|
+
branchName?: string;
|
|
28
|
+
all?: boolean;
|
|
29
|
+
force?: boolean;
|
|
30
|
+
verbose?: boolean;
|
|
31
|
+
help?: boolean;
|
|
32
|
+
shareIgnored?: boolean;
|
|
33
|
+
};
|
|
34
|
+
rawArgs: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function matchesParam(arg: string, paramInfo: RCLIParamInfo): boolean {
|
|
38
|
+
if (!arg || !arg.startsWith('-')) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const stripped = arg.replace(/^-+/, '');
|
|
42
|
+
if (paramInfo.name && stripped === paramInfo.name) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (paramInfo.synonyms && paramInfo.synonyms.includes(stripped)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Parses raw command line argument vector (process.argv.slice(2)).
|
|
53
|
+
*/
|
|
54
|
+
export function parseVcsArgs(argv: string[]): ParsedVcsArgs {
|
|
55
|
+
const rawArgs = [...argv];
|
|
56
|
+
let command: VcsSubcommand = VCS_SUBCOMMANDS.HELP;
|
|
57
|
+
const positionals: string[] = [];
|
|
58
|
+
const flags: ParsedVcsArgs['flags'] = {};
|
|
59
|
+
|
|
60
|
+
const validSubcommands = Object.values(VCS_SUBCOMMANDS) as string[];
|
|
61
|
+
|
|
62
|
+
let i = 0;
|
|
63
|
+
while (i < rawArgs.length) {
|
|
64
|
+
const arg = rawArgs[i];
|
|
65
|
+
|
|
66
|
+
if (matchesParam(arg, VCS_PARAM_HELP)) {
|
|
67
|
+
flags.help = true;
|
|
68
|
+
i++;
|
|
69
|
+
} else if (arg === '--version' || (arg === '-v' && rawArgs.length === 1)) {
|
|
70
|
+
if (command === VCS_SUBCOMMANDS.HELP) {
|
|
71
|
+
command = VCS_SUBCOMMANDS.VERSION;
|
|
72
|
+
}
|
|
73
|
+
i++;
|
|
74
|
+
} else if (matchesParam(arg, VCS_PARAM_MESSAGE)) {
|
|
75
|
+
flags.message = rawArgs[i + 1] || '';
|
|
76
|
+
i += 2;
|
|
77
|
+
} else if (matchesParam(arg, VCS_PARAM_BRANCH)) {
|
|
78
|
+
flags.branchName = rawArgs[i + 1] || '';
|
|
79
|
+
i += 2;
|
|
80
|
+
} else if (matchesParam(arg, VCS_PARAM_ALL)) {
|
|
81
|
+
flags.all = true;
|
|
82
|
+
i++;
|
|
83
|
+
} else if (matchesParam(arg, VCS_PARAM_FORCE)) {
|
|
84
|
+
flags.force = true;
|
|
85
|
+
i++;
|
|
86
|
+
} else if (matchesParam(arg, VCS_PARAM_VERBOSE)) {
|
|
87
|
+
flags.verbose = true;
|
|
88
|
+
i++;
|
|
89
|
+
} else if (matchesParam(arg, VCS_PARAM_SHARE_IGNORED)) {
|
|
90
|
+
flags.shareIgnored = true;
|
|
91
|
+
i++;
|
|
92
|
+
} else if (!arg.startsWith('-')) {
|
|
93
|
+
if (command === VCS_SUBCOMMANDS.HELP) {
|
|
94
|
+
const normalized = arg.toLowerCase();
|
|
95
|
+
if (validSubcommands.includes(normalized)) {
|
|
96
|
+
command = normalized as VcsSubcommand;
|
|
97
|
+
} else {
|
|
98
|
+
positionals.push(arg);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
positionals.push(arg);
|
|
102
|
+
}
|
|
103
|
+
i++;
|
|
104
|
+
} else {
|
|
105
|
+
i++;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (flags.help && command !== VCS_SUBCOMMANDS.VERSION) {
|
|
110
|
+
command = VCS_SUBCOMMANDS.HELP;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
command,
|
|
115
|
+
positionals,
|
|
116
|
+
flags,
|
|
117
|
+
rawArgs,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module cli-arg-parser.respec
|
|
3
|
+
*
|
|
4
|
+
* Unit tests for zero-dependency vcs CLI argument parser.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
respecfully, ifWe, iReckon
|
|
9
|
+
} from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
|
|
10
|
+
|
|
11
|
+
import { parseVcsArgs } from './cli-arg-parser.mjs';
|
|
12
|
+
|
|
13
|
+
const lc = `[apps/vcs-gib/src/cli/cli-arg-parser.respec.node.mts]`;
|
|
14
|
+
|
|
15
|
+
await respecfully(lc, `Zero-Dependency CLI Argument Parser`, async () => {
|
|
16
|
+
|
|
17
|
+
await respecfully(lc, `parseVcsArgs`, async () => {
|
|
18
|
+
await ifWe(lc, `parses init command and target path positional`, async () => {
|
|
19
|
+
const parsed = parseVcsArgs(['init', 'my_repo']);
|
|
20
|
+
iReckon(lc, parsed.command).willEqual('init');
|
|
21
|
+
iReckon(lc, parsed.positionals[0]).willEqual('my_repo');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await ifWe(lc, `parses commit command with message flag -m`, async () => {
|
|
25
|
+
const parsed = parseVcsArgs(['commit', '-m', 'initial commit']);
|
|
26
|
+
iReckon(lc, parsed.command).willEqual('commit');
|
|
27
|
+
iReckon(lc, parsed.flags.message).willEqual('initial commit');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
await ifWe(lc, `parses add command with --all flag and positionals`, async () => {
|
|
31
|
+
const parsed = parseVcsArgs(['add', 'src/index.mts', '--all']);
|
|
32
|
+
iReckon(lc, parsed.command).willEqual('add');
|
|
33
|
+
iReckon(lc, parsed.positionals[0]).willEqual('src/index.mts');
|
|
34
|
+
iReckon(lc, parsed.flags.all).isGonnaBeTrue();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await ifWe(lc, `defaults to help command when no args or --help specified`, async () => {
|
|
38
|
+
const parsed1 = parseVcsArgs([]);
|
|
39
|
+
iReckon(lc, parsed1.command).willEqual('help');
|
|
40
|
+
|
|
41
|
+
const parsed2 = parseVcsArgs(['status', '--help']);
|
|
42
|
+
iReckon(lc, parsed2.command).willEqual('help');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module cli-constants
|
|
3
|
+
*
|
|
4
|
+
* Constants and RCLIParamInfo parameter definitions for vcs CLI commands.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { RCLIParamInfo } from '@ibgib/helper-gib/dist/rcli/rcli-types.mjs';
|
|
8
|
+
|
|
9
|
+
export const VCS_CMD_NAME = 'vcs';
|
|
10
|
+
|
|
11
|
+
export const VCS_SUBCOMMANDS = {
|
|
12
|
+
INIT: 'init',
|
|
13
|
+
STATUS: 'status',
|
|
14
|
+
ADD: 'add',
|
|
15
|
+
COMMIT: 'commit',
|
|
16
|
+
LOG: 'log',
|
|
17
|
+
BRANCH: 'branch',
|
|
18
|
+
CHECKOUT: 'checkout',
|
|
19
|
+
HELP: 'help',
|
|
20
|
+
VERSION: 'version',
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
export const VCS_PARAM_MESSAGE: RCLIParamInfo = {
|
|
24
|
+
name: 'message',
|
|
25
|
+
synonyms: ['m'],
|
|
26
|
+
description: 'Commit message description',
|
|
27
|
+
isFlag: false,
|
|
28
|
+
argTypeName: 'string',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const VCS_PARAM_BRANCH: RCLIParamInfo = {
|
|
32
|
+
name: 'branch',
|
|
33
|
+
synonyms: ['b'],
|
|
34
|
+
description: 'Target branch name',
|
|
35
|
+
isFlag: false,
|
|
36
|
+
argTypeName: 'string',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const VCS_PARAM_ALL: RCLIParamInfo = {
|
|
40
|
+
name: 'all',
|
|
41
|
+
synonyms: ['a'],
|
|
42
|
+
description: 'Stage all tracked and untracked files',
|
|
43
|
+
isFlag: true,
|
|
44
|
+
argTypeName: 'boolean',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const VCS_PARAM_FORCE: RCLIParamInfo = {
|
|
48
|
+
name: 'force',
|
|
49
|
+
synonyms: ['f'],
|
|
50
|
+
description: 'Force operation execution',
|
|
51
|
+
isFlag: true,
|
|
52
|
+
argTypeName: 'boolean',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const VCS_PARAM_VERBOSE: RCLIParamInfo = {
|
|
56
|
+
name: 'verbose',
|
|
57
|
+
synonyms: ['v'],
|
|
58
|
+
description: 'Enable detailed verbose console logging',
|
|
59
|
+
isFlag: true,
|
|
60
|
+
argTypeName: 'boolean',
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const VCS_PARAM_HELP: RCLIParamInfo = {
|
|
64
|
+
name: 'help',
|
|
65
|
+
synonyms: ['h'],
|
|
66
|
+
description: 'Display CLI help information',
|
|
67
|
+
isFlag: true,
|
|
68
|
+
argTypeName: 'boolean',
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const VCS_PARAM_SHARE_IGNORED: RCLIParamInfo = {
|
|
72
|
+
name: 'share-ignored',
|
|
73
|
+
synonyms: ['link-ignored'],
|
|
74
|
+
description: 'Share/symlink ignored directories across branch worktrees',
|
|
75
|
+
isFlag: true,
|
|
76
|
+
argTypeName: 'boolean',
|
|
77
|
+
};
|