nano-git 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/core/types.d.mts +1 -1
  3. package/dist/objects/tree.d.mts +4 -0
  4. package/dist/objects/tree.mjs +53 -2
  5. package/dist/repository/tree/tree-patch.mjs +4 -4
  6. package/dist/repository/tree/tree-walk.mjs +1 -1
  7. package/dist/repository/tree/tree-writer.mjs +1 -1
  8. package/dist/workdir/change-index-plan.mjs +2 -2
  9. package/dist/workdir/change-index.mjs +6 -6
  10. package/dist/workdir/core.d.mts +13 -44
  11. package/dist/workdir/directory-view.mjs +2 -2
  12. package/dist/workdir/dirty-dir-plan.mjs +3 -3
  13. package/dist/workdir/file-backend.d.mts +34 -12
  14. package/dist/workdir/file-backend.mjs +67 -86
  15. package/dist/workdir/file.d.mts +2 -2
  16. package/dist/workdir/file.mjs +2 -2
  17. package/dist/workdir/ids.d.mts +1 -1
  18. package/dist/workdir/ids.mjs +3 -3
  19. package/dist/workdir/memory-backend.mjs +4 -39
  20. package/dist/workdir/memory.d.mts +2 -3
  21. package/dist/workdir/memory.mjs +2 -3
  22. package/dist/workdir/nodes.d.mts +7 -7
  23. package/dist/workdir/nodes.mjs +3 -3
  24. package/dist/workdir/origin.mjs +2 -2
  25. package/dist/workdir/overlay.d.mts +3 -3
  26. package/dist/workdir/sqlite-backend.d.mts +31 -14
  27. package/dist/workdir/sqlite-backend.mjs +113 -118
  28. package/dist/workdir/sqlite.d.mts +2 -2
  29. package/dist/workdir/sqlite.mjs +2 -2
  30. package/dist/workdir/state-store.d.mts +4 -4
  31. package/dist/workdir/{session-internal.mjs → workdir-path.mjs} +10 -10
  32. package/dist/workdir/{session-transaction.mjs → workdir-transaction.mjs} +10 -10
  33. package/dist/workdir/workdir.d.mts +30 -0
  34. package/dist/workdir/{session.mjs → workdir.mjs} +17 -17
  35. package/dist/workdir/write-tree.mjs +5 -5
  36. package/package.json +1 -1
  37. package/dist/workdir/memory-backend.d.mts +0 -17
  38. package/dist/workdir/session-id.mjs +0 -18
  39. package/dist/workdir/session.d.mts +0 -30
package/README.md CHANGED
@@ -381,7 +381,7 @@ Git 使用内容寻址文件系统,所有对象通过 SHA-1 哈希寻址:
381
381
 
382
382
  存储目录内容,每个条目包含:
383
383
 
384
- - 文件模式(如 `100644` 普通文件,`100755` 可执行文件,`040000` 目录)
384
+ - 文件模式(如 `100644` 普通文件,`100755` 可执行文件,`040000` 目录,API 中均使用规范 6 位形式)
385
385
  - 文件名
386
386
  - 指向 blob 或子 tree 的哈希
387
387
 
@@ -48,7 +48,7 @@ interface GitBlob {
48
48
  }
49
49
  /** Tree 条目 — 目录中的一个文件或子目录 */
50
50
  interface TreeEntry {
51
- /** 文件模式(如 "100644" 普通文件, "100755" 可执行文件, "40000" 目录) */
51
+ /** 文件模式(如 "100644" 普通文件, "100755" 可执行文件, "040000" 目录) */
52
52
  mode: string;
53
53
  /** 文件/目录名 */
54
54
  name: string;
@@ -4,6 +4,8 @@ import { GitTree } from "../core/types.mjs";
4
4
  /**
5
5
  * 序列化 Tree 对象
6
6
  *
7
+ * 写入时自动将规范 mode 转换为磁盘格式(如 "040000" → "40000")。
8
+ *
7
9
  * @example
8
10
  * ```ts
9
11
  * const tree: GitTree = {
@@ -16,6 +18,8 @@ import { GitTree } from "../core/types.mjs";
16
18
  declare function serializeTree(tree: GitTree): Buffer;
17
19
  /**
18
20
  * 反序列化 Tree 对象
21
+ *
22
+ * 读取时自动将磁盘 mode 转换为规范形式(如 "40000" → "040000")。
19
23
  */
20
24
  declare function deserializeTree(content: Buffer): GitTree;
21
25
  //#endregion
@@ -9,10 +9,58 @@ import { sha1 } from "../core/types.mjs";
9
9
  * - mode: 文件模式(如 "100644")
10
10
  * - name: 文件名
11
11
  * - hash: 20 字节的原始 SHA-1(不是十六进制字符串)
12
+ *
13
+ * mode 规范化说明:
14
+ * Git CLI 显示目录 mode 为 "040000"(6 位八进制,前导补零),但磁盘上存储为 "40000"(5 字节)。
15
+ * 本模块在序列化/反序列化边界做双向转换,内部统一使用规范形式("040000")。
16
+ */
17
+ /**
18
+ * 目录 mode 的磁盘格式(无前导零,5 字节)
12
19
  */
20
+ const DIR_MODE_ON_DISK = "40000";
21
+ /**
22
+ * 目录 mode 的规范格式(有前导零,6 字节,与 git cat-file -p 显示一致)
23
+ */
24
+ const DIR_MODE_CANONICAL = "040000";
25
+ /**
26
+ * 将 mode 转换为规范形式(6 位八进制)
27
+ *
28
+ * 读取磁盘 tree 条目时调用:将 "40000" → "040000",其他 mode 不变。
29
+ *
30
+ * @param mode - 来自磁盘的 mode 字符串
31
+ * @returns 规范化的 mode 字符串
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * toCanonicalMode("40000") // => "040000"
36
+ * toCanonicalMode("100644") // => "100644"
37
+ * ```
38
+ */
39
+ function toCanonicalMode(mode) {
40
+ return mode === DIR_MODE_ON_DISK ? DIR_MODE_CANONICAL : mode;
41
+ }
42
+ /**
43
+ * 将 mode 转换为磁盘格式(无多余前导零)
44
+ *
45
+ * 写入磁盘 tree 条目时调用:将 "040000" → "40000",其他 mode 不变。
46
+ *
47
+ * @param mode - 规范形式的 mode 字符串
48
+ * @returns 磁盘形式的 mode 字符串
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * toOnDiskMode("040000") // => "40000"
53
+ * toOnDiskMode("100644") // => "100644"
54
+ * ```
55
+ */
56
+ function toOnDiskMode(mode) {
57
+ return mode === DIR_MODE_CANONICAL ? DIR_MODE_ON_DISK : mode;
58
+ }
13
59
  /**
14
60
  * 序列化 Tree 对象
15
61
  *
62
+ * 写入时自动将规范 mode 转换为磁盘格式(如 "040000" → "40000")。
63
+ *
16
64
  * @example
17
65
  * ```ts
18
66
  * const tree: GitTree = {
@@ -25,7 +73,8 @@ import { sha1 } from "../core/types.mjs";
25
73
  function serializeTree(tree) {
26
74
  const buffers = [];
27
75
  for (const entry of tree.entries) {
28
- const entryHeader = Buffer.from(`${entry.mode} ${entry.name}\0`, "utf-8");
76
+ const mode = toOnDiskMode(entry.mode);
77
+ const entryHeader = Buffer.from(`${mode} ${entry.name}\0`, "utf-8");
29
78
  const entryHash = Buffer.from(entry.hash, "hex");
30
79
  if (entryHash.length !== 20) throw new InvalidObjectError(`invalid SHA-1 hash length: ${entryHash.length}`);
31
80
  buffers.push(entryHeader, entryHash);
@@ -34,6 +83,8 @@ function serializeTree(tree) {
34
83
  }
35
84
  /**
36
85
  * 反序列化 Tree 对象
86
+ *
87
+ * 读取时自动将磁盘 mode 转换为规范形式(如 "40000" → "040000")。
37
88
  */
38
89
  function deserializeTree(content) {
39
90
  const entries = [];
@@ -51,7 +102,7 @@ function deserializeTree(content) {
51
102
  if (hashEnd > content.length) throw new InvalidObjectError("tree: truncated hash");
52
103
  const hash = content.subarray(hashStart, hashEnd).toString("hex");
53
104
  entries.push({
54
- mode,
105
+ mode: toCanonicalMode(mode),
55
106
  name,
56
107
  hash: sha1(hash)
57
108
  });
@@ -98,7 +98,7 @@ function processOpsSequentially(objects, rootHash, ops) {
98
98
  * 在 tree 中查找路径对应的条目
99
99
  *
100
100
  * 沿路径依次读取 tree 对象,最后一段返回目标条目。
101
- * 中间段必须为目录(mode "40000"),否则抛出异常。
101
+ * 中间段必须为目录(mode "040000"),否则抛出异常。
102
102
  */
103
103
  function findEntryByPath(objects, treeHash, path) {
104
104
  const segments = path.split("/");
@@ -109,7 +109,7 @@ function findEntryByPath(objects, treeHash, path) {
109
109
  const entry = obj.entries.find((e) => e.name === segments[i]);
110
110
  if (!entry) return null;
111
111
  if (i === segments.length - 1) return entry;
112
- if (entry.mode !== "40000") throw new Error(`Cannot access '${segments.slice(0, i + 1).join("/")}': not a directory (mode: ${entry.mode})`);
112
+ if (entry.mode !== "040000") throw new Error(`Cannot access '${segments.slice(0, i + 1).join("/")}': not a directory (mode: ${entry.mode})`);
113
113
  currentHash = entry.hash;
114
114
  }
115
115
  return null;
@@ -174,7 +174,7 @@ function applyPatchRecursive(objects, treeHash, ops, prefix, upsertedPaths) {
174
174
  for (const [name, childOps] of deeperOps) {
175
175
  const existingEntry = existingEntries.find((e) => e.name === name);
176
176
  const existingHash = existingEntry?.hash ?? null;
177
- if (existingEntry !== void 0 && existingEntry.mode !== "40000") throw new Error(`Cannot access '${prefix}${name}': existing entry is not a directory (mode: ${existingEntry.mode})`);
177
+ if (existingEntry !== void 0 && existingEntry.mode !== "040000") throw new Error(`Cannot access '${prefix}${name}': existing entry is not a directory (mode: ${existingEntry.mode})`);
178
178
  if (existingHash === null) {
179
179
  const hasUpsertInBatch = childOps.some((op) => op.op === "upsert") || childOps.some((op) => op.op === "delete" && upsertedPaths.has(`${prefix}${name}/${op.path}`));
180
180
  if (childOps.every((op) => op.op === "delete") && !hasUpsertInBatch) {
@@ -185,7 +185,7 @@ function applyPatchRecursive(objects, treeHash, ops, prefix, upsertedPaths) {
185
185
  const result = applyPatchRecursive(objects, existingHash, childOps, `${prefix}${name}/`, upsertedPaths);
186
186
  writtenTrees.push(...result.written);
187
187
  finalEntryMap.set(name, {
188
- mode: "40000",
188
+ mode: "040000",
189
189
  name,
190
190
  hash: result.hash
191
191
  });
@@ -58,7 +58,7 @@ function walkTreeRecursive(objects, treeHash, prefix, result, visit) {
58
58
  };
59
59
  if (result) result.push(entryWithPath);
60
60
  if (visit) visit(entryWithPath);
61
- if (entry.mode === "40000") walkTreeRecursive(objects, entry.hash, path, result, visit);
61
+ if (entry.mode === "040000") walkTreeRecursive(objects, entry.hash, path, result, visit);
62
62
  }
63
63
  }
64
64
  //#endregion
@@ -31,7 +31,7 @@ function writeTreeRecursive(store, dirPath) {
31
31
  if (stat.isDirectory()) {
32
32
  const subtreeHash = writeTreeRecursive(store, fullPath);
33
33
  entries.push({
34
- mode: "40000",
34
+ mode: "040000",
35
35
  name,
36
36
  hash: subtreeHash
37
37
  });
@@ -1,9 +1,9 @@
1
- import { resolvePath } from "./session-internal.mjs";
1
+ import { resolvePath } from "./workdir-path.mjs";
2
2
  //#region src/workdir/change-index-plan.ts
3
3
  /**
4
4
  * Virtual Workdir change-index 刷新策略
5
5
  *
6
- * 把 session 写路径里的“是否允许增量刷新”判断与
6
+ * 把 workdir 写路径里的“是否允许增量刷新”判断与
7
7
  * “应该执行哪种 change-index 更新动作”集中到单独模块。
8
8
  */
9
9
  /**
@@ -1,6 +1,6 @@
1
1
  import { hashObject } from "../core/hash-digest.mjs";
2
2
  import { readRepoBlobContent, readRepoTree } from "./origin.mjs";
3
- import { getDirectoryChildrenView, joinChildPath, resolveCurrentLeafAtPath } from "./session-internal.mjs";
3
+ import { getDirectoryChildrenView, joinChildPath, resolveCurrentLeafAtPath } from "./workdir-path.mjs";
4
4
  import { observeListedDirectoryChild } from "./directory-view.mjs";
5
5
  //#region src/workdir/change-index.ts
6
6
  /**
@@ -15,7 +15,7 @@ import { observeListedDirectoryChild } from "./directory-view.mjs";
15
15
  */
16
16
  const baseSnapshotCache = /* @__PURE__ */ new WeakMap();
17
17
  /**
18
- * 重建当前 session 的规范化变更索引。
18
+ * 重建当前 workdir 的规范化变更索引。
19
19
  *
20
20
  * @example
21
21
  * ```ts
@@ -173,7 +173,7 @@ function rewriteChangeRecordForRename(source, state, from, to, cache) {
173
173
  * 为 copy 目标路径写入折叠后的变更记录。
174
174
  *
175
175
  * 仅适用于叶子节点 copy;
176
- * session-only 来源允许退化为普通 create。
176
+ * workdir-only 来源允许退化为普通 create。
177
177
  */
178
178
  function writeChangeRecordForCopy(source, state, from, to, cache) {
179
179
  const sourceRecord = state.getChangeRecord(from);
@@ -195,7 +195,7 @@ function snapshotBaseTree(source, treeHash, dirPath) {
195
195
  const out = [];
196
196
  for (const entry of tree.entries) {
197
197
  const path = joinChildPath(dirPath, entry.name);
198
- if (entry.mode === "40000") {
198
+ if (entry.mode === "040000") {
199
199
  out.push(...snapshotBaseTree(source, entry.hash, path));
200
200
  continue;
201
201
  }
@@ -218,7 +218,7 @@ function baseSnapshotViewForTree(source, treeHash) {
218
218
  }
219
219
  function snapshotCurrentTree(source, state, cache) {
220
220
  const root = state.getNode("root");
221
- if (root === null) throw new Error("Virtual workdir session is missing root node");
221
+ if (root === null) throw new Error("Virtual workdir is missing root node");
222
222
  return snapshotCurrentNode(source, state, root, "", cache);
223
223
  }
224
224
  function snapshotCurrentNode(source, state, node, path, cache) {
@@ -398,7 +398,7 @@ function modeKind(mode) {
398
398
  return mode === "120000" ? "symlink" : "blob";
399
399
  }
400
400
  /**
401
- * 从规范化变更索引导出当前 session 的最终 diff。
401
+ * 从规范化变更索引导出当前 workdir 的最终 diff。
402
402
  *
403
403
  * @example
404
404
  * ```ts
@@ -1,5 +1,4 @@
1
1
  import { SHA1 } from "../core/types.mjs";
2
- import { ObjectDatabase } from "../core/types/odb.mjs";
3
2
  import { VirtualNotDirectoryError, VirtualNotFileError, VirtualNotSymlinkError, VirtualOriginUnavailableError, VirtualPathAlreadyExistsError, VirtualPathNotFoundError, VirtualRevertNotSupportedError } from "../core/errors.mjs";
4
3
 
5
4
  //#region src/workdir/core.d.ts
@@ -19,7 +18,7 @@ type VirtualEntryKind = "blob" | "tree" | "symlink";
19
18
  interface VirtualEntryStat {
20
19
  /** 条目种类 */
21
20
  readonly kind: VirtualEntryKind;
22
- /** Git 文件模式(如 "100644"、"100755"、"40000"、"120000") */
21
+ /** Git 文件模式(如 "100644"、"100755"、"040000"、"120000") */
23
22
  readonly mode: string;
24
23
  /** 文件大小(对 blob 和 symlink 有效;目录返回 0) */
25
24
  readonly size: number;
@@ -93,42 +92,36 @@ type VirtualDiffEntry = {
93
92
  readonly source?: VirtualDiffSource;
94
93
  };
95
94
  /**
96
- * 创建 VirtualWorkdirSession 的选项
95
+ * 创建 VirtualWorkdir 的选项
97
96
  */
98
- interface CreateVirtualWorkdirSessionOptions {
97
+ interface CreateVirtualWorkdirOptions {
99
98
  /** 基线 tree 的 SHA-1 哈希 */
100
99
  readonly baseTree: SHA1;
101
100
  }
102
101
  /**
103
- * Virtual Workdir session 标识
104
- */
105
- type VirtualWorkdirSessionId = string & {
106
- readonly __brand: "VirtualWorkdirSessionId";
107
- };
108
- /**
109
- * VirtualWorkdirSession(虚拟工作目录会话)
102
+ * VirtualWorkdir(虚拟工作目录实例)
110
103
  *
111
104
  * 提供独立生命周期的可变 tree 视图,基于 `baseTree + CoW overlay` 模型。
112
105
  * 不绑定 commit,不涉及 Git index / 真实工作目录。
113
106
  *
114
- * 当前 session 对 origin 仓库对象采用弱保证:
107
+ * 当前实例对 origin 仓库对象采用弱保证:
115
108
  * 如果 base tree / origin blob 在后续被移除、损坏或不可读取,
116
109
  * 相关读取、`revert()`、`writeTree()` 等操作会抛出 `VirtualOriginUnavailableError`。
117
110
  *
118
111
  * @example
119
112
  * ```ts
120
113
  * import { createMemoryRepository } from "nano-git/repository/memory";
121
- * import { createVirtualWorkdirSession } from "nano-git/workdir/memory";
114
+ * import { createVirtualWorkdir } from "nano-git/workdir/memory";
122
115
  *
123
116
  * const repo = createMemoryRepository();
124
117
  * const tree = repo.writeTree(); // 初始空 tree
125
- * const session = createVirtualWorkdirSession(repo, { baseTree: tree });
118
+ * const workdir = createVirtualWorkdir(repo.objects, { baseTree: tree });
126
119
  *
127
- * session.writeFile("hello.txt", Buffer.from("world"));
128
- * const newTree = session.writeTree();
120
+ * workdir.writeFile("hello.txt", Buffer.from("world"));
121
+ * const newTree = workdir.writeTree();
129
122
  * ```
130
123
  */
131
- interface VirtualWorkdirSession {
124
+ interface VirtualWorkdir {
132
125
  /** 当前基线 tree 的 SHA-1 哈希 */
133
126
  readonly baseTree: SHA1;
134
127
  /** 路径是否存在 */
@@ -161,7 +154,7 @@ interface VirtualWorkdirSession {
161
154
  /**
162
155
  * 复制路径
163
156
  *
164
- * 新建 session node,共享 origin,不共享 node 身份。
157
+ * 新建 workdir node,共享 origin,不共享 node 身份。
165
158
  * 目录复制为浅复制,子项保持懒加载。
166
159
  */
167
160
  copy(from: string, to: string): void;
@@ -186,35 +179,11 @@ interface VirtualWorkdirSession {
186
179
  */
187
180
  writeTree(): SHA1;
188
181
  /**
189
- * 重置 session 到指定基线 tree
182
+ * 重置当前实例到指定基线 tree
190
183
  *
191
184
  * 丢弃全部 overlay 与变更历史。
192
185
  */
193
186
  reset(baseTree: SHA1): void;
194
187
  }
195
- /**
196
- * VirtualWorkdirBackend
197
- *
198
- * session 内部状态存储的抽象接口。
199
- * memory / file / sqlite 后端通过实现此接口来提供不同的持久化策略。
200
- *
201
- * `file` / `sqlite` 持久化 backend 当前都按单进程、单写者场景收口;
202
- * 不承诺跨进程并发写安全,也不提供多写者协调协议。
203
- *
204
- * 本接口在后续 Phase 中会逐步补充完整方法签名。
205
- * 当前仅为命名冻结与角色声明。
206
- */
207
- interface VirtualWorkdirBackend {
208
- /** 后端类型标识 */
209
- readonly kind: "memory" | "file" | "sqlite";
210
- /** 创建新 session 并返回其标识 */
211
- createSession(options: CreateVirtualWorkdirSessionOptions): VirtualWorkdirSessionId;
212
- /** 打开已存在的 session */
213
- openSession(source: ObjectDatabase, sessionId: VirtualWorkdirSessionId): VirtualWorkdirSession;
214
- /** 删除 session */
215
- deleteSession(sessionId: VirtualWorkdirSessionId): void;
216
- /** 列出当前后端中可完整恢复的 session */
217
- listSessions(): VirtualWorkdirSessionId[];
218
- }
219
188
  //#endregion
220
- export { CreateVirtualWorkdirSessionOptions, VirtualDiffChanges, VirtualDiffEntry, VirtualDiffObject, VirtualDiffSource, VirtualDirEntry, VirtualEntryKind, VirtualEntryStat, VirtualNotDirectoryError, VirtualNotFileError, VirtualNotSymlinkError, VirtualOriginUnavailableError, VirtualPathAlreadyExistsError, VirtualPathNotFoundError, VirtualRevertNotSupportedError, VirtualWorkdirBackend, VirtualWorkdirSession, VirtualWorkdirSessionId };
189
+ export { CreateVirtualWorkdirOptions, VirtualDiffChanges, VirtualDiffEntry, VirtualDiffObject, VirtualDiffSource, VirtualDirEntry, VirtualEntryKind, VirtualEntryStat, VirtualNotDirectoryError, VirtualNotFileError, VirtualNotSymlinkError, VirtualOriginUnavailableError, VirtualPathAlreadyExistsError, VirtualPathNotFoundError, VirtualRevertNotSupportedError, VirtualWorkdir };
@@ -1,10 +1,10 @@
1
1
  import { VirtualNotDirectoryError } from "../core/errors.mjs";
2
- import { ensureNodeFromTreeEntry, joinChildPath, listDirectoryChildren } from "./session-internal.mjs";
2
+ import { ensureNodeFromTreeEntry, joinChildPath, listDirectoryChildren } from "./workdir-path.mjs";
3
3
  //#region src/workdir/directory-view.ts
4
4
  /**
5
5
  * Virtual Workdir 目录展开、观察与编译计划
6
6
  *
7
- * 从 session-internal.ts 拆分,聚焦以下职责:
7
+ * 从 workdir-path.ts 拆分,聚焦以下职责:
8
8
  * - 目录子项观察(observeDirectoryChildren / observeListedDirectoryChild / observeNamedDirectoryChild)
9
9
  * - origin 按名查询视图(createNamedOriginChildLookup)
10
10
  * - 受影响子项编译计划(planAffectedDirectoryChildren)
@@ -1,12 +1,12 @@
1
- import { getRootNode } from "./session-internal.mjs";
1
+ import { getRootNode } from "./workdir-path.mjs";
2
2
  import { observeDirectoryChildren } from "./directory-view.mjs";
3
3
  import { createDirtyDirSummary } from "./dirty-dir.mjs";
4
4
  //#region src/workdir/dirty-dir-plan.ts
5
5
  /**
6
6
  * Virtual Workdir dirty-dir summary 重建策略
7
7
  *
8
- * 把 session 写路径里的脏目录摘要清理与重建逻辑集中到单独模块,
9
- * 让 session.ts 更接近纯编排层。
8
+ * 把 workdir 写路径里的脏目录摘要清理与重建逻辑集中到单独模块,
9
+ * 让 workdir.ts 更接近纯编排层。
10
10
  */
11
11
  /**
12
12
  * 创建 dirty-dir summary 策略器。
@@ -1,22 +1,44 @@
1
- import { VirtualWorkdirBackend } from "./core.mjs";
1
+ import { ObjectDatabase } from "../core/types/odb.mjs";
2
+ import { CreateVirtualWorkdirOptions, VirtualWorkdir } from "./core.mjs";
3
+ import { VirtualWorkdirStateStore } from "./state-store.mjs";
2
4
 
3
5
  //#region src/workdir/file-backend.d.ts
4
- /** 创建文件系统 Virtual Workdir backend 的可选参数 */
5
- interface CreateFileVirtualWorkdirBackendOptions {
6
- /** session 根目录名,默认 `sessions` */
7
- readonly sessionsDirName?: string;
6
+ /** 打开文件系统 VirtualWorkdir 的可选参数 */
7
+ interface OpenFileVirtualWorkdirOptions extends CreateVirtualWorkdirOptions {
8
+ /** 不存在时按 baseTree 初始化 */
9
+ readonly create?: boolean;
8
10
  }
9
11
  /**
10
- * 创建基于文件系统目录的 Virtual Workdir backend
12
+ * 打开基于目录持久化的 VirtualWorkdir
11
13
  *
12
14
  * @example
13
15
  * ```ts
14
- * const backend = createFileVirtualWorkdirBackend("/tmp/workdirs");
15
- * const sessionId = backend.createSession({ baseTree: tree });
16
- * const session = backend.openSession(repo.objects, sessionId);
17
- * expect(session.baseTree).toBe(tree);
16
+ * const workdir = openFileVirtualWorkdir(repo.objects, "/tmp/workdir", {
17
+ * baseTree: tree,
18
+ * create: true,
19
+ * });
20
+ * expect(workdir.baseTree).toBe(tree);
18
21
  * ```
19
22
  */
20
- declare function createFileVirtualWorkdirBackend(rootDir: string, options?: CreateFileVirtualWorkdirBackendOptions): VirtualWorkdirBackend;
23
+ declare function openFileVirtualWorkdir(source: ObjectDatabase, workdirDir: string, options: OpenFileVirtualWorkdirOptions): VirtualWorkdir;
24
+ /**
25
+ * 删除指定目录上的持久化 VirtualWorkdir
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * deleteFileVirtualWorkdir("/tmp/workdir");
30
+ * ```
31
+ */
32
+ declare function deleteFileVirtualWorkdir(workdirDir: string): void;
33
+ /**
34
+ * 创建单个文件系统 VirtualWorkdir 的状态存储
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const store = createFileVirtualWorkdirStateStore("/tmp/workdir");
39
+ * expect(store.kind).toBe("file");
40
+ * ```
41
+ */
42
+ declare function createFileVirtualWorkdirStateStore(workdirDir: string): VirtualWorkdirStateStore;
21
43
  //#endregion
22
- export { CreateFileVirtualWorkdirBackendOptions, createFileVirtualWorkdirBackend };
44
+ export { OpenFileVirtualWorkdirOptions, createFileVirtualWorkdirStateStore, deleteFileVirtualWorkdir, openFileVirtualWorkdir };