shell-dsl 0.0.34 → 0.0.36
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 +41 -5
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/fs/memfs-adapter.cjs +56 -2
- package/dist/cjs/src/fs/memfs-adapter.cjs.map +3 -3
- package/dist/cjs/src/fs/real-fs.cjs +134 -3
- package/dist/cjs/src/fs/real-fs.cjs.map +3 -3
- package/dist/cjs/src/fs/special-files.cjs +3 -2
- package/dist/cjs/src/fs/special-files.cjs.map +3 -3
- package/dist/cjs/src/fs/web-fs.cjs +72 -3
- package/dist/cjs/src/fs/web-fs.cjs.map +3 -3
- package/dist/cjs/src/index.cjs +2 -7
- package/dist/cjs/src/index.cjs.map +3 -3
- package/dist/cjs/src/interpreter/interpreter.cjs +186 -68
- package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
- package/dist/cjs/src/parser/ast.cjs +5 -25
- package/dist/cjs/src/parser/ast.cjs.map +3 -3
- package/dist/cjs/src/parser/index.cjs +2 -7
- package/dist/cjs/src/parser/index.cjs.map +3 -3
- package/dist/cjs/src/parser/parser.cjs +132 -82
- package/dist/cjs/src/parser/parser.cjs.map +3 -3
- package/dist/cjs/src/types.cjs.map +2 -2
- package/dist/cjs/src/vcs/content.cjs +106 -0
- package/dist/cjs/src/vcs/content.cjs.map +10 -0
- package/dist/cjs/src/vcs/diff.cjs +72 -28
- package/dist/cjs/src/vcs/diff.cjs.map +3 -3
- package/dist/cjs/src/vcs/index.cjs.map +1 -1
- package/dist/cjs/src/vcs/objects.cjs +141 -0
- package/dist/cjs/src/vcs/objects.cjs.map +10 -0
- package/dist/cjs/src/vcs/rules.cjs +6 -3
- package/dist/cjs/src/vcs/rules.cjs.map +3 -3
- package/dist/cjs/src/vcs/snapshot.cjs +89 -39
- package/dist/cjs/src/vcs/snapshot.cjs.map +3 -3
- package/dist/cjs/src/vcs/storage.cjs +44 -3
- package/dist/cjs/src/vcs/storage.cjs.map +3 -3
- package/dist/cjs/src/vcs/text-diff.cjs +219 -0
- package/dist/cjs/src/vcs/text-diff.cjs.map +10 -0
- package/dist/cjs/src/vcs/vcs.cjs +108 -61
- package/dist/cjs/src/vcs/vcs.cjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/fs/memfs-adapter.mjs +57 -2
- package/dist/mjs/src/fs/memfs-adapter.mjs.map +3 -3
- package/dist/mjs/src/fs/real-fs.mjs +135 -3
- package/dist/mjs/src/fs/real-fs.mjs.map +3 -3
- package/dist/mjs/src/fs/special-files.mjs +3 -2
- package/dist/mjs/src/fs/special-files.mjs.map +3 -3
- package/dist/mjs/src/fs/web-fs.mjs +72 -3
- package/dist/mjs/src/fs/web-fs.mjs.map +3 -3
- package/dist/mjs/src/index.mjs +4 -14
- package/dist/mjs/src/index.mjs.map +3 -3
- package/dist/mjs/src/interpreter/interpreter.mjs +186 -68
- package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
- package/dist/mjs/src/parser/ast.mjs +5 -25
- package/dist/mjs/src/parser/ast.mjs.map +3 -3
- package/dist/mjs/src/parser/index.mjs +4 -14
- package/dist/mjs/src/parser/index.mjs.map +3 -3
- package/dist/mjs/src/parser/parser.mjs +132 -82
- package/dist/mjs/src/parser/parser.mjs.map +3 -3
- package/dist/mjs/src/types.mjs.map +2 -2
- package/dist/mjs/src/vcs/content.mjs +66 -0
- package/dist/mjs/src/vcs/content.mjs.map +10 -0
- package/dist/mjs/src/vcs/diff.mjs +72 -28
- package/dist/mjs/src/vcs/diff.mjs.map +3 -3
- package/dist/mjs/src/vcs/index.mjs.map +1 -1
- package/dist/mjs/src/vcs/objects.mjs +106 -0
- package/dist/mjs/src/vcs/objects.mjs.map +10 -0
- package/dist/mjs/src/vcs/rules.mjs +6 -3
- package/dist/mjs/src/vcs/rules.mjs.map +3 -3
- package/dist/mjs/src/vcs/snapshot.mjs +89 -39
- package/dist/mjs/src/vcs/snapshot.mjs.map +3 -3
- package/dist/mjs/src/vcs/storage.mjs +45 -3
- package/dist/mjs/src/vcs/storage.mjs.map +3 -3
- package/dist/mjs/src/vcs/text-diff.mjs +179 -0
- package/dist/mjs/src/vcs/text-diff.mjs.map +10 -0
- package/dist/mjs/src/vcs/vcs.mjs +115 -63
- package/dist/mjs/src/vcs/vcs.mjs.map +3 -3
- package/dist/types/src/fs/real-fs.d.ts +12 -1
- package/dist/types/src/index.d.ts +4 -4
- package/dist/types/src/interpreter/interpreter.d.ts +15 -1
- package/dist/types/src/parser/ast.d.ts +34 -38
- package/dist/types/src/parser/index.d.ts +2 -2
- package/dist/types/src/parser/parser.d.ts +4 -1
- package/dist/types/src/types.d.ts +10 -0
- package/dist/types/src/vcs/content.d.ts +6 -0
- package/dist/types/src/vcs/diff.d.ts +10 -7
- package/dist/types/src/vcs/index.d.ts +1 -1
- package/dist/types/src/vcs/objects.d.ts +22 -0
- package/dist/types/src/vcs/snapshot.d.ts +13 -8
- package/dist/types/src/vcs/storage.d.ts +7 -1
- package/dist/types/src/vcs/text-diff.d.ts +1 -0
- package/dist/types/src/vcs/types.d.ts +20 -5
- package/dist/types/src/vcs/vcs.d.ts +6 -0
- package/package.json +7 -2
|
@@ -39,63 +39,107 @@ var __export = (target, all) => {
|
|
|
39
39
|
// src/vcs/diff.ts
|
|
40
40
|
var exports_diff = {};
|
|
41
41
|
__export(exports_diff, {
|
|
42
|
-
diffWorkingTree: () => diffWorkingTree,
|
|
43
42
|
diffManifests: () => diffManifests
|
|
44
43
|
});
|
|
45
44
|
module.exports = __toCommonJS(exports_diff);
|
|
45
|
+
var import_content = require("./content.cjs");
|
|
46
46
|
var import_rules = require("./rules.cjs");
|
|
47
|
-
var
|
|
48
|
-
function diffManifests(before, after,
|
|
47
|
+
var import_text_diff = require("./text-diff.cjs");
|
|
48
|
+
async function diffManifests(before, after, options) {
|
|
49
49
|
const entries = [];
|
|
50
50
|
const allPaths = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
51
|
-
for (const path of allPaths) {
|
|
51
|
+
for (const path of [...allPaths].sort((a, b) => a.localeCompare(b))) {
|
|
52
52
|
const prev = before[path];
|
|
53
53
|
const curr = after[path];
|
|
54
54
|
if (!prev && curr) {
|
|
55
|
-
entries.push(createDiffEntry("add", path, curr, undefined,
|
|
55
|
+
entries.push(await createDiffEntry("add", path, curr, undefined, options));
|
|
56
56
|
} else if (prev && !curr) {
|
|
57
|
-
entries.push(createDiffEntry("delete", path, undefined, prev,
|
|
57
|
+
entries.push(await createDiffEntry("delete", path, undefined, prev, options));
|
|
58
58
|
} else if (prev && curr && !entriesEqual(prev, curr)) {
|
|
59
|
-
entries.push(createDiffEntry("modify", path, curr, prev,
|
|
59
|
+
entries.push(await createDiffEntry("modify", path, curr, prev, options));
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
return entries
|
|
62
|
+
return entries;
|
|
63
63
|
}
|
|
64
|
-
async function
|
|
65
|
-
const
|
|
66
|
-
rules,
|
|
67
|
-
trackedPaths: Object.keys(manifest)
|
|
68
|
-
});
|
|
69
|
-
return diffManifests(manifest, workingManifest, rules);
|
|
70
|
-
}
|
|
71
|
-
function createDiffEntry(type, path, current, previous, rules) {
|
|
64
|
+
async function createDiffEntry(type, path, current, previous, options) {
|
|
65
|
+
const rules = options.rules ?? new import_rules.VCSRules;
|
|
72
66
|
const attributes = rules.resolveAttributes(path);
|
|
73
67
|
const entryKind = getEntryKind(current ?? previous);
|
|
74
68
|
const previousEntryKind = previous ? getEntryKind(previous) : undefined;
|
|
69
|
+
const currentFile = isFileEntry(current) ? current : undefined;
|
|
70
|
+
const previousFile = isFileEntry(previous) ? previous : undefined;
|
|
71
|
+
const binary = await resolveBinary(path, currentFile, previousFile, attributes, options);
|
|
72
|
+
const diff = resolveDiffMode(attributes, binary);
|
|
75
73
|
const entry = {
|
|
76
74
|
type,
|
|
77
75
|
path,
|
|
78
|
-
binary
|
|
79
|
-
diff
|
|
76
|
+
binary,
|
|
77
|
+
diff,
|
|
80
78
|
entryKind,
|
|
81
|
-
previousEntryKind
|
|
79
|
+
previousEntryKind,
|
|
80
|
+
blobId: currentFile?.blobId,
|
|
81
|
+
previousBlobId: previousFile?.blobId
|
|
82
82
|
};
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
83
|
+
if (!currentFile && !previousFile) {
|
|
84
|
+
return entry;
|
|
85
|
+
}
|
|
86
|
+
if (diff === "none") {
|
|
87
|
+
entry.patchSuppressedReason = "none";
|
|
88
|
+
return entry;
|
|
90
89
|
}
|
|
90
|
+
if (diff === "binary") {
|
|
91
|
+
entry.patchSuppressedReason = "binary";
|
|
92
|
+
return entry;
|
|
93
|
+
}
|
|
94
|
+
const largestSize = Math.max(currentFile?.size ?? 0, previousFile?.size ?? 0);
|
|
95
|
+
if (largestSize > import_content.MAX_PATCH_BYTES) {
|
|
96
|
+
entry.patchSuppressedReason = "too-large";
|
|
97
|
+
return entry;
|
|
98
|
+
}
|
|
99
|
+
const previousText = previousFile ? await options.objectStore.readBlobText(previousFile.blobId) : "";
|
|
100
|
+
const currentText = currentFile ? await options.objectStore.readBlobText(currentFile.blobId) : "";
|
|
101
|
+
entry.patch = import_text_diff.createUnifiedPatch(path, previousText, currentText);
|
|
91
102
|
return entry;
|
|
92
103
|
}
|
|
104
|
+
async function resolveBinary(path, current, previous, attributes, options) {
|
|
105
|
+
if (attributes.diff === "text") {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (attributes.diff === "binary" || attributes.binary === true) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
const currentBinary = await resolveEntryBinary(path, current, options.afterIndex, options.objectStore);
|
|
112
|
+
const previousBinary = await resolveEntryBinary(path, previous, options.beforeIndex, options.objectStore);
|
|
113
|
+
return currentBinary || previousBinary;
|
|
114
|
+
}
|
|
115
|
+
async function resolveEntryBinary(path, entry, indexEntries, objectStore) {
|
|
116
|
+
if (!entry) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const cached = indexEntries?.[path];
|
|
120
|
+
if (cached?.blobId === entry.blobId) {
|
|
121
|
+
return cached.binary;
|
|
122
|
+
}
|
|
123
|
+
return objectStore.isBinaryBlob(entry.blobId);
|
|
124
|
+
}
|
|
125
|
+
function resolveDiffMode(attributes, binary) {
|
|
126
|
+
if (attributes.diff === "none") {
|
|
127
|
+
return "none";
|
|
128
|
+
}
|
|
129
|
+
if (attributes.diff === "text") {
|
|
130
|
+
return "text";
|
|
131
|
+
}
|
|
132
|
+
if (attributes.diff === "binary" || binary) {
|
|
133
|
+
return "binary";
|
|
134
|
+
}
|
|
135
|
+
return "text";
|
|
136
|
+
}
|
|
93
137
|
function entriesEqual(a, b) {
|
|
94
138
|
if (getEntryKind(a) !== getEntryKind(b))
|
|
95
139
|
return false;
|
|
96
140
|
if (!isFileEntry(a) || !isFileEntry(b))
|
|
97
141
|
return true;
|
|
98
|
-
return a.
|
|
142
|
+
return a.blobId === b.blobId && a.size === b.size;
|
|
99
143
|
}
|
|
100
144
|
function getEntryKind(entry) {
|
|
101
145
|
return entry?.kind === "directory" ? "directory" : "file";
|
|
@@ -104,4 +148,4 @@ function isFileEntry(entry) {
|
|
|
104
148
|
return !!entry && entry.kind !== "directory";
|
|
105
149
|
}
|
|
106
150
|
|
|
107
|
-
//# debugId=
|
|
151
|
+
//# debugId=07954E8C085717B664756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/vcs/diff.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {
|
|
5
|
+
"import type { TreeManifest, DiffEntry, TreeEntry, VCSIndexEntry } from \"./types.cjs\";\nimport { MAX_PATCH_BYTES } from \"./content.cjs\";\nimport { VCSObjectStore } from \"./objects.cjs\";\nimport { VCSRules } from \"./rules.cjs\";\nimport { createUnifiedPatch } from \"./text-diff.cjs\";\n\ninterface DiffOptions {\n rules?: VCSRules;\n objectStore: VCSObjectStore;\n beforeIndex?: Record<string, VCSIndexEntry>;\n afterIndex?: Record<string, VCSIndexEntry>;\n}\n\n/**\n * Compute diff entries between two tree manifests.\n */\nexport async function diffManifests(\n before: TreeManifest,\n after: TreeManifest,\n options: DiffOptions,\n): Promise<DiffEntry[]> {\n const entries: DiffEntry[] = [];\n const allPaths = new Set([...Object.keys(before), ...Object.keys(after)]);\n\n for (const path of [...allPaths].sort((a, b) => a.localeCompare(b))) {\n const prev = before[path];\n const curr = after[path];\n\n if (!prev && curr) {\n entries.push(await createDiffEntry(\"add\", path, curr, undefined, options));\n } else if (prev && !curr) {\n entries.push(await createDiffEntry(\"delete\", path, undefined, prev, options));\n } else if (prev && curr && !entriesEqual(prev, curr)) {\n entries.push(await createDiffEntry(\"modify\", path, curr, prev, options));\n }\n }\n\n return entries;\n}\n\nasync function createDiffEntry(\n type: DiffEntry[\"type\"],\n path: string,\n current: TreeEntry | undefined,\n previous: TreeEntry | undefined,\n options: DiffOptions,\n): Promise<DiffEntry> {\n const rules = options.rules ?? new VCSRules();\n const attributes = rules.resolveAttributes(path);\n const entryKind = getEntryKind(current ?? previous);\n const previousEntryKind = previous ? getEntryKind(previous) : undefined;\n const currentFile = isFileEntry(current) ? current : undefined;\n const previousFile = isFileEntry(previous) ? previous : undefined;\n const binary = await resolveBinary(path, currentFile, previousFile, attributes, options);\n const diff = resolveDiffMode(attributes, binary);\n const entry: DiffEntry = {\n type,\n path,\n binary,\n diff,\n entryKind,\n previousEntryKind,\n blobId: currentFile?.blobId,\n previousBlobId: previousFile?.blobId,\n };\n\n if (!currentFile && !previousFile) {\n return entry;\n }\n\n if (diff === \"none\") {\n entry.patchSuppressedReason = \"none\";\n return entry;\n }\n\n if (diff === \"binary\") {\n entry.patchSuppressedReason = \"binary\";\n return entry;\n }\n\n const largestSize = Math.max(currentFile?.size ?? 0, previousFile?.size ?? 0);\n if (largestSize > MAX_PATCH_BYTES) {\n entry.patchSuppressedReason = \"too-large\";\n return entry;\n }\n\n const previousText = previousFile\n ? await options.objectStore.readBlobText(previousFile.blobId)\n : \"\";\n const currentText = currentFile\n ? await options.objectStore.readBlobText(currentFile.blobId)\n : \"\";\n entry.patch = createUnifiedPatch(path, previousText, currentText);\n return entry;\n}\n\nasync function resolveBinary(\n path: string,\n current: Extract<TreeEntry, { kind?: \"file\" }> | undefined,\n previous: Extract<TreeEntry, { kind?: \"file\" }> | undefined,\n attributes: ReturnType<VCSRules[\"resolveAttributes\"]>,\n options: DiffOptions,\n): Promise<boolean> {\n if (attributes.diff === \"text\") {\n return false;\n }\n if (attributes.diff === \"binary\" || attributes.binary === true) {\n return true;\n }\n\n const currentBinary = await resolveEntryBinary(\n path,\n current,\n options.afterIndex,\n options.objectStore,\n );\n const previousBinary = await resolveEntryBinary(\n path,\n previous,\n options.beforeIndex,\n options.objectStore,\n );\n\n return currentBinary || previousBinary;\n}\n\nasync function resolveEntryBinary(\n path: string,\n entry: Extract<TreeEntry, { kind?: \"file\" }> | undefined,\n indexEntries: Record<string, VCSIndexEntry> | undefined,\n objectStore: VCSObjectStore,\n): Promise<boolean> {\n if (!entry) {\n return false;\n }\n const cached = indexEntries?.[path];\n if (cached?.blobId === entry.blobId) {\n return cached.binary;\n }\n return objectStore.isBinaryBlob(entry.blobId);\n}\n\nfunction resolveDiffMode(\n attributes: ReturnType<VCSRules[\"resolveAttributes\"]>,\n binary: boolean,\n): DiffEntry[\"diff\"] {\n if (attributes.diff === \"none\") {\n return \"none\";\n }\n if (attributes.diff === \"text\") {\n return \"text\";\n }\n if (attributes.diff === \"binary\" || binary) {\n return \"binary\";\n }\n return \"text\";\n}\n\nfunction entriesEqual(a: TreeEntry, b: TreeEntry): boolean {\n if (getEntryKind(a) !== getEntryKind(b)) return false;\n if (!isFileEntry(a) || !isFileEntry(b)) return true;\n return a.blobId === b.blobId && a.size === b.size;\n}\n\nfunction getEntryKind(entry: TreeEntry | undefined): \"file\" | \"directory\" {\n return entry?.kind === \"directory\" ? \"directory\" : \"file\";\n}\n\nfunction isFileEntry(entry: TreeEntry | undefined): entry is Extract<TreeEntry, { kind?: \"file\" }> {\n return !!entry && entry.kind !== \"directory\";\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACgC,IAAhC;AAEyB,IAAzB;AACmC,IAAnC;AAYA,eAAsB,aAAa,CACjC,QACA,OACA,SACsB;AAAA,EACtB,MAAM,UAAuB,CAAC;AAAA,EAC9B,MAAM,WAAW,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC;AAAA,EAExE,WAAW,QAAQ,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC,GAAG;AAAA,IACnE,MAAM,OAAO,OAAO;AAAA,IACpB,MAAM,OAAO,MAAM;AAAA,IAEnB,IAAI,CAAC,QAAQ,MAAM;AAAA,MACjB,QAAQ,KAAK,MAAM,gBAAgB,OAAO,MAAM,MAAM,WAAW,OAAO,CAAC;AAAA,IAC3E,EAAO,SAAI,QAAQ,CAAC,MAAM;AAAA,MACxB,QAAQ,KAAK,MAAM,gBAAgB,UAAU,MAAM,WAAW,MAAM,OAAO,CAAC;AAAA,IAC9E,EAAO,SAAI,QAAQ,QAAQ,CAAC,aAAa,MAAM,IAAI,GAAG;AAAA,MACpD,QAAQ,KAAK,MAAM,gBAAgB,UAAU,MAAM,MAAM,MAAM,OAAO,CAAC;AAAA,IACzE;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAGT,eAAe,eAAe,CAC5B,MACA,MACA,SACA,UACA,SACoB;AAAA,EACpB,MAAM,QAAQ,QAAQ,SAAS,IAAI;AAAA,EACnC,MAAM,aAAa,MAAM,kBAAkB,IAAI;AAAA,EAC/C,MAAM,YAAY,aAAa,WAAW,QAAQ;AAAA,EAClD,MAAM,oBAAoB,WAAW,aAAa,QAAQ,IAAI;AAAA,EAC9D,MAAM,cAAc,YAAY,OAAO,IAAI,UAAU;AAAA,EACrD,MAAM,eAAe,YAAY,QAAQ,IAAI,WAAW;AAAA,EACxD,MAAM,SAAS,MAAM,cAAc,MAAM,aAAa,cAAc,YAAY,OAAO;AAAA,EACvF,MAAM,OAAO,gBAAgB,YAAY,MAAM;AAAA,EAC/C,MAAM,QAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,aAAa;AAAA,IACrB,gBAAgB,cAAc;AAAA,EAChC;AAAA,EAEA,IAAI,CAAC,eAAe,CAAC,cAAc;AAAA,IACjC,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAS,QAAQ;AAAA,IACnB,MAAM,wBAAwB;AAAA,IAC9B,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAS,UAAU;AAAA,IACrB,MAAM,wBAAwB;AAAA,IAC9B,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,KAAK,IAAI,aAAa,QAAQ,GAAG,cAAc,QAAQ,CAAC;AAAA,EAC5E,IAAI,cAAc,gCAAiB;AAAA,IACjC,MAAM,wBAAwB;AAAA,IAC9B,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAe,eACjB,MAAM,QAAQ,YAAY,aAAa,aAAa,MAAM,IAC1D;AAAA,EACJ,MAAM,cAAc,cAChB,MAAM,QAAQ,YAAY,aAAa,YAAY,MAAM,IACzD;AAAA,EACJ,MAAM,QAAQ,oCAAmB,MAAM,cAAc,WAAW;AAAA,EAChE,OAAO;AAAA;AAGT,eAAe,aAAa,CAC1B,MACA,SACA,UACA,YACA,SACkB;AAAA,EAClB,IAAI,WAAW,SAAS,QAAQ;AAAA,IAC9B,OAAO;AAAA,EACT;AAAA,EACA,IAAI,WAAW,SAAS,YAAY,WAAW,WAAW,MAAM;AAAA,IAC9D,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBAAgB,MAAM,mBAC1B,MACA,SACA,QAAQ,YACR,QAAQ,WACV;AAAA,EACA,MAAM,iBAAiB,MAAM,mBAC3B,MACA,UACA,QAAQ,aACR,QAAQ,WACV;AAAA,EAEA,OAAO,iBAAiB;AAAA;AAG1B,eAAe,kBAAkB,CAC/B,MACA,OACA,cACA,aACkB;AAAA,EAClB,IAAI,CAAC,OAAO;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,MAAM,SAAS,eAAe;AAAA,EAC9B,IAAI,QAAQ,WAAW,MAAM,QAAQ;AAAA,IACnC,OAAO,OAAO;AAAA,EAChB;AAAA,EACA,OAAO,YAAY,aAAa,MAAM,MAAM;AAAA;AAG9C,SAAS,eAAe,CACtB,YACA,QACmB;AAAA,EACnB,IAAI,WAAW,SAAS,QAAQ;AAAA,IAC9B,OAAO;AAAA,EACT;AAAA,EACA,IAAI,WAAW,SAAS,QAAQ;AAAA,IAC9B,OAAO;AAAA,EACT;AAAA,EACA,IAAI,WAAW,SAAS,YAAY,QAAQ;AAAA,IAC1C,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,YAAY,CAAC,GAAc,GAAuB;AAAA,EACzD,IAAI,aAAa,CAAC,MAAM,aAAa,CAAC;AAAA,IAAG,OAAO;AAAA,EAChD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC;AAAA,IAAG,OAAO;AAAA,EAC/C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE;AAAA;AAG/C,SAAS,YAAY,CAAC,OAAoD;AAAA,EACxE,OAAO,OAAO,SAAS,cAAc,cAAc;AAAA;AAGrD,SAAS,WAAW,CAAC,OAA8E;AAAA,EACjG,OAAO,CAAC,CAAC,SAAS,MAAM,SAAS;AAAA;",
|
|
8
|
+
"debugId": "07954E8C085717B664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/vcs/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export { VersionControlSystem } from \"./vcs.cjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./types.cjs\";\n"
|
|
5
|
+
"export { VersionControlSystem } from \"./vcs.cjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n VCSPatchSuppressionReason,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n VCSIndexEntry,\n VCSIndexFile,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./types.cjs\";\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAqC,IAArC;",
|
|
8
8
|
"debugId": "882B2013CEEDB5D864756E2164756E21",
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/vcs/objects.ts
|
|
40
|
+
var exports_objects = {};
|
|
41
|
+
__export(exports_objects, {
|
|
42
|
+
VCSObjectStore: () => VCSObjectStore
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(exports_objects);
|
|
45
|
+
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
46
|
+
var import_content = require("./content.cjs");
|
|
47
|
+
|
|
48
|
+
class VCSObjectStore {
|
|
49
|
+
fs;
|
|
50
|
+
basePath;
|
|
51
|
+
constructor(fs, basePath) {
|
|
52
|
+
this.fs = fs;
|
|
53
|
+
this.basePath = basePath;
|
|
54
|
+
}
|
|
55
|
+
async initialize() {
|
|
56
|
+
await this.fs.mkdir(this.path("objects", "blobs"), { recursive: true });
|
|
57
|
+
await this.fs.mkdir(this.path("tmp"), { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
async hasBlob(blobId) {
|
|
60
|
+
return this.fs.exists(this.blobPath(blobId));
|
|
61
|
+
}
|
|
62
|
+
async store(source) {
|
|
63
|
+
const tempPath = this.path("tmp", `${Date.now()}-${Math.random().toString(36).slice(2)}.blob`);
|
|
64
|
+
const writer = await this.fs.writeStream(tempPath);
|
|
65
|
+
const hash = import_sha2.sha256.create();
|
|
66
|
+
let size = 0;
|
|
67
|
+
let sample = new Uint8Array;
|
|
68
|
+
try {
|
|
69
|
+
for await (const chunk of source) {
|
|
70
|
+
const bytes = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
|
|
71
|
+
hash.update(bytes);
|
|
72
|
+
size += bytes.byteLength;
|
|
73
|
+
sample = import_content.appendSample(sample, bytes);
|
|
74
|
+
await writer.write(bytes);
|
|
75
|
+
}
|
|
76
|
+
await writer.close();
|
|
77
|
+
const blobId = toHex(hash.digest());
|
|
78
|
+
const finalPath = this.blobPath(blobId);
|
|
79
|
+
await this.fs.mkdir(this.fs.dirname(finalPath), { recursive: true });
|
|
80
|
+
if (!await this.fs.exists(finalPath)) {
|
|
81
|
+
await copyStream(this.fs, tempPath, finalPath);
|
|
82
|
+
}
|
|
83
|
+
await this.fs.rm(tempPath, { force: true });
|
|
84
|
+
return {
|
|
85
|
+
blobId,
|
|
86
|
+
size,
|
|
87
|
+
binary: import_content.detectBinaryFromSample(sample),
|
|
88
|
+
sampleHash: import_content.hashSample(sample)
|
|
89
|
+
};
|
|
90
|
+
} catch (error) {
|
|
91
|
+
await writer.abort?.(error);
|
|
92
|
+
await this.fs.rm(tempPath, { force: true });
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async readBlob(blobId) {
|
|
97
|
+
return this.fs.readFile(this.blobPath(blobId));
|
|
98
|
+
}
|
|
99
|
+
async readBlobText(blobId) {
|
|
100
|
+
return this.fs.readFile(this.blobPath(blobId), "utf8");
|
|
101
|
+
}
|
|
102
|
+
readBlobStream(blobId) {
|
|
103
|
+
return this.fs.readStream(this.blobPath(blobId));
|
|
104
|
+
}
|
|
105
|
+
async isBinaryBlob(blobId) {
|
|
106
|
+
const sample = await import_content.readStreamSample(this.readBlobStream(blobId));
|
|
107
|
+
return import_content.detectBinaryFromSample(sample);
|
|
108
|
+
}
|
|
109
|
+
async deleteTempFiles() {
|
|
110
|
+
await this.fs.rm(this.path("tmp"), { recursive: true, force: true });
|
|
111
|
+
await this.fs.mkdir(this.path("tmp"), { recursive: true });
|
|
112
|
+
}
|
|
113
|
+
blobPath(blobId) {
|
|
114
|
+
return this.path("objects", "blobs", blobId.slice(0, 2), blobId.slice(2));
|
|
115
|
+
}
|
|
116
|
+
path(...segments) {
|
|
117
|
+
return this.fs.resolve(this.basePath, ...segments);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function copyStream(fs, fromPath, toPath) {
|
|
121
|
+
const writer = await fs.writeStream(toPath);
|
|
122
|
+
try {
|
|
123
|
+
for await (const chunk of fs.readStream(fromPath)) {
|
|
124
|
+
await writer.write(chunk);
|
|
125
|
+
}
|
|
126
|
+
await writer.close();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
await writer.abort?.(error);
|
|
129
|
+
await fs.rm(toPath, { force: true });
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function toHex(bytes) {
|
|
134
|
+
let out = "";
|
|
135
|
+
for (const byte of bytes) {
|
|
136
|
+
out += byte.toString(16).padStart(2, "0");
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//# debugId=46E2107E1DA7789564756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/vcs/objects.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { sha256 } from \"@noble/hashes/sha2.js\";\nimport type { VirtualFS } from \"../types.cjs\";\nimport {\n appendSample,\n detectBinaryFromSample,\n hashSample,\n readStreamSample,\n} from \"./content.cjs\";\n\nexport interface StoredBlob {\n blobId: string;\n size: number;\n binary: boolean;\n sampleHash: string;\n}\n\nexport class VCSObjectStore {\n constructor(\n private readonly fs: VirtualFS,\n private readonly basePath: string,\n ) {}\n\n async initialize(): Promise<void> {\n await this.fs.mkdir(this.path(\"objects\", \"blobs\"), { recursive: true });\n await this.fs.mkdir(this.path(\"tmp\"), { recursive: true });\n }\n\n async hasBlob(blobId: string): Promise<boolean> {\n return this.fs.exists(this.blobPath(blobId));\n }\n\n async store(source: AsyncIterable<Uint8Array>): Promise<StoredBlob> {\n const tempPath = this.path(\"tmp\", `${Date.now()}-${Math.random().toString(36).slice(2)}.blob`);\n const writer = await this.fs.writeStream(tempPath);\n const hash = sha256.create();\n let size = 0;\n let sample: Uint8Array<ArrayBufferLike> = new Uint8Array();\n\n try {\n for await (const chunk of source) {\n const bytes = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);\n hash.update(bytes);\n size += bytes.byteLength;\n sample = appendSample(sample, bytes);\n await writer.write(bytes);\n }\n await writer.close();\n\n const blobId = toHex(hash.digest());\n const finalPath = this.blobPath(blobId);\n await this.fs.mkdir(this.fs.dirname(finalPath), { recursive: true });\n\n if (!(await this.fs.exists(finalPath))) {\n await copyStream(this.fs, tempPath, finalPath);\n }\n\n await this.fs.rm(tempPath, { force: true });\n return {\n blobId,\n size,\n binary: detectBinaryFromSample(sample),\n sampleHash: hashSample(sample),\n };\n } catch (error) {\n await writer.abort?.(error);\n await this.fs.rm(tempPath, { force: true });\n throw error;\n }\n }\n\n async readBlob(blobId: string): Promise<Buffer> {\n return this.fs.readFile(this.blobPath(blobId));\n }\n\n async readBlobText(blobId: string): Promise<string> {\n return this.fs.readFile(this.blobPath(blobId), \"utf8\");\n }\n\n readBlobStream(blobId: string): AsyncIterable<Uint8Array> {\n return this.fs.readStream(this.blobPath(blobId));\n }\n\n async isBinaryBlob(blobId: string): Promise<boolean> {\n const sample = await readStreamSample(this.readBlobStream(blobId));\n return detectBinaryFromSample(sample);\n }\n\n async deleteTempFiles(): Promise<void> {\n await this.fs.rm(this.path(\"tmp\"), { recursive: true, force: true });\n await this.fs.mkdir(this.path(\"tmp\"), { recursive: true });\n }\n\n private blobPath(blobId: string): string {\n return this.path(\"objects\", \"blobs\", blobId.slice(0, 2), blobId.slice(2));\n }\n\n private path(...segments: string[]): string {\n return this.fs.resolve(this.basePath, ...segments);\n }\n}\n\nasync function copyStream(fs: VirtualFS, fromPath: string, toPath: string): Promise<void> {\n const writer = await fs.writeStream(toPath);\n try {\n for await (const chunk of fs.readStream(fromPath)) {\n await writer.write(chunk);\n }\n await writer.close();\n } catch (error) {\n await writer.abort?.(error);\n await fs.rm(toPath, { force: true });\n throw error;\n }\n}\n\nfunction toHex(bytes: Uint8Array): string {\n let out = \"\";\n for (const byte of bytes) {\n out += byte.toString(16).padStart(2, \"0\");\n }\n return out;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "46E2107E1DA7789564756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -97,8 +97,8 @@ class VCSRules {
|
|
|
97
97
|
return this.isIgnored(relPath);
|
|
98
98
|
}
|
|
99
99
|
resolveAttributes(relPath) {
|
|
100
|
-
let binary
|
|
101
|
-
let diff
|
|
100
|
+
let binary;
|
|
101
|
+
let diff;
|
|
102
102
|
for (const rule of this.attributeRules) {
|
|
103
103
|
if (!matchVCSPath(rule.pattern, relPath))
|
|
104
104
|
continue;
|
|
@@ -112,6 +112,9 @@ class VCSRules {
|
|
|
112
112
|
if (diff === "binary") {
|
|
113
113
|
binary = true;
|
|
114
114
|
}
|
|
115
|
+
if (diff === "text") {
|
|
116
|
+
binary = false;
|
|
117
|
+
}
|
|
115
118
|
return { binary, diff };
|
|
116
119
|
}
|
|
117
120
|
}
|
|
@@ -177,4 +180,4 @@ function hasTrackedPathAtOrBelow(relPath, trackedPaths) {
|
|
|
177
180
|
return false;
|
|
178
181
|
}
|
|
179
182
|
|
|
180
|
-
//# debugId=
|
|
183
|
+
//# debugId=44746568854B06D364756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/vcs/rules.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { matchGlobPath } from \"./match.cjs\";\nimport type { VCSAttributeRule, VCSResolvedAttributes } from \"./types.cjs\";\n\ninterface VCSRulesConfig {\n internalPath?: string;\n internalDirName?: string;\n ignore?: string[];\n attributes?: VCSAttributeRule[];\n}\n\nexport class VCSRules {\n private readonly internalPath: string;\n private readonly ignorePatterns: string[];\n private readonly attributeRules: VCSAttributeRule[];\n\n constructor(config: VCSRulesConfig = {}) {\n this.internalPath = normalizePath(config.internalPath ?? config.internalDirName ?? \"\");\n this.ignorePatterns = [...(config.ignore ?? [])];\n this.attributeRules = [...(config.attributes ?? [])];\n }\n\n isInternalPath(relPath: string): boolean {\n if (!this.internalPath) return false;\n const normalizedPath = normalizePath(relPath);\n if (!normalizedPath) return false;\n return normalizedPath === this.internalPath || normalizedPath.startsWith(`${this.internalPath}/`);\n }\n\n isIgnored(relPath: string): boolean {\n if (this.isInternalPath(relPath)) return true;\n return this.ignorePatterns.some((pattern) => matchVCSPath(pattern, relPath));\n }\n\n shouldEnterDirectory(relPath: string, trackedPaths: Iterable<string>): boolean {\n if (this.isInternalPath(relPath)) return false;\n if (!this.isIgnored(relPath)) return true;\n return hasTrackedPathAtOrBelow(relPath, trackedPaths);\n }\n\n shouldIncludeWorkingFile(relPath: string, trackedPaths: ReadonlySet<string>): boolean {\n if (this.isInternalPath(relPath)) return false;\n if (trackedPaths.has(relPath)) return true;\n return !this.isIgnored(relPath);\n }\n\n shouldIncludeEmptyDirectory(relPath: string, trackedPaths: ReadonlySet<string>): boolean {\n if (this.isInternalPath(relPath)) return false;\n if (trackedPaths.has(relPath)) return true;\n return !this.isIgnored(relPath);\n }\n\n shouldIncludeRestoreScanFile(relPath: string): boolean {\n return !this.isInternalPath(relPath);\n }\n\n shouldPreserveUntrackedIgnored(relPath: string, trackedPaths: ReadonlySet<string>): boolean {\n if (trackedPaths.has(relPath)) return false;\n return this.isIgnored(relPath);\n }\n\n resolveAttributes(relPath: string): VCSResolvedAttributes {\n let binary
|
|
5
|
+
"import { matchGlobPath } from \"./match.cjs\";\nimport type { VCSAttributeRule, VCSResolvedAttributes } from \"./types.cjs\";\n\ninterface VCSRulesConfig {\n internalPath?: string;\n internalDirName?: string;\n ignore?: string[];\n attributes?: VCSAttributeRule[];\n}\n\nexport class VCSRules {\n private readonly internalPath: string;\n private readonly ignorePatterns: string[];\n private readonly attributeRules: VCSAttributeRule[];\n\n constructor(config: VCSRulesConfig = {}) {\n this.internalPath = normalizePath(config.internalPath ?? config.internalDirName ?? \"\");\n this.ignorePatterns = [...(config.ignore ?? [])];\n this.attributeRules = [...(config.attributes ?? [])];\n }\n\n isInternalPath(relPath: string): boolean {\n if (!this.internalPath) return false;\n const normalizedPath = normalizePath(relPath);\n if (!normalizedPath) return false;\n return normalizedPath === this.internalPath || normalizedPath.startsWith(`${this.internalPath}/`);\n }\n\n isIgnored(relPath: string): boolean {\n if (this.isInternalPath(relPath)) return true;\n return this.ignorePatterns.some((pattern) => matchVCSPath(pattern, relPath));\n }\n\n shouldEnterDirectory(relPath: string, trackedPaths: Iterable<string>): boolean {\n if (this.isInternalPath(relPath)) return false;\n if (!this.isIgnored(relPath)) return true;\n return hasTrackedPathAtOrBelow(relPath, trackedPaths);\n }\n\n shouldIncludeWorkingFile(relPath: string, trackedPaths: ReadonlySet<string>): boolean {\n if (this.isInternalPath(relPath)) return false;\n if (trackedPaths.has(relPath)) return true;\n return !this.isIgnored(relPath);\n }\n\n shouldIncludeEmptyDirectory(relPath: string, trackedPaths: ReadonlySet<string>): boolean {\n if (this.isInternalPath(relPath)) return false;\n if (trackedPaths.has(relPath)) return true;\n return !this.isIgnored(relPath);\n }\n\n shouldIncludeRestoreScanFile(relPath: string): boolean {\n return !this.isInternalPath(relPath);\n }\n\n shouldPreserveUntrackedIgnored(relPath: string, trackedPaths: ReadonlySet<string>): boolean {\n if (trackedPaths.has(relPath)) return false;\n return this.isIgnored(relPath);\n }\n\n resolveAttributes(relPath: string): VCSResolvedAttributes {\n let binary: boolean | undefined;\n let diff: VCSResolvedAttributes[\"diff\"];\n\n for (const rule of this.attributeRules) {\n if (!matchVCSPath(rule.pattern, relPath)) continue;\n if (rule.binary !== undefined) {\n binary = rule.binary;\n }\n if (rule.diff !== undefined) {\n diff = rule.diff;\n }\n }\n\n if (diff === \"binary\") {\n binary = true;\n }\n if (diff === \"text\") {\n binary = false;\n }\n\n return { binary, diff };\n }\n}\n\nexport function matchVCSPath(pattern: string, relPath: string): boolean {\n const normalizedPattern = normalizePattern(pattern);\n const normalizedPath = normalizePath(relPath);\n\n if (!normalizedPattern || !normalizedPath) return false;\n\n if (normalizedPattern.mode === \"root-path\") {\n return matchGlobPath(normalizedPattern.pattern, normalizedPath);\n }\n\n if (normalizedPattern.mode === \"root-segment\") {\n const [firstSegment] = normalizedPath.split(\"/\");\n return firstSegment ? matchGlobPath(normalizedPattern.pattern, firstSegment) : false;\n }\n\n if (normalizedPattern.mode === \"root-prefix\") {\n return (\n matchGlobPath(normalizedPattern.pattern, normalizedPath) ||\n matchGlobPath(`${normalizedPattern.pattern}/**`, normalizedPath)\n );\n }\n\n const segments = normalizedPath.split(\"/\");\n return segments.some((segment) => matchGlobPath(normalizedPattern.pattern, segment));\n}\n\nfunction normalizePath(relPath: string): string {\n return relPath.replace(/\\\\/g, \"/\").replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction normalizePattern(pattern: string): {\n pattern: string;\n mode: \"root-path\" | \"root-prefix\" | \"root-segment\" | \"segment\";\n} | null {\n let normalized = pattern.trim();\n if (!normalized) return null;\n\n normalized = normalized.replace(/\\\\/g, \"/\");\n const anchored = normalized.startsWith(\"/\");\n const directoryOnly = normalized.endsWith(\"/\");\n normalized = normalized.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n if (!normalized) return null;\n\n if (normalized.includes(\"/\")) {\n return {\n pattern: normalized,\n mode: directoryOnly ? \"root-prefix\" : \"root-path\",\n };\n }\n\n if (anchored) {\n return {\n pattern: normalized,\n mode: \"root-segment\",\n };\n }\n\n return {\n pattern: normalized,\n mode: \"segment\",\n };\n}\n\nfunction hasTrackedPathAtOrBelow(relPath: string, trackedPaths: Iterable<string>): boolean {\n const normalizedPath = normalizePath(relPath);\n if (!normalizedPath) return false;\n\n const prefix = normalizedPath + \"/\";\n for (const trackedPath of trackedPaths) {\n const normalizedTrackedPath = normalizePath(trackedPath);\n if (\n normalizedTrackedPath === normalizedPath ||\n normalizedTrackedPath.startsWith(prefix)\n ) {\n return true;\n }\n }\n return false;\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAA8B,IAA9B;AAAA;AAUO,MAAM,SAAS;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,WAAW,CAAC,SAAyB,CAAC,GAAG;AAAA,IACvC,KAAK,eAAe,cAAc,OAAO,gBAAgB,OAAO,mBAAmB,EAAE;AAAA,IACrF,KAAK,iBAAiB,CAAC,GAAI,OAAO,UAAU,CAAC,CAAE;AAAA,IAC/C,KAAK,iBAAiB,CAAC,GAAI,OAAO,cAAc,CAAC,CAAE;AAAA;AAAA,EAGrD,cAAc,CAAC,SAA0B;AAAA,IACvC,IAAI,CAAC,KAAK;AAAA,MAAc,OAAO;AAAA,IAC/B,MAAM,iBAAiB,cAAc,OAAO;AAAA,IAC5C,IAAI,CAAC;AAAA,MAAgB,OAAO;AAAA,IAC5B,OAAO,mBAAmB,KAAK,gBAAgB,eAAe,WAAW,GAAG,KAAK,eAAe;AAAA;AAAA,EAGlG,SAAS,CAAC,SAA0B;AAAA,IAClC,IAAI,KAAK,eAAe,OAAO;AAAA,MAAG,OAAO;AAAA,IACzC,OAAO,KAAK,eAAe,KAAK,CAAC,YAAY,aAAa,SAAS,OAAO,CAAC;AAAA;AAAA,EAG7E,oBAAoB,CAAC,SAAiB,cAAyC;AAAA,IAC7E,IAAI,KAAK,eAAe,OAAO;AAAA,MAAG,OAAO;AAAA,IACzC,IAAI,CAAC,KAAK,UAAU,OAAO;AAAA,MAAG,OAAO;AAAA,IACrC,OAAO,wBAAwB,SAAS,YAAY;AAAA;AAAA,EAGtD,wBAAwB,CAAC,SAAiB,cAA4C;AAAA,IACpF,IAAI,KAAK,eAAe,OAAO;AAAA,MAAG,OAAO;AAAA,IACzC,IAAI,aAAa,IAAI,OAAO;AAAA,MAAG,OAAO;AAAA,IACtC,OAAO,CAAC,KAAK,UAAU,OAAO;AAAA;AAAA,EAGhC,2BAA2B,CAAC,SAAiB,cAA4C;AAAA,IACvF,IAAI,KAAK,eAAe,OAAO;AAAA,MAAG,OAAO;AAAA,IACzC,IAAI,aAAa,IAAI,OAAO;AAAA,MAAG,OAAO;AAAA,IACtC,OAAO,CAAC,KAAK,UAAU,OAAO;AAAA;AAAA,EAGhC,4BAA4B,CAAC,SAA0B;AAAA,IACrD,OAAO,CAAC,KAAK,eAAe,OAAO;AAAA;AAAA,EAGrC,8BAA8B,CAAC,SAAiB,cAA4C;AAAA,IAC1F,IAAI,aAAa,IAAI,OAAO;AAAA,MAAG,OAAO;AAAA,IACtC,OAAO,KAAK,UAAU,OAAO;AAAA;AAAA,EAG/B,iBAAiB,CAAC,SAAwC;AAAA,IACxD,IAAI
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "44746568854B06D364756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -39,17 +39,20 @@ var __export = (target, all) => {
|
|
|
39
39
|
// src/vcs/snapshot.ts
|
|
40
40
|
var exports_snapshot = {};
|
|
41
41
|
__export(exports_snapshot, {
|
|
42
|
+
updateIndexForScopedPaths: () => updateIndexForScopedPaths,
|
|
42
43
|
restoreTree: () => restoreTree,
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
rebuildIndexForManifest: () => rebuildIndexForManifest,
|
|
45
|
+
buildTreeManifest: () => buildTreeManifest
|
|
45
46
|
});
|
|
46
47
|
module.exports = __toCommonJS(exports_snapshot);
|
|
48
|
+
var import_content = require("./content.cjs");
|
|
47
49
|
var import_rules = require("./rules.cjs");
|
|
48
50
|
var import_walk = require("./walk.cjs");
|
|
49
51
|
async function buildTreeManifest(fs, rootPath, options) {
|
|
50
52
|
const manifest = {};
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
+
const nextIndexEntries = {};
|
|
54
|
+
const rules = options.rules ?? new import_rules.VCSRules({ internalDirName: ".vcs" });
|
|
55
|
+
const trackedPaths = new Set(options.trackedPaths ?? []);
|
|
53
56
|
const entries = await import_walk.walkTreeEntries(fs, rootPath, {
|
|
54
57
|
enterDirectory: (relPath) => rules.shouldEnterDirectory(relPath, trackedPaths),
|
|
55
58
|
includeFile: (relPath) => rules.shouldIncludeWorkingFile(relPath, trackedPaths),
|
|
@@ -61,43 +64,37 @@ async function buildTreeManifest(fs, rootPath, options) {
|
|
|
61
64
|
continue;
|
|
62
65
|
}
|
|
63
66
|
const fullPath = fs.resolve(rootPath, entry.path);
|
|
64
|
-
const content = await fs.readFile(fullPath);
|
|
65
|
-
const buf = Buffer.from(content);
|
|
66
|
-
manifest[entry.path] = {
|
|
67
|
-
kind: "file",
|
|
68
|
-
content: buf.toString("base64"),
|
|
69
|
-
size: buf.length
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
return manifest;
|
|
73
|
-
}
|
|
74
|
-
async function buildPartialManifest(fs, rootPath, paths) {
|
|
75
|
-
const manifest = {};
|
|
76
|
-
for (const relPath of paths) {
|
|
77
|
-
const fullPath = fs.resolve(rootPath, relPath);
|
|
78
|
-
if (!await fs.exists(fullPath))
|
|
79
|
-
continue;
|
|
80
67
|
const stat = await fs.stat(fullPath);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
68
|
+
const cached = options.indexEntries?.[entry.path];
|
|
69
|
+
if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs && await options.objectStore.hasBlob(cached.blobId)) {
|
|
70
|
+
const sampleHash = import_content.hashSample(await import_content.readStreamSample(fs.readStream(fullPath)));
|
|
71
|
+
if (sampleHash === cached.sampleHash) {
|
|
72
|
+
manifest[entry.path] = {
|
|
73
|
+
kind: "file",
|
|
74
|
+
blobId: cached.blobId,
|
|
75
|
+
size: cached.size
|
|
76
|
+
};
|
|
77
|
+
nextIndexEntries[entry.path] = cached;
|
|
78
|
+
continue;
|
|
85
79
|
}
|
|
86
|
-
continue;
|
|
87
80
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const content = await fs.readFile(fullPath);
|
|
91
|
-
const buf = Buffer.from(content);
|
|
92
|
-
manifest[relPath] = {
|
|
81
|
+
const stored = await options.objectStore.store(fs.readStream(fullPath));
|
|
82
|
+
manifest[entry.path] = {
|
|
93
83
|
kind: "file",
|
|
94
|
-
|
|
95
|
-
size:
|
|
84
|
+
blobId: stored.blobId,
|
|
85
|
+
size: stored.size
|
|
86
|
+
};
|
|
87
|
+
nextIndexEntries[entry.path] = {
|
|
88
|
+
blobId: stored.blobId,
|
|
89
|
+
size: stored.size,
|
|
90
|
+
mtimeMs: stat.mtimeMs,
|
|
91
|
+
binary: stored.binary,
|
|
92
|
+
sampleHash: stored.sampleHash
|
|
96
93
|
};
|
|
97
94
|
}
|
|
98
|
-
return manifest;
|
|
95
|
+
return { manifest, indexEntries: nextIndexEntries };
|
|
99
96
|
}
|
|
100
|
-
async function restoreTree(fs, rootPath, manifest, options) {
|
|
97
|
+
async function restoreTree(fs, rootPath, manifest, objectStore, options) {
|
|
101
98
|
const fullRestore = options?.fullRestore ?? false;
|
|
102
99
|
const rules = options?.rules ?? new import_rules.VCSRules({ internalDirName: ".vcs" });
|
|
103
100
|
const trackedPaths = new Set(options?.trackedPaths ?? []);
|
|
@@ -132,7 +129,7 @@ async function restoreTree(fs, rootPath, manifest, options) {
|
|
|
132
129
|
await ensureDirectoryExists(fs, fs.resolve(rootPath, relPath));
|
|
133
130
|
continue;
|
|
134
131
|
}
|
|
135
|
-
await writeFileFromEntry(fs, rootPath, relPath, entry);
|
|
132
|
+
await writeFileFromEntry(fs, rootPath, relPath, entry, objectStore);
|
|
136
133
|
}
|
|
137
134
|
if (shouldDeleteExtras) {
|
|
138
135
|
const currentEntries = await import_walk.walkTreeEntries(fs, rootPath, {
|
|
@@ -153,12 +150,65 @@ async function restoreTree(fs, rootPath, manifest, options) {
|
|
|
153
150
|
}
|
|
154
151
|
}
|
|
155
152
|
}
|
|
156
|
-
async function
|
|
153
|
+
async function rebuildIndexForManifest(fs, rootPath, manifest, objectStore) {
|
|
154
|
+
const entries = {};
|
|
155
|
+
for (const [relPath, entry] of Object.entries(manifest)) {
|
|
156
|
+
if (isDirectoryEntry(entry)) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const fullPath = fs.resolve(rootPath, relPath);
|
|
160
|
+
const stat = await fs.stat(fullPath);
|
|
161
|
+
entries[relPath] = {
|
|
162
|
+
blobId: entry.blobId,
|
|
163
|
+
size: entry.size,
|
|
164
|
+
mtimeMs: stat.mtimeMs,
|
|
165
|
+
binary: await objectStore.isBinaryBlob(entry.blobId),
|
|
166
|
+
sampleHash: import_content.hashSample(await import_content.readStreamSample(fs.readStream(fullPath)))
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return entries;
|
|
170
|
+
}
|
|
171
|
+
async function updateIndexForScopedPaths(fs, rootPath, manifest, objectStore, existingIndex, patterns) {
|
|
172
|
+
const nextIndex = { ...existingIndex };
|
|
173
|
+
for (const relPath of Object.keys(existingIndex)) {
|
|
174
|
+
if (isPathInScope(relPath, patterns) && !manifest[relPath]) {
|
|
175
|
+
delete nextIndex[relPath];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const [relPath, entry] of Object.entries(manifest)) {
|
|
179
|
+
if (!isPathInScope(relPath, patterns) || isDirectoryEntry(entry)) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const fullPath = fs.resolve(rootPath, relPath);
|
|
183
|
+
if (!await fs.exists(fullPath)) {
|
|
184
|
+
delete nextIndex[relPath];
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const stat = await fs.stat(fullPath);
|
|
188
|
+
nextIndex[relPath] = {
|
|
189
|
+
blobId: entry.blobId,
|
|
190
|
+
size: entry.size,
|
|
191
|
+
mtimeMs: stat.mtimeMs,
|
|
192
|
+
binary: await objectStore.isBinaryBlob(entry.blobId),
|
|
193
|
+
sampleHash: import_content.hashSample(await import_content.readStreamSample(fs.readStream(fullPath)))
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return nextIndex;
|
|
197
|
+
}
|
|
198
|
+
async function writeFileFromEntry(fs, rootPath, relPath, entry, objectStore) {
|
|
157
199
|
const fullPath = fs.resolve(rootPath, relPath);
|
|
158
200
|
await ensureDirectoryExists(fs, fs.dirname(fullPath));
|
|
159
201
|
await removeDirectoryAtPath(fs, fullPath);
|
|
160
|
-
const
|
|
161
|
-
|
|
202
|
+
const writer = await fs.writeStream(fullPath);
|
|
203
|
+
try {
|
|
204
|
+
for await (const chunk of objectStore.readBlobStream(entry.blobId)) {
|
|
205
|
+
await writer.write(chunk);
|
|
206
|
+
}
|
|
207
|
+
await writer.close();
|
|
208
|
+
} catch (error) {
|
|
209
|
+
await writer.abort?.(error);
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
162
212
|
}
|
|
163
213
|
function isDirectoryEntry(entry) {
|
|
164
214
|
return entry.kind === "directory";
|
|
@@ -225,4 +275,4 @@ async function isEmptyDirectory(fs, dirPath) {
|
|
|
225
275
|
}
|
|
226
276
|
}
|
|
227
277
|
|
|
228
|
-
//# debugId=
|
|
278
|
+
//# debugId=7BF3A16CF496D89964756E2164756E21
|