shell-dsl 0.0.32 → 0.0.34
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 +130 -0
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/index.cjs +3 -1
- package/dist/cjs/src/index.cjs.map +3 -3
- package/dist/cjs/src/vcs/diff.cjs +107 -0
- package/dist/cjs/src/vcs/diff.cjs.map +10 -0
- package/dist/cjs/src/vcs/index.cjs +47 -0
- package/dist/cjs/src/vcs/index.cjs.map +10 -0
- package/dist/cjs/src/vcs/match.cjs +106 -0
- package/dist/cjs/src/vcs/match.cjs.map +10 -0
- package/dist/cjs/src/vcs/rules.cjs +180 -0
- package/dist/cjs/src/vcs/rules.cjs.map +10 -0
- package/dist/cjs/src/vcs/snapshot.cjs +228 -0
- package/dist/cjs/src/vcs/snapshot.cjs.map +10 -0
- package/dist/cjs/src/vcs/storage.cjs +120 -0
- package/dist/cjs/src/vcs/storage.cjs.map +10 -0
- package/dist/cjs/src/vcs/types.cjs +30 -0
- package/dist/cjs/src/vcs/types.cjs.map +9 -0
- package/dist/cjs/src/vcs/vcs.cjs +322 -0
- package/dist/cjs/src/vcs/vcs.cjs.map +10 -0
- package/dist/cjs/src/vcs/walk.cjs +89 -0
- package/dist/cjs/src/vcs/walk.cjs.map +10 -0
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/index.mjs +3 -1
- package/dist/mjs/src/index.mjs.map +3 -3
- package/dist/mjs/src/vcs/diff.mjs +67 -0
- package/dist/mjs/src/vcs/diff.mjs.map +10 -0
- package/dist/mjs/src/vcs/index.mjs +7 -0
- package/dist/mjs/src/vcs/index.mjs.map +10 -0
- package/dist/mjs/src/vcs/match.mjs +66 -0
- package/dist/mjs/src/vcs/match.mjs.map +10 -0
- package/dist/mjs/src/vcs/rules.mjs +140 -0
- package/dist/mjs/src/vcs/rules.mjs.map +10 -0
- package/dist/mjs/src/vcs/snapshot.mjs +188 -0
- package/dist/mjs/src/vcs/snapshot.mjs.map +10 -0
- package/dist/mjs/src/vcs/storage.mjs +79 -0
- package/dist/mjs/src/vcs/storage.mjs.map +10 -0
- package/dist/mjs/src/vcs/types.mjs +2 -0
- package/dist/mjs/src/vcs/types.mjs.map +9 -0
- package/dist/mjs/src/vcs/vcs.mjs +282 -0
- package/dist/mjs/src/vcs/vcs.mjs.map +10 -0
- package/dist/mjs/src/vcs/walk.mjs +49 -0
- package/dist/mjs/src/vcs/walk.mjs.map +10 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/vcs/diff.d.ts +11 -0
- package/dist/types/src/vcs/index.d.ts +2 -0
- package/dist/types/src/vcs/match.d.ts +5 -0
- package/dist/types/src/vcs/rules.d.ts +23 -0
- package/dist/types/src/vcs/snapshot.d.ts +26 -0
- package/dist/types/src/vcs/storage.d.ts +22 -0
- package/dist/types/src/vcs/types.d.ts +99 -0
- package/dist/types/src/vcs/vcs.d.ts +35 -0
- package/dist/types/src/vcs/walk.d.ts +19 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ bun add shell-dsl memfs
|
|
|
36
36
|
- **Automatic escaping** — Interpolated values are escaped by default for safety
|
|
37
37
|
- **POSIX-inspired syntax** — Pipes, redirects, control flow operators, and more
|
|
38
38
|
- **Streaming pipelines** — Commands communicate via async iteration
|
|
39
|
+
- **Version control** — Built-in VCS with commits, branches, checkout, and diffs on any virtual filesystem
|
|
39
40
|
- **TypeScript-first** — Full type definitions included
|
|
40
41
|
|
|
41
42
|
## Getting Started
|
|
@@ -745,6 +746,130 @@ const fs = new FileSystem("/", {}, createWebUnderlyingFS(root));
|
|
|
745
746
|
```
|
|
746
747
|
|
|
747
748
|
|
|
749
|
+
## Version Control
|
|
750
|
+
|
|
751
|
+
`VersionControlSystem` adds git-like version control to any `VirtualFS`. It tracks changes as diffs, supports branching, and stores metadata in a `.vcs` directory.
|
|
752
|
+
|
|
753
|
+
Ignore and attribute rules are configured directly on the constructor:
|
|
754
|
+
|
|
755
|
+
```ts
|
|
756
|
+
import { VersionControlSystem, createVirtualFS } from "shell-dsl";
|
|
757
|
+
import { createFsFromVolume, Volume } from "memfs";
|
|
758
|
+
|
|
759
|
+
const vol = new Volume();
|
|
760
|
+
vol.fromJSON({
|
|
761
|
+
"/project/src/index.ts": 'console.log("hello")',
|
|
762
|
+
"/project/README.md": "# My Project",
|
|
763
|
+
});
|
|
764
|
+
const fs = createVirtualFS(createFsFromVolume(vol));
|
|
765
|
+
|
|
766
|
+
const vcs = new VersionControlSystem({
|
|
767
|
+
fs,
|
|
768
|
+
path: "/project",
|
|
769
|
+
ignore: ["dist", "*.log"],
|
|
770
|
+
attributes: [
|
|
771
|
+
{ pattern: "assets/*.png", diff: "binary" },
|
|
772
|
+
{ pattern: "secrets/**", diff: "none" },
|
|
773
|
+
],
|
|
774
|
+
});
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
Ignore patterns apply only to untracked paths:
|
|
778
|
+
|
|
779
|
+
- Ignored untracked files are skipped by `status()` and full `commit()`
|
|
780
|
+
- Files already tracked by VCS remain tracked even if they later match an ignore rule
|
|
781
|
+
- Full `checkout()` preserves ignored untracked files
|
|
782
|
+
|
|
783
|
+
Attribute rules are applied in declaration order, with later matches winning. Supported properties:
|
|
784
|
+
|
|
785
|
+
- `binary?: boolean`
|
|
786
|
+
- `diff?: "text" | "binary" | "none"`
|
|
787
|
+
|
|
788
|
+
### Committing Changes
|
|
789
|
+
|
|
790
|
+
```ts
|
|
791
|
+
// Commit all pending changes
|
|
792
|
+
const rev = await vcs.commit("initial commit");
|
|
793
|
+
|
|
794
|
+
// Selective commit with glob patterns (relative to root path)
|
|
795
|
+
await vcs.commit("update src only", { paths: ["/src/**"] });
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
### Checking Status
|
|
799
|
+
|
|
800
|
+
`status()` returns a `DiffEntry[]` describing uncommitted changes:
|
|
801
|
+
|
|
802
|
+
```ts
|
|
803
|
+
const changes = await vcs.status();
|
|
804
|
+
for (const entry of changes) {
|
|
805
|
+
console.log(entry.type, entry.path, entry.diff, entry.binary);
|
|
806
|
+
// "add" | "modify" | "delete", "text" | "binary" | "none", boolean
|
|
807
|
+
}
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
When `diff` is `"none"`, the entry still reports the path and change type, but omits `content` and `previousContent`.
|
|
811
|
+
|
|
812
|
+
### Checkout
|
|
813
|
+
|
|
814
|
+
```ts
|
|
815
|
+
// Checkout a specific revision (errors if working tree is dirty)
|
|
816
|
+
await vcs.checkout(1);
|
|
817
|
+
|
|
818
|
+
// Force checkout, discarding uncommitted changes
|
|
819
|
+
await vcs.checkout(1, { force: true });
|
|
820
|
+
|
|
821
|
+
// Partial checkout — restore specific files without changing HEAD
|
|
822
|
+
await vcs.checkout(1, { paths: ["/src/index.ts", "/**/*.txt"] });
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
### Branching
|
|
826
|
+
|
|
827
|
+
```ts
|
|
828
|
+
// Create a branch at HEAD
|
|
829
|
+
await vcs.branch("feature");
|
|
830
|
+
|
|
831
|
+
// Switch to a branch
|
|
832
|
+
await vcs.checkout("feature");
|
|
833
|
+
|
|
834
|
+
// List all branches
|
|
835
|
+
const branches = await vcs.branches();
|
|
836
|
+
// [{ name: "main", revision: 1, current: false },
|
|
837
|
+
// { name: "feature", revision: 1, current: true }]
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
### History and Diffs
|
|
841
|
+
|
|
842
|
+
```ts
|
|
843
|
+
// Revision history
|
|
844
|
+
const entries = await vcs.log();
|
|
845
|
+
const filtered = await vcs.log({ path: "src/index.ts", limit: 10 });
|
|
846
|
+
|
|
847
|
+
// Diff between two revisions
|
|
848
|
+
const diff = await vcs.diff(1, 2);
|
|
849
|
+
for (const entry of diff) {
|
|
850
|
+
console.log(entry.type, entry.path, entry.diff);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Current HEAD info
|
|
854
|
+
const head = await vcs.head();
|
|
855
|
+
// { branch: "main", revision: 2 }
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
### Separate VCS Storage
|
|
859
|
+
|
|
860
|
+
By default, metadata lives in `{path}/.vcs`. You can store it on a different filesystem:
|
|
861
|
+
|
|
862
|
+
```ts
|
|
863
|
+
const vcs = new VersionControlSystem({
|
|
864
|
+
fs: workingTreeFs,
|
|
865
|
+
path: "/project",
|
|
866
|
+
vcsPath: {
|
|
867
|
+
fs: metadataFs, // different VirtualFS instance
|
|
868
|
+
path: "/meta/.vcs", // custom location
|
|
869
|
+
},
|
|
870
|
+
});
|
|
871
|
+
```
|
|
872
|
+
|
|
748
873
|
## Low-Level API
|
|
749
874
|
|
|
750
875
|
For advanced use cases (custom tooling, AST inspection):
|
|
@@ -809,6 +934,11 @@ import type {
|
|
|
809
934
|
Permission,
|
|
810
935
|
PermissionRules,
|
|
811
936
|
UnderlyingFS,
|
|
937
|
+
VCSConfig,
|
|
938
|
+
Revision,
|
|
939
|
+
DiffEntry,
|
|
940
|
+
LogEntry,
|
|
941
|
+
BranchInfo,
|
|
812
942
|
} from "shell-dsl";
|
|
813
943
|
```
|
|
814
944
|
|
package/dist/cjs/package.json
CHANGED
package/dist/cjs/src/index.cjs
CHANGED
|
@@ -70,6 +70,7 @@ __export(exports_src, {
|
|
|
70
70
|
createShellDSL: () => import_shell_dsl.createShellDSL,
|
|
71
71
|
createPipe: () => import_io2.createPipe,
|
|
72
72
|
WebFileSystem: () => import_fs2.WebFileSystem,
|
|
73
|
+
VersionControlSystem: () => import_vcs.VersionControlSystem,
|
|
73
74
|
StdinImpl: () => import_io.StdinImpl,
|
|
74
75
|
ShellPromise: () => import_shell_promise.ShellPromise,
|
|
75
76
|
ShellError: () => import_errors.ShellError,
|
|
@@ -100,5 +101,6 @@ var import_fs2 = require("./fs/index.cjs");
|
|
|
100
101
|
var import_io = require("./io/index.cjs");
|
|
101
102
|
var import_io2 = require("./io/index.cjs");
|
|
102
103
|
var import_utils = require("./utils/index.cjs");
|
|
104
|
+
var import_vcs = require("./vcs/index.cjs");
|
|
103
105
|
|
|
104
|
-
//# debugId=
|
|
106
|
+
//# debugId=27F0973A44539CA064756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.cjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.cjs\";\n\n// Types\nexport type {\n VirtualFS,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.cjs\";\nexport { isRawValue } from \"./types.cjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.cjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.cjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.cjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.cjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n LiteralNode,\n VariableNode,\n SubstitutionNode,\n GlobNode,\n ConcatNode,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n ArithmeticNode,\n} from \"./parser/index.cjs\";\nexport {\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isLiteralNode,\n isVariableNode,\n isSubstitutionNode,\n isGlobNode,\n isConcatNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n isArithmeticNode,\n} from \"./parser/index.cjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter/index.cjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.cjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.cjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.cjs\";\nexport { createStdout, createStderr, createPipe, OutputCollectorImpl, PipeBuffer } from \"./io/index.cjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation, globVirtualFS } from \"./utils/index.cjs\";\nexport type { GlobVirtualFS, GlobOptions } from \"./utils/index.cjs\";\n"
|
|
5
|
+
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.cjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.cjs\";\n\n// Types\nexport type {\n VirtualFS,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.cjs\";\nexport { isRawValue } from \"./types.cjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.cjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.cjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.cjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.cjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n LiteralNode,\n VariableNode,\n SubstitutionNode,\n GlobNode,\n ConcatNode,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n ArithmeticNode,\n} from \"./parser/index.cjs\";\nexport {\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isLiteralNode,\n isVariableNode,\n isSubstitutionNode,\n isGlobNode,\n isConcatNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n isArithmeticNode,\n} from \"./parser/index.cjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter/index.cjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.cjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.cjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.cjs\";\nexport { createStdout, createStderr, createPipe, OutputCollectorImpl, PipeBuffer } from \"./io/index.cjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation, globVirtualFS } from \"./utils/index.cjs\";\nexport type { GlobVirtualFS, GlobOptions } from \"./utils/index.cjs\";\n\n// Version Control\nexport { VersionControlSystem } from \"./vcs/index.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 \"./vcs/index.cjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACuD,IAAvD;AACuD,IAAvD;AAgB2B,IAA3B;AAGiD,IAAjD;AAG0C,IAA1C;AAI8B,IAA9B;AAuCO,IAjBP;AAoBwF,IAAxF;AAGgC,IAAhC;AAUO,IATP;AAYuC,IAAvC;AACwF,IAAxF;AAG8D,IAA9D;AAIqC,IAArC;",
|
|
8
|
+
"debugId": "27F0973A44539CA064756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
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/diff.ts
|
|
40
|
+
var exports_diff = {};
|
|
41
|
+
__export(exports_diff, {
|
|
42
|
+
diffWorkingTree: () => diffWorkingTree,
|
|
43
|
+
diffManifests: () => diffManifests
|
|
44
|
+
});
|
|
45
|
+
module.exports = __toCommonJS(exports_diff);
|
|
46
|
+
var import_rules = require("./rules.cjs");
|
|
47
|
+
var import_snapshot = require("./snapshot.cjs");
|
|
48
|
+
function diffManifests(before, after, rules = new import_rules.VCSRules) {
|
|
49
|
+
const entries = [];
|
|
50
|
+
const allPaths = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
51
|
+
for (const path of allPaths) {
|
|
52
|
+
const prev = before[path];
|
|
53
|
+
const curr = after[path];
|
|
54
|
+
if (!prev && curr) {
|
|
55
|
+
entries.push(createDiffEntry("add", path, curr, undefined, rules));
|
|
56
|
+
} else if (prev && !curr) {
|
|
57
|
+
entries.push(createDiffEntry("delete", path, undefined, prev, rules));
|
|
58
|
+
} else if (prev && curr && !entriesEqual(prev, curr)) {
|
|
59
|
+
entries.push(createDiffEntry("modify", path, curr, prev, rules));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
63
|
+
}
|
|
64
|
+
async function diffWorkingTree(fs, rootPath, manifest, rules = new import_rules.VCSRules({ internalDirName: ".vcs" })) {
|
|
65
|
+
const workingManifest = await import_snapshot.buildTreeManifest(fs, rootPath, {
|
|
66
|
+
rules,
|
|
67
|
+
trackedPaths: Object.keys(manifest)
|
|
68
|
+
});
|
|
69
|
+
return diffManifests(manifest, workingManifest, rules);
|
|
70
|
+
}
|
|
71
|
+
function createDiffEntry(type, path, current, previous, rules) {
|
|
72
|
+
const attributes = rules.resolveAttributes(path);
|
|
73
|
+
const entryKind = getEntryKind(current ?? previous);
|
|
74
|
+
const previousEntryKind = previous ? getEntryKind(previous) : undefined;
|
|
75
|
+
const entry = {
|
|
76
|
+
type,
|
|
77
|
+
path,
|
|
78
|
+
binary: attributes.binary,
|
|
79
|
+
diff: attributes.diff,
|
|
80
|
+
entryKind,
|
|
81
|
+
previousEntryKind
|
|
82
|
+
};
|
|
83
|
+
if (attributes.diff !== "none") {
|
|
84
|
+
if (isFileEntry(current)) {
|
|
85
|
+
entry.content = current.content;
|
|
86
|
+
}
|
|
87
|
+
if (isFileEntry(previous)) {
|
|
88
|
+
entry.previousContent = previous.content;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return entry;
|
|
92
|
+
}
|
|
93
|
+
function entriesEqual(a, b) {
|
|
94
|
+
if (getEntryKind(a) !== getEntryKind(b))
|
|
95
|
+
return false;
|
|
96
|
+
if (!isFileEntry(a) || !isFileEntry(b))
|
|
97
|
+
return true;
|
|
98
|
+
return a.content === b.content;
|
|
99
|
+
}
|
|
100
|
+
function getEntryKind(entry) {
|
|
101
|
+
return entry?.kind === "directory" ? "directory" : "file";
|
|
102
|
+
}
|
|
103
|
+
function isFileEntry(entry) {
|
|
104
|
+
return !!entry && entry.kind !== "directory";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//# debugId=F0849DE3546011FF64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/vcs/diff.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { VirtualFS } from \"../types.cjs\";\nimport type { TreeManifest, DiffEntry, TreeEntry } from \"./types.cjs\";\nimport { VCSRules } from \"./rules.cjs\";\nimport { buildTreeManifest } from \"./snapshot.cjs\";\n\n/**\n * Compute diff entries between two tree manifests.\n */\nexport function diffManifests(\n before: TreeManifest,\n after: TreeManifest,\n rules: VCSRules = new VCSRules(),\n): DiffEntry[] {\n const entries: DiffEntry[] = [];\n const allPaths = new Set([...Object.keys(before), ...Object.keys(after)]);\n\n for (const path of allPaths) {\n const prev = before[path];\n const curr = after[path];\n\n if (!prev && curr) {\n entries.push(createDiffEntry(\"add\", path, curr, undefined, rules));\n } else if (prev && !curr) {\n entries.push(createDiffEntry(\"delete\", path, undefined, prev, rules));\n } else if (prev && curr && !entriesEqual(prev, curr)) {\n entries.push(createDiffEntry(\"modify\", path, curr, prev, rules));\n }\n }\n\n return entries.sort((a, b) => a.path.localeCompare(b.path));\n}\n\n/**\n * Compute diff between a tree manifest and the current working tree.\n */\nexport async function diffWorkingTree(\n fs: VirtualFS,\n rootPath: string,\n manifest: TreeManifest,\n rules: VCSRules = new VCSRules({ internalDirName: \".vcs\" }),\n): Promise<DiffEntry[]> {\n const workingManifest = await buildTreeManifest(fs, rootPath, {\n rules,\n trackedPaths: Object.keys(manifest),\n });\n return diffManifests(manifest, workingManifest, rules);\n}\n\nfunction createDiffEntry(\n type: DiffEntry[\"type\"],\n path: string,\n current: TreeEntry | undefined,\n previous: TreeEntry | undefined,\n rules: VCSRules,\n): DiffEntry {\n const attributes = rules.resolveAttributes(path);\n const entryKind = getEntryKind(current ?? previous);\n const previousEntryKind = previous ? getEntryKind(previous) : undefined;\n const entry: DiffEntry = {\n type,\n path,\n binary: attributes.binary,\n diff: attributes.diff,\n entryKind,\n previousEntryKind,\n };\n\n if (attributes.diff !== \"none\") {\n if (isFileEntry(current)) {\n entry.content = current.content;\n }\n if (isFileEntry(previous)) {\n entry.previousContent = previous.content;\n }\n }\n\n return entry;\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.content === b.content;\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
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEyB,IAAzB;AACkC,IAAlC;AAKO,SAAS,aAAa,CAC3B,QACA,OACA,QAAkB,IAAI,uBACT;AAAA,EACb,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,UAAU;AAAA,IAC3B,MAAM,OAAO,OAAO;AAAA,IACpB,MAAM,OAAO,MAAM;AAAA,IAEnB,IAAI,CAAC,QAAQ,MAAM;AAAA,MACjB,QAAQ,KAAK,gBAAgB,OAAO,MAAM,MAAM,WAAW,KAAK,CAAC;AAAA,IACnE,EAAO,SAAI,QAAQ,CAAC,MAAM;AAAA,MACxB,QAAQ,KAAK,gBAAgB,UAAU,MAAM,WAAW,MAAM,KAAK,CAAC;AAAA,IACtE,EAAO,SAAI,QAAQ,QAAQ,CAAC,aAAa,MAAM,IAAI,GAAG;AAAA,MACpD,QAAQ,KAAK,gBAAgB,UAAU,MAAM,MAAM,MAAM,KAAK,CAAC;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA;AAM5D,eAAsB,eAAe,CACnC,IACA,UACA,UACA,QAAkB,IAAI,sBAAS,EAAE,iBAAiB,OAAO,CAAC,GACpC;AAAA,EACtB,MAAM,kBAAkB,MAAM,kCAAkB,IAAI,UAAU;AAAA,IAC5D;AAAA,IACA,cAAc,OAAO,KAAK,QAAQ;AAAA,EACpC,CAAC;AAAA,EACD,OAAO,cAAc,UAAU,iBAAiB,KAAK;AAAA;AAGvD,SAAS,eAAe,CACtB,MACA,MACA,SACA,UACA,OACW;AAAA,EACX,MAAM,aAAa,MAAM,kBAAkB,IAAI;AAAA,EAC/C,MAAM,YAAY,aAAa,WAAW,QAAQ;AAAA,EAClD,MAAM,oBAAoB,WAAW,aAAa,QAAQ,IAAI;AAAA,EAC9D,MAAM,QAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA,QAAQ,WAAW;AAAA,IACnB,MAAM,WAAW;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,IAAI,WAAW,SAAS,QAAQ;AAAA,IAC9B,IAAI,YAAY,OAAO,GAAG;AAAA,MACxB,MAAM,UAAU,QAAQ;AAAA,IAC1B;AAAA,IACA,IAAI,YAAY,QAAQ,GAAG;AAAA,MACzB,MAAM,kBAAkB,SAAS;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,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,YAAY,EAAE;AAAA;AAGzB,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": "F0849DE3546011FF64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
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/index.ts
|
|
40
|
+
var exports_vcs = {};
|
|
41
|
+
__export(exports_vcs, {
|
|
42
|
+
VersionControlSystem: () => import_vcs.VersionControlSystem
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(exports_vcs);
|
|
45
|
+
var import_vcs = require("./vcs.cjs");
|
|
46
|
+
|
|
47
|
+
//# debugId=882B2013CEEDB5D864756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/vcs/index.ts"],
|
|
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"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAqC,IAArC;",
|
|
8
|
+
"debugId": "882B2013CEEDB5D864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
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/match.ts
|
|
40
|
+
var exports_match = {};
|
|
41
|
+
__export(exports_match, {
|
|
42
|
+
matchGlobPath: () => matchGlobPath
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(exports_match);
|
|
45
|
+
function matchGlobPath(pattern, filePath) {
|
|
46
|
+
const p = pattern.startsWith("/") ? pattern.slice(1) : pattern;
|
|
47
|
+
const f = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
48
|
+
const patternParts = p.split("/");
|
|
49
|
+
const pathParts = f.split("/");
|
|
50
|
+
return matchParts(patternParts, pathParts, 0, 0);
|
|
51
|
+
}
|
|
52
|
+
function matchParts(pattern, path, pi, fi) {
|
|
53
|
+
while (pi < pattern.length && fi < path.length) {
|
|
54
|
+
const seg = pattern[pi];
|
|
55
|
+
if (seg === "**") {
|
|
56
|
+
for (let i = fi;i <= path.length; i++) {
|
|
57
|
+
if (matchParts(pattern, path, pi + 1, i))
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (!matchSegment(seg, path[fi]))
|
|
63
|
+
return false;
|
|
64
|
+
pi++;
|
|
65
|
+
fi++;
|
|
66
|
+
}
|
|
67
|
+
while (pi < pattern.length && pattern[pi] === "**")
|
|
68
|
+
pi++;
|
|
69
|
+
return pi === pattern.length && fi === path.length;
|
|
70
|
+
}
|
|
71
|
+
function matchSegment(pattern, segment) {
|
|
72
|
+
let regex = "^";
|
|
73
|
+
for (let i = 0;i < pattern.length; i++) {
|
|
74
|
+
const c = pattern[i];
|
|
75
|
+
switch (c) {
|
|
76
|
+
case "*":
|
|
77
|
+
regex += "[^/]*";
|
|
78
|
+
break;
|
|
79
|
+
case "?":
|
|
80
|
+
regex += "[^/]";
|
|
81
|
+
break;
|
|
82
|
+
case ".":
|
|
83
|
+
case "^":
|
|
84
|
+
case "$":
|
|
85
|
+
case "+":
|
|
86
|
+
case "{":
|
|
87
|
+
case "}":
|
|
88
|
+
case "(":
|
|
89
|
+
case ")":
|
|
90
|
+
case "|":
|
|
91
|
+
case "\\":
|
|
92
|
+
regex += "\\" + c;
|
|
93
|
+
break;
|
|
94
|
+
default:
|
|
95
|
+
regex += c;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
regex += "$";
|
|
99
|
+
try {
|
|
100
|
+
return new RegExp(regex).test(segment);
|
|
101
|
+
} catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
//# debugId=9C038AE3F1837D4764756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/vcs/match.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Match a file path against a glob pattern.\n * Supports `**` for recursive directory matching, `*` for single segment wildcard.\n */\nexport function matchGlobPath(pattern: string, filePath: string): boolean {\n // Normalize: strip leading slashes\n const p = pattern.startsWith(\"/\") ? pattern.slice(1) : pattern;\n const f = filePath.startsWith(\"/\") ? filePath.slice(1) : filePath;\n\n const patternParts = p.split(\"/\");\n const pathParts = f.split(\"/\");\n\n return matchParts(patternParts, pathParts, 0, 0);\n}\n\nfunction matchParts(\n pattern: string[],\n path: string[],\n pi: number,\n fi: number,\n): boolean {\n while (pi < pattern.length && fi < path.length) {\n const seg = pattern[pi]!;\n\n if (seg === \"**\") {\n // ** matches zero or more path segments\n // Try matching rest of pattern against current position and all subsequent positions\n for (let i = fi; i <= path.length; i++) {\n if (matchParts(pattern, path, pi + 1, i)) return true;\n }\n return false;\n }\n\n if (!matchSegment(seg, path[fi]!)) return false;\n pi++;\n fi++;\n }\n\n // Skip trailing ** patterns\n while (pi < pattern.length && pattern[pi] === \"**\") pi++;\n\n return pi === pattern.length && fi === path.length;\n}\n\nfunction matchSegment(pattern: string, segment: string): boolean {\n // Convert glob segment to regex\n let regex = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const c = pattern[i]!;\n switch (c) {\n case \"*\":\n regex += \"[^/]*\";\n break;\n case \"?\":\n regex += \"[^/]\";\n break;\n case \".\":\n case \"^\":\n case \"$\":\n case \"+\":\n case \"{\":\n case \"}\":\n case \"(\":\n case \")\":\n case \"|\":\n case \"\\\\\":\n regex += \"\\\\\" + c;\n break;\n default:\n regex += c;\n }\n }\n regex += \"$\";\n\n try {\n return new RegExp(regex).test(segment);\n } catch {\n return false;\n }\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIO,SAAS,aAAa,CAAC,SAAiB,UAA2B;AAAA,EAExE,MAAM,IAAI,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AAAA,EACvD,MAAM,IAAI,SAAS,WAAW,GAAG,IAAI,SAAS,MAAM,CAAC,IAAI;AAAA,EAEzD,MAAM,eAAe,EAAE,MAAM,GAAG;AAAA,EAChC,MAAM,YAAY,EAAE,MAAM,GAAG;AAAA,EAE7B,OAAO,WAAW,cAAc,WAAW,GAAG,CAAC;AAAA;AAGjD,SAAS,UAAU,CACjB,SACA,MACA,IACA,IACS;AAAA,EACT,OAAO,KAAK,QAAQ,UAAU,KAAK,KAAK,QAAQ;AAAA,IAC9C,MAAM,MAAM,QAAQ;AAAA,IAEpB,IAAI,QAAQ,MAAM;AAAA,MAGhB,SAAS,IAAI,GAAI,KAAK,KAAK,QAAQ,KAAK;AAAA,QACtC,IAAI,WAAW,SAAS,MAAM,KAAK,GAAG,CAAC;AAAA,UAAG,OAAO;AAAA,MACnD;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,CAAC,aAAa,KAAK,KAAK,GAAI;AAAA,MAAG,OAAO;AAAA,IAC1C;AAAA,IACA;AAAA,EACF;AAAA,EAGA,OAAO,KAAK,QAAQ,UAAU,QAAQ,QAAQ;AAAA,IAAM;AAAA,EAEpD,OAAO,OAAO,QAAQ,UAAU,OAAO,KAAK;AAAA;AAG9C,SAAS,YAAY,CAAC,SAAiB,SAA0B;AAAA,EAE/D,IAAI,QAAQ;AAAA,EACZ,SAAS,IAAI,EAAG,IAAI,QAAQ,QAAQ,KAAK;AAAA,IACvC,MAAM,IAAI,QAAQ;AAAA,IAClB,QAAQ;AAAA,WACD;AAAA,QACH,SAAS;AAAA,QACT;AAAA,WACG;AAAA,QACH,SAAS;AAAA,QACT;AAAA,WACG;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,SAAS,OAAO;AAAA,QAChB;AAAA;AAAA,QAEA,SAAS;AAAA;AAAA,EAEf;AAAA,EACA,SAAS;AAAA,EAET,IAAI;AAAA,IACF,OAAO,IAAI,OAAO,KAAK,EAAE,KAAK,OAAO;AAAA,IACrC,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;",
|
|
8
|
+
"debugId": "9C038AE3F1837D4764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|