@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,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module index-helper
|
|
3
|
+
*
|
|
4
|
+
* B2tFS Index Helper functions: space-qualified address formatting and branch index tracking.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
|
|
10
|
+
import { getUUID, extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
11
|
+
import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
|
|
12
|
+
import { Factory_V1 } from '@ibgib/ts-gib/dist/V1/factory.mjs';
|
|
13
|
+
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
14
|
+
import { getIbGibsFromCache_fallbackToSpaces } from '@ibgib/core-gib/dist/common/other/ibgib-helper.mjs';
|
|
15
|
+
import { MetaspaceService } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs';
|
|
16
|
+
import { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';
|
|
17
|
+
import { putInSpace, persistTransformResult } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
|
|
18
|
+
|
|
19
|
+
import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
|
|
20
|
+
import { SpaceQualifiedIbGibAddr, B2tFSIndexIbGib_V1, B2tFSIndexData_V1, B2tFSIndexRel8ns_V1 } from './index-types.mjs';
|
|
21
|
+
|
|
22
|
+
const lcFile = `[index-helper]`;
|
|
23
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
24
|
+
|
|
25
|
+
export const SOFT_ADDR_DATA_KEY_PREFIX = '@';
|
|
26
|
+
export const SOFT_ADDR_DATA_KEY_PREFIX_SPACE_QUALIFIED = '$@';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns a space-qualified address string.
|
|
30
|
+
* Format: `v:1^spaceId:<spaceId>^<ibGibAddr>`
|
|
31
|
+
*/
|
|
32
|
+
export function getSpaceQualifiedIbGibAddr(
|
|
33
|
+
optsOrSpaceId: { spaceId: string; ibGibAddr: string } | string,
|
|
34
|
+
rawIbGibAddr?: string,
|
|
35
|
+
): SpaceQualifiedIbGibAddr {
|
|
36
|
+
if (typeof optsOrSpaceId === 'object' && optsOrSpaceId !== null) {
|
|
37
|
+
return `v:1^spaceId:${optsOrSpaceId.spaceId}^${optsOrSpaceId.ibGibAddr}`;
|
|
38
|
+
}
|
|
39
|
+
return `v:1^spaceId:${optsOrSpaceId}^${rawIbGibAddr}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Parses a space-qualified address string into version, spaceId, ibGibAddr, ib, and gib.
|
|
44
|
+
*/
|
|
45
|
+
export function parseSpaceQualifiedIbGibAddr(
|
|
46
|
+
optsOrSqAddr: { spaceQualifiedAddr: string } | { sqAddr: string } | string,
|
|
47
|
+
): { version: number; spaceId: string; ibGibAddr: string; ib: string; gib: string } | null {
|
|
48
|
+
let sqAddr: string | undefined;
|
|
49
|
+
if (typeof optsOrSqAddr === 'string') {
|
|
50
|
+
sqAddr = optsOrSqAddr;
|
|
51
|
+
} else if (typeof optsOrSqAddr === 'object' && optsOrSqAddr !== null) {
|
|
52
|
+
sqAddr = (optsOrSqAddr as any).spaceQualifiedAddr || (optsOrSqAddr as any).sqAddr;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!sqAddr || typeof sqAddr !== 'string') {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const match = sqAddr.match(/^v:(\d+)\^spaceId:([^\^]+)\^(.+)$/);
|
|
60
|
+
if (!match) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const version = parseInt(match[1], 10);
|
|
65
|
+
const spaceId = match[2];
|
|
66
|
+
const ibGibAddr = match[3];
|
|
67
|
+
|
|
68
|
+
const lastCaretIndex = ibGibAddr.lastIndexOf('^');
|
|
69
|
+
if (lastCaretIndex === -1) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const ib = ibGibAddr.substring(0, lastCaretIndex);
|
|
74
|
+
const gib = ibGibAddr.substring(lastCaretIndex + 1);
|
|
75
|
+
|
|
76
|
+
if (!ib || !gib) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
version,
|
|
82
|
+
spaceId,
|
|
83
|
+
ibGibAddr,
|
|
84
|
+
ib,
|
|
85
|
+
gib,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Helper to extract branch name from space-qualified address or raw atom ib string.
|
|
91
|
+
*/
|
|
92
|
+
export function extractBranchNameFromAddr(addr: string): string | null {
|
|
93
|
+
if (!addr) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
const sq = parseSpaceQualifiedIbGibAddr(addr);
|
|
97
|
+
const ib = sq ? sq.ib : (addr.includes('^') ? addr.substring(0, addr.lastIndexOf('^')) : addr);
|
|
98
|
+
if (ib && ib.startsWith('b2tfs_branch ')) {
|
|
99
|
+
const parts = ib.split(' ');
|
|
100
|
+
if (parts.length >= 2 && parts[1]) {
|
|
101
|
+
return parts[1];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Deduplicates branch entries by branch name and merges new branch addresses into existing addresses
|
|
109
|
+
* without dropping other registered branches.
|
|
110
|
+
*/
|
|
111
|
+
export function mergeBranchAddrs(
|
|
112
|
+
existingAddrs: string[] = [],
|
|
113
|
+
newAddrs: string[] = [],
|
|
114
|
+
): string[] {
|
|
115
|
+
const map = new Map<string, string>();
|
|
116
|
+
for (const addr of existingAddrs) {
|
|
117
|
+
if (!addr) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const bName = extractBranchNameFromAddr(addr) || addr;
|
|
121
|
+
map.set(bName, addr);
|
|
122
|
+
}
|
|
123
|
+
for (const addr of newAddrs) {
|
|
124
|
+
if (!addr) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const bName = extractBranchNameFromAddr(addr) || addr;
|
|
128
|
+
map.set(bName, addr);
|
|
129
|
+
}
|
|
130
|
+
return Array.from(map.values());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Creates a new B2tFSIndexIbGib special meta object for a space.
|
|
135
|
+
*/
|
|
136
|
+
export async function createB2tFSIndexIbGib({
|
|
137
|
+
spaceId,
|
|
138
|
+
activeSpaceId,
|
|
139
|
+
activeBranch,
|
|
140
|
+
space,
|
|
141
|
+
metaspace,
|
|
142
|
+
branchAddr,
|
|
143
|
+
}: {
|
|
144
|
+
spaceId: string;
|
|
145
|
+
activeSpaceId: string;
|
|
146
|
+
activeBranch?: string;
|
|
147
|
+
space: IbGibSpaceAny;
|
|
148
|
+
metaspace: MetaspaceService;
|
|
149
|
+
branchAddr?: string;
|
|
150
|
+
}): Promise<B2tFSIndexIbGib_V1> {
|
|
151
|
+
const lc = `${lcFile}[${createB2tFSIndexIbGib.name}]`;
|
|
152
|
+
try {
|
|
153
|
+
if (logalot) {
|
|
154
|
+
console.log(`${lc} starting... (I: 3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d)`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const uuid = await getUUID();
|
|
158
|
+
const data: B2tFSIndexData_V1 = {
|
|
159
|
+
mySpaceId: spaceId,
|
|
160
|
+
activeSpaceId,
|
|
161
|
+
activeBranch,
|
|
162
|
+
uuid,
|
|
163
|
+
classname: 'B2tFSIndexIbGib_V1',
|
|
164
|
+
'$@branch': [],
|
|
165
|
+
stagedPaths: {},
|
|
166
|
+
staged_item: [],
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const rel8ns: B2tFSIndexRel8ns_V1 = {};
|
|
170
|
+
if (branchAddr) {
|
|
171
|
+
const sqBranchAddr = branchAddr.startsWith('v:1^spaceId:')
|
|
172
|
+
? branchAddr
|
|
173
|
+
: getSpaceQualifiedIbGibAddr({
|
|
174
|
+
spaceId: space.data?.spaceSubPath || space.data?.name || spaceId,
|
|
175
|
+
ibGibAddr: branchAddr,
|
|
176
|
+
});
|
|
177
|
+
rel8ns.branch = [sqBranchAddr];
|
|
178
|
+
rel8ns.branch_tjp = [sqBranchAddr];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const res = await Factory_V1.firstGen({
|
|
182
|
+
parentIbGib: ROOT,
|
|
183
|
+
ib: `meta special b2tfs_index ${uuid}`,
|
|
184
|
+
data,
|
|
185
|
+
rel8ns: Object.keys(rel8ns).length > 0 ? rel8ns : undefined,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const indexIbGib = res.newIbGib as B2tFSIndexIbGib_V1;
|
|
189
|
+
await persistTransformResult({ resTransform: res, space });
|
|
190
|
+
await metaspace.registerNewIbGib({ ibGib: indexIbGib });
|
|
191
|
+
|
|
192
|
+
if (logalot) {
|
|
193
|
+
console.log(`${lc} Created index IbGib: ${indexIbGib.ib} (I: 4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e)`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return indexIbGib;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error(`${lc} ${extractErrorMsg(error)} (E: 5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f)`);
|
|
199
|
+
throw error;
|
|
200
|
+
} finally {
|
|
201
|
+
if (logalot) {
|
|
202
|
+
console.log(`${lc} complete. (I: 6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a)`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Retrieves authoritative B2tFSIndexIbGib_V1 from space.
|
|
209
|
+
*/
|
|
210
|
+
export async function getB2tFSIndexIbGib({
|
|
211
|
+
space,
|
|
212
|
+
vcsPath,
|
|
213
|
+
}: {
|
|
214
|
+
space: IbGibSpaceAny;
|
|
215
|
+
vcsPath?: string;
|
|
216
|
+
}): Promise<B2tFSIndexIbGib_V1 | undefined> {
|
|
217
|
+
const lc = `${lcFile}[${getB2tFSIndexIbGib.name}]`;
|
|
218
|
+
try {
|
|
219
|
+
if (logalot) {
|
|
220
|
+
console.log(`${lc} starting... (I: 7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b)`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (!vcsPath) {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const projPath = path.join(vcsPath, 'vcs_index_projection.json');
|
|
228
|
+
let indexAddr: string | undefined;
|
|
229
|
+
try {
|
|
230
|
+
const raw = await fs.readFile(projPath, 'utf8');
|
|
231
|
+
const parsed = JSON.parse(raw);
|
|
232
|
+
indexAddr = parsed.indexAddr;
|
|
233
|
+
} catch {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (!indexAddr) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const ibgibs = await getIbGibsFromCache_fallbackToSpaces({
|
|
242
|
+
addrs: [indexAddr],
|
|
243
|
+
space,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const indexIbGib = ibgibs?.at(0) as B2tFSIndexIbGib_V1;
|
|
247
|
+
return indexIbGib;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.error(`${lc} ${extractErrorMsg(error)} (E: 8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c)`);
|
|
250
|
+
throw error;
|
|
251
|
+
} finally {
|
|
252
|
+
if (logalot) {
|
|
253
|
+
console.log(`${lc} complete. (I: 9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d)`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Updates B2tFSIndexIbGib_V1 in space and updates local projection cache.
|
|
260
|
+
*/
|
|
261
|
+
export async function updateB2tFSIndexIbGib({
|
|
262
|
+
space,
|
|
263
|
+
metaspace,
|
|
264
|
+
indexIbGib,
|
|
265
|
+
dataToUpdate,
|
|
266
|
+
rel8nsToUpdate,
|
|
267
|
+
vcsPath,
|
|
268
|
+
}: {
|
|
269
|
+
space: IbGibSpaceAny;
|
|
270
|
+
metaspace: MetaspaceService;
|
|
271
|
+
indexIbGib: B2tFSIndexIbGib_V1;
|
|
272
|
+
dataToUpdate?: Partial<B2tFSIndexData_V1>;
|
|
273
|
+
rel8nsToUpdate?: Partial<B2tFSIndexRel8ns_V1>;
|
|
274
|
+
vcsPath?: string;
|
|
275
|
+
}): Promise<B2tFSIndexIbGib_V1> {
|
|
276
|
+
const lc = `${lcFile}[${updateB2tFSIndexIbGib.name}]`;
|
|
277
|
+
try {
|
|
278
|
+
if (logalot) {
|
|
279
|
+
console.log(`${lc} starting... (I: 0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e)`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const mergedData: B2tFSIndexData_V1 = {
|
|
283
|
+
...(indexIbGib.data || {
|
|
284
|
+
mySpaceId: space.data?.uuid || '',
|
|
285
|
+
activeSpaceId: '',
|
|
286
|
+
uuid: await getUUID(),
|
|
287
|
+
}),
|
|
288
|
+
...dataToUpdate,
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const mergedRel8ns: B2tFSIndexRel8ns_V1 = {
|
|
292
|
+
...(indexIbGib.rel8ns || {}),
|
|
293
|
+
...rel8nsToUpdate,
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
if (rel8nsToUpdate?.branch || indexIbGib.rel8ns?.branch) {
|
|
297
|
+
mergedRel8ns.branch = mergeBranchAddrs(
|
|
298
|
+
indexIbGib.rel8ns?.branch || [],
|
|
299
|
+
rel8nsToUpdate?.branch || [],
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (rel8nsToUpdate?.branch_tjp || indexIbGib.rel8ns?.branch_tjp) {
|
|
304
|
+
mergedRel8ns.branch_tjp = mergeBranchAddrs(
|
|
305
|
+
indexIbGib.rel8ns?.branch_tjp || [],
|
|
306
|
+
rel8nsToUpdate?.branch_tjp || [],
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
delete mergedRel8ns.past;
|
|
311
|
+
|
|
312
|
+
const res = await Factory_V1.firstGen({
|
|
313
|
+
parentIbGib: ROOT,
|
|
314
|
+
ib: indexIbGib.ib,
|
|
315
|
+
data: mergedData,
|
|
316
|
+
rel8ns: mergedRel8ns,
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const newIndexIbGib = res.newIbGib as B2tFSIndexIbGib_V1;
|
|
320
|
+
await persistTransformResult({ resTransform: res, space });
|
|
321
|
+
await metaspace.registerNewIbGib({ ibGib: newIndexIbGib });
|
|
322
|
+
|
|
323
|
+
if (vcsPath) {
|
|
324
|
+
await writeVcsIndexProjection({ vcsPath, indexIbGib: newIndexIbGib });
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return newIndexIbGib;
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error(`${lc} ${extractErrorMsg(error)} (E: 1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f)`);
|
|
330
|
+
throw error;
|
|
331
|
+
} finally {
|
|
332
|
+
if (logalot) {
|
|
333
|
+
console.log(`${lc} complete. (I: 2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a)`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Writes read-only JSON projection cache of repository index.
|
|
340
|
+
*/
|
|
341
|
+
export async function writeVcsIndexProjection({
|
|
342
|
+
vcsPath,
|
|
343
|
+
indexIbGib,
|
|
344
|
+
}: {
|
|
345
|
+
vcsPath: string;
|
|
346
|
+
indexIbGib: B2tFSIndexIbGib_V1;
|
|
347
|
+
}): Promise<void> {
|
|
348
|
+
const lc = `${lcFile}[${writeVcsIndexProjection.name}]`;
|
|
349
|
+
try {
|
|
350
|
+
if (logalot) {
|
|
351
|
+
console.log(`${lc} starting... (I: 3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b)`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
await fs.mkdir(vcsPath, { recursive: true });
|
|
355
|
+
|
|
356
|
+
const indexAddr = getIbGibAddr({ ibGib: indexIbGib });
|
|
357
|
+
const projectionObj = {
|
|
358
|
+
_isReadOnlyProjection: true,
|
|
359
|
+
_comment: 'STRICTLY READ-ONLY PROJECTION GENERATED FROM B2TFSINDEXIBGIB_V1 IN LOCALSPACE',
|
|
360
|
+
indexAddr,
|
|
361
|
+
spaceId: indexIbGib.data?.mySpaceId,
|
|
362
|
+
activeBranch: indexIbGib.data?.activeBranch || 'main',
|
|
363
|
+
stagedCount: (indexIbGib.data?.staged_item || []).length,
|
|
364
|
+
stagedPaths: indexIbGib.data?.stagedPaths || {},
|
|
365
|
+
updatedAt: new Date().toISOString(),
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const projFile = path.join(vcsPath, 'vcs_index_projection.json');
|
|
369
|
+
await fs.writeFile(projFile, JSON.stringify(projectionObj, null, 2), 'utf8');
|
|
370
|
+
} catch (error) {
|
|
371
|
+
console.error(`${lc} ${extractErrorMsg(error)} (E: 4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c)`);
|
|
372
|
+
throw error;
|
|
373
|
+
} finally {
|
|
374
|
+
if (logalot) {
|
|
375
|
+
console.log(`${lc} complete. (I: 5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d)`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module index-types
|
|
3
|
+
*
|
|
4
|
+
* Space-qualified address and B2tFS index type definitions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
|
|
8
|
+
import { IbGibData_V1, IbGibRel8ns_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Format: v:1^spaceId:<spaceId>^<ibGibAddr>
|
|
12
|
+
*/
|
|
13
|
+
export type SpaceQualifiedIbGibAddr = string;
|
|
14
|
+
|
|
15
|
+
export interface B2tFSStagedItemRecord {
|
|
16
|
+
itemAddr: string;
|
|
17
|
+
binAddr?: string;
|
|
18
|
+
fileHash?: string;
|
|
19
|
+
fsType: 'file' | 'folder';
|
|
20
|
+
stagedAt: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface B2tFSIndexData_V1 extends IbGibData_V1 {
|
|
24
|
+
/**
|
|
25
|
+
* Space UUID containing this index
|
|
26
|
+
*/
|
|
27
|
+
mySpaceId: string;
|
|
28
|
+
/**
|
|
29
|
+
* Currently active branch space UUID
|
|
30
|
+
*/
|
|
31
|
+
activeSpaceId: string;
|
|
32
|
+
/**
|
|
33
|
+
* Active branch name (e.g. 'main')
|
|
34
|
+
*/
|
|
35
|
+
activeBranch?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Space UUID from which this space forked
|
|
38
|
+
*/
|
|
39
|
+
ancestorSpaceId?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Soft references to branch TJPs: $@branch = [SpaceQualifiedIbGibAddr, ...]
|
|
42
|
+
*/
|
|
43
|
+
'$@branch'?: SpaceQualifiedIbGibAddr[];
|
|
44
|
+
/**
|
|
45
|
+
* Staged paths lookup table
|
|
46
|
+
*/
|
|
47
|
+
stagedPaths?: { [relPath: string]: B2tFSStagedItemRecord };
|
|
48
|
+
/**
|
|
49
|
+
* Staged candidate item addresses
|
|
50
|
+
*/
|
|
51
|
+
staged_item?: IbGibAddr[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface B2tFSIndexRel8ns_V1 extends IbGibRel8ns_V1 {
|
|
55
|
+
/**
|
|
56
|
+
* Local branch TJP address for this space
|
|
57
|
+
*/
|
|
58
|
+
branch_tjp?: IbGibAddr[];
|
|
59
|
+
/**
|
|
60
|
+
* Active or registered branch IbGib addresses
|
|
61
|
+
*/
|
|
62
|
+
branch?: IbGibAddr[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface B2tFSIndexIbGib_V1 extends IbGib_V1<B2tFSIndexData_V1, B2tFSIndexRel8ns_V1> {
|
|
66
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module item-atom-helper
|
|
3
|
+
*
|
|
4
|
+
* Helper functions enforcing canonical space-delimited `ib` atom formulas.
|
|
5
|
+
*
|
|
6
|
+
* Formula: `[atom] [fsType] [saferName] [saferNameVersion] [nameHash]`
|
|
7
|
+
* Example: `b2tfs_item file index_mts v1 a745323851634de188beaebdcb85cbb9`
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const B2TFS_ITEM_ATOM = 'b2tfs_item';
|
|
11
|
+
export const B2TFS_ITEM_SAFER_NAME_VERSION_V1 = 'v1';
|
|
12
|
+
|
|
13
|
+
export function getB2tFSItemSaferName(rawName: string): string {
|
|
14
|
+
if (!rawName) { return 'unnamed'; }
|
|
15
|
+
// Clean to alphanumeric and underscores/dashes/dots
|
|
16
|
+
const safe = rawName.replace(/[^a-zA-Z0-9_\-\.]/g, '_');
|
|
17
|
+
return safe.slice(0, 32);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns canonical `ib` metadata string for a B2tFS item.
|
|
22
|
+
*
|
|
23
|
+
* @param fsType 'file' or 'folder'
|
|
24
|
+
* @param name raw file/folder name
|
|
25
|
+
* @param nameHash SHA-256 hash of name
|
|
26
|
+
*/
|
|
27
|
+
export function getB2tFSItemIb(fsType: 'file' | 'folder', name: string, nameHash: string): string {
|
|
28
|
+
const saferName = getB2tFSItemSaferName(name);
|
|
29
|
+
return `${B2TFS_ITEM_ATOM} ${fsType} ${saferName} ${B2TFS_ITEM_SAFER_NAME_VERSION_V1} ${nameHash}`;
|
|
30
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module item-helper
|
|
3
|
+
*
|
|
4
|
+
* B2tFS Item Helper functions: graph diff generation, filesystem projection materialization,
|
|
5
|
+
* and two-pass transform application.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
|
|
11
|
+
import { MetaspaceService } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs';
|
|
12
|
+
import { IbGibSpaceAny } from '@ibgib/core-gib/dist/witness/space/space-base-v1.mjs';
|
|
13
|
+
import { getIbGibsFromCache_fallbackToSpaces } from '@ibgib/core-gib/dist/common/other/ibgib-helper.mjs';
|
|
14
|
+
import { putInSpace, persistTransformResult, getFromSpace } from '@ibgib/core-gib/dist/witness/space/space-helper.mjs';
|
|
15
|
+
|
|
16
|
+
import { parseSpaceQualifiedIbGibAddr } from '../index/index-helper.mjs';
|
|
17
|
+
import { GLOBAL_LOG_A_LOT } from '../../vcs-gib-constants.mjs';
|
|
18
|
+
import {
|
|
19
|
+
B2tFSItemIbGib_V1, B2TFS_CHILD_ITEM_REL8N_NAME, BINARY_REL8N_NAME, B2tFSItemDiffInfo
|
|
20
|
+
} from './item-types.mjs';
|
|
21
|
+
|
|
22
|
+
const lcFile = `[item-helper]`;
|
|
23
|
+
const logalot = GLOBAL_LOG_A_LOT;
|
|
24
|
+
|
|
25
|
+
function getSpacesArray(metaAny: any): IbGibSpaceAny[] {
|
|
26
|
+
if (!metaAny || !metaAny.spaces) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
if (metaAny.spaces instanceof Map) {
|
|
30
|
+
return Array.from(metaAny.spaces.values());
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(metaAny.spaces)) {
|
|
33
|
+
return metaAny.spaces;
|
|
34
|
+
}
|
|
35
|
+
if (typeof metaAny.spaces === 'object') {
|
|
36
|
+
return Object.values(metaAny.spaces);
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function fetchFromSpaceSilently(spaceToQuery: IbGibSpaceAny, addrToGet: string): Promise<any> {
|
|
42
|
+
try {
|
|
43
|
+
const resGet = await getFromSpace({ space: spaceToQuery, addrs: [addrToGet] });
|
|
44
|
+
if (resGet && resGet.success && resGet.ibGibs && resGet.ibGibs.length > 0) {
|
|
45
|
+
return resGet.ibGibs[0];
|
|
46
|
+
}
|
|
47
|
+
} catch {
|
|
48
|
+
// Suppress missing address error
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Retrieves an ibgib node by address, searching space first, then falling back to metaspace spaces if available.
|
|
55
|
+
*/
|
|
56
|
+
export async function getIbGibWithMetaspaceFallback({
|
|
57
|
+
addr,
|
|
58
|
+
space,
|
|
59
|
+
metaspace,
|
|
60
|
+
}: {
|
|
61
|
+
addr: string;
|
|
62
|
+
space: IbGibSpaceAny;
|
|
63
|
+
metaspace?: MetaspaceService;
|
|
64
|
+
}): Promise<any> {
|
|
65
|
+
const parsedSq = parseSpaceQualifiedIbGibAddr(addr);
|
|
66
|
+
const targetAddr = parsedSq ? parsedSq.ibGibAddr : addr;
|
|
67
|
+
|
|
68
|
+
if (parsedSq && metaspace) {
|
|
69
|
+
try {
|
|
70
|
+
const spaceList = (await metaspace.getLocalUserSpaces({ lock: false })) || [];
|
|
71
|
+
let targetSpace = spaceList.find(s =>
|
|
72
|
+
s?.data?.uuid === parsedSq.spaceId ||
|
|
73
|
+
s?.data?.spaceId === parsedSq.spaceId ||
|
|
74
|
+
s?.data?.name === parsedSq.spaceId ||
|
|
75
|
+
s?.ib === parsedSq.spaceId ||
|
|
76
|
+
s?.data?.spaceSubPath === parsedSq.spaceId
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
if (!targetSpace) {
|
|
80
|
+
try {
|
|
81
|
+
targetSpace = await metaspace.getLocalUserSpace({ localSpaceId: parsedSq.spaceId, lock: false });
|
|
82
|
+
} catch {
|
|
83
|
+
// Suppress lookup error
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (targetSpace) {
|
|
88
|
+
const found = await fetchFromSpaceSilently(targetSpace, targetAddr);
|
|
89
|
+
if (found) {
|
|
90
|
+
return found;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch {
|
|
94
|
+
// Suppress space lookup errors
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const primaryFound = await fetchFromSpaceSilently(space, targetAddr);
|
|
99
|
+
if (primaryFound) {
|
|
100
|
+
return primaryFound;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (metaspace) {
|
|
104
|
+
let spaceList: IbGibSpaceAny[] = [];
|
|
105
|
+
try {
|
|
106
|
+
spaceList = (await metaspace.getLocalUserSpaces({ lock: false })) || [];
|
|
107
|
+
} catch {
|
|
108
|
+
// Ignore bootstrap lookup error
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const metaAny = metaspace as any;
|
|
112
|
+
|
|
113
|
+
// Try zero space if distinct
|
|
114
|
+
if (metaspace.zeroSpace && metaspace.zeroSpace !== space) {
|
|
115
|
+
const zeroFound = await fetchFromSpaceSilently(metaspace.zeroSpace, targetAddr);
|
|
116
|
+
if (zeroFound) {
|
|
117
|
+
return zeroFound;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (metaAny.activeSpace && metaAny.activeSpace !== space && metaAny.activeSpace !== metaspace.zeroSpace) {
|
|
122
|
+
const activeFound = await fetchFromSpaceSilently(metaAny.activeSpace, targetAddr);
|
|
123
|
+
if (activeFound) {
|
|
124
|
+
return activeFound;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for (const s of spaceList) {
|
|
129
|
+
if (s && s !== space && s !== metaAny.activeSpace && s !== metaspace.zeroSpace) {
|
|
130
|
+
const sFound = await fetchFromSpaceSilently(s, targetAddr);
|
|
131
|
+
if (sFound) {
|
|
132
|
+
return sFound;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Projects a B2tFS item graph back onto the physical filesystem directory.
|
|
143
|
+
*/
|
|
144
|
+
export async function writeB2tFSItemToFS(opts: {
|
|
145
|
+
item: B2tFSItemIbGib_V1;
|
|
146
|
+
destPath: string;
|
|
147
|
+
space: IbGibSpaceAny;
|
|
148
|
+
metaspace: MetaspaceService;
|
|
149
|
+
}): Promise<void> {
|
|
150
|
+
const lc = `${lcFile}[${writeB2tFSItemToFS.name}]`;
|
|
151
|
+
const { item, destPath, space, metaspace } = opts;
|
|
152
|
+
|
|
153
|
+
if (!item || !item.data) {
|
|
154
|
+
throw new Error(`Invalid B2tFS item provided (E: 32a09c81b29e4d58)`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const { fsType, name } = item.data;
|
|
158
|
+
const targetPath = path.join(destPath, name);
|
|
159
|
+
|
|
160
|
+
if (fsType === 'folder') {
|
|
161
|
+
await fs.mkdir(targetPath, { recursive: true });
|
|
162
|
+
const childAddrs = item.rel8ns?.[B2TFS_CHILD_ITEM_REL8N_NAME] || [];
|
|
163
|
+
|
|
164
|
+
for (const childAddr of childAddrs) {
|
|
165
|
+
const childItem = await getIbGibWithMetaspaceFallback({
|
|
166
|
+
addr: childAddr,
|
|
167
|
+
space,
|
|
168
|
+
metaspace,
|
|
169
|
+
}) as B2tFSItemIbGib_V1;
|
|
170
|
+
|
|
171
|
+
if (childItem) {
|
|
172
|
+
await writeB2tFSItemToFS({
|
|
173
|
+
item: childItem,
|
|
174
|
+
destPath: targetPath,
|
|
175
|
+
space,
|
|
176
|
+
metaspace,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} else if (fsType === 'file') {
|
|
181
|
+
const binAddrs = item.rel8ns?.[BINARY_REL8N_NAME] || [];
|
|
182
|
+
const latestBinAddr = binAddrs.at(-1);
|
|
183
|
+
|
|
184
|
+
if (latestBinAddr) {
|
|
185
|
+
const binIbGib = await getIbGibWithMetaspaceFallback({
|
|
186
|
+
addr: latestBinAddr,
|
|
187
|
+
space,
|
|
188
|
+
metaspace,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
if (binIbGib && binIbGib.data) {
|
|
192
|
+
let fileData: Uint8Array;
|
|
193
|
+
if (typeof binIbGib.data === 'string') {
|
|
194
|
+
fileData = Buffer.from(binIbGib.data, 'base64');
|
|
195
|
+
} else if (binIbGib.data instanceof Uint8Array || Buffer.isBuffer(binIbGib.data)) {
|
|
196
|
+
fileData = binIbGib.data as Uint8Array;
|
|
197
|
+
} else if (typeof binIbGib.data === 'object') {
|
|
198
|
+
const vals = Object.values(binIbGib.data as object);
|
|
199
|
+
fileData = new Uint8Array(vals);
|
|
200
|
+
} else {
|
|
201
|
+
fileData = new Uint8Array(0);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
await fs.writeFile(targetPath, fileData);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Executes two-pass application of diff transform results:
|
|
212
|
+
* 1. Persists all child and parent transform results to space.
|
|
213
|
+
* 2. Registers new IbGib pointers with metaspace to advance timeline tips.
|
|
214
|
+
*/
|
|
215
|
+
export async function applyB2tFSItemDiff(opts: {
|
|
216
|
+
diff: B2tFSItemDiffInfo;
|
|
217
|
+
space: IbGibSpaceAny;
|
|
218
|
+
metaspace: MetaspaceService;
|
|
219
|
+
}): Promise<void> {
|
|
220
|
+
const lc = `${lcFile}[${applyB2tFSItemDiff.name}]`;
|
|
221
|
+
const { diff, space, metaspace } = opts;
|
|
222
|
+
|
|
223
|
+
if (diff.childDiffs && diff.childDiffs.length > 0) {
|
|
224
|
+
for (const childDiff of diff.childDiffs) {
|
|
225
|
+
await applyB2tFSItemDiff({ diff: childDiff, space, metaspace });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const results = diff.transformResults || [];
|
|
230
|
+
for (const tr of results) {
|
|
231
|
+
await persistTransformResult({ resTransform: tr, space });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
for (const tr of results) {
|
|
235
|
+
if (tr.newIbGib) {
|
|
236
|
+
await metaspace.registerNewIbGib({ ibGib: tr.newIbGib });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|