just-git 0.1.7 → 0.1.9
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 +55 -8
- package/dist/index.d.ts +75 -1
- package/dist/index.js +290 -296
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://github.com/blindmansion/just-git/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/just-git)
|
|
5
5
|
|
|
6
|
-
Git implementation for virtual bash environments (particularly [just-bash](https://github.com/vercel-labs/just-bash)). Pure TypeScript, zero dependencies. Works in Node, Bun, Deno, and the browser. ~100 kB gzipped.
|
|
6
|
+
Git implementation for virtual bash environments (particularly [just-bash](https://github.com/vercel-labs/just-bash)). Pure TypeScript, zero dependencies. 34 commands implemented. Works in Node, Bun, Deno, and the browser. ~100 kB gzipped.
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
@@ -37,12 +37,13 @@ await bash.exec("git log --oneline");
|
|
|
37
37
|
|
|
38
38
|
`createGit(options?)` accepts:
|
|
39
39
|
|
|
40
|
-
| Option
|
|
41
|
-
|
|
|
42
|
-
| `identity`
|
|
43
|
-
| `credentials`
|
|
44
|
-
| `disabled`
|
|
45
|
-
| `network`
|
|
40
|
+
| Option | Description |
|
|
41
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
42
|
+
| `identity` | Author/committer override. With `locked: true`, always wins over env vars and git config. Without `locked`, acts as a fallback. |
|
|
43
|
+
| `credentials` | `(url) => HttpAuth \| null` callback for Smart HTTP transport auth. |
|
|
44
|
+
| `disabled` | `GitCommandName[]` of subcommands to block (e.g. `["push", "rebase"]`). |
|
|
45
|
+
| `network` | `{ allowed?: string[], fetch?: FetchFunction }` to restrict HTTP access and/or provide a custom `fetch` implementation. Set to `false` to block all network access. |
|
|
46
|
+
| `resolveRemote` | `(url) => GitContext \| null` callback for cross-VFS remote resolution. See [Multi-agent collaboration](#multi-agent-collaboration). |
|
|
46
47
|
|
|
47
48
|
```ts
|
|
48
49
|
const git = createGit({
|
|
@@ -177,9 +178,55 @@ Fire-and-forget events emitted on every object/ref write. Handler errors are cau
|
|
|
177
178
|
| `ref:delete` | `{ ref, oldHash }` |
|
|
178
179
|
| `object:write` | `{ type, hash }` |
|
|
179
180
|
|
|
181
|
+
## Multi-agent collaboration
|
|
182
|
+
|
|
183
|
+
Multiple agents can work on clones of the same repository in the same process, each with full VFS isolation. The `resolveRemote` option maps remote URLs to `GitContext` instances on other virtual filesystems, so clone/fetch/push/pull cross VFS boundaries without any network or shared filesystem.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
import { Bash, InMemoryFs } from "just-bash";
|
|
187
|
+
import { createGit, findGitDir } from "just-git";
|
|
188
|
+
|
|
189
|
+
// Origin repo on its own filesystem
|
|
190
|
+
const originFs = new InMemoryFs();
|
|
191
|
+
const setupBash = new Bash({
|
|
192
|
+
fs: originFs,
|
|
193
|
+
cwd: "/repo",
|
|
194
|
+
customCommands: [
|
|
195
|
+
createGit({ identity: { name: "Setup", email: "setup@example.com", locked: true } }),
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
await setupBash.exec("git init");
|
|
199
|
+
await setupBash.exec("echo 'hello' > README.md");
|
|
200
|
+
await setupBash.exec("git add . && git commit -m 'initial'");
|
|
201
|
+
|
|
202
|
+
const originCtx = await findGitDir(originFs, "/repo");
|
|
203
|
+
|
|
204
|
+
// Each agent gets its own filesystem + resolveRemote pointing to origin
|
|
205
|
+
function createAgent(name: string, email: string) {
|
|
206
|
+
const agentFs = new InMemoryFs();
|
|
207
|
+
const git = createGit({
|
|
208
|
+
identity: { name, email, locked: true },
|
|
209
|
+
resolveRemote: (url) => (url === "/origin" ? originCtx : null),
|
|
210
|
+
});
|
|
211
|
+
return new Bash({ fs: agentFs, cwd: "/repo", customCommands: [git] });
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const alice = createAgent("Alice", "alice@example.com");
|
|
215
|
+
const bob = createAgent("Bob", "bob@example.com");
|
|
216
|
+
|
|
217
|
+
await alice.exec("git clone /origin /repo", { cwd: "/" });
|
|
218
|
+
await bob.exec("git clone /origin /repo", { cwd: "/" });
|
|
219
|
+
|
|
220
|
+
// Alice and Bob work independently, push to origin, fetch each other's changes
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Concurrent pushes to the same remote are automatically serialized — if two agents push simultaneously, one succeeds and the other gets a proper non-fast-forward rejection, just like real git.
|
|
224
|
+
|
|
225
|
+
See [`examples/multi-agent.ts`](examples/multi-agent.ts) for a full working example with a coordinator agent that merges feature branches.
|
|
226
|
+
|
|
180
227
|
## Command coverage
|
|
181
228
|
|
|
182
|
-
|
|
229
|
+
See [CLI.md](CLI.md) for full usage details.
|
|
183
230
|
|
|
184
231
|
| Command | Flags / options |
|
|
185
232
|
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
package/dist/index.d.ts
CHANGED
|
@@ -28,10 +28,37 @@ interface FileSystem {
|
|
|
28
28
|
symlink?(target: string, path: string): Promise<void>;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Git object storage: compressed loose objects for new writes, with
|
|
33
|
+
* retained packfiles from fetch/clone. Reads check loose first,
|
|
34
|
+
* then fall back to pack indices.
|
|
35
|
+
*/
|
|
36
|
+
declare class PackedObjectStore {
|
|
37
|
+
private fs;
|
|
38
|
+
private gitDir;
|
|
39
|
+
private hooks?;
|
|
40
|
+
private packs;
|
|
41
|
+
private loadedPackNames;
|
|
42
|
+
private discoverPromise;
|
|
43
|
+
constructor(fs: FileSystem, gitDir: string, hooks?: HookEmitter | undefined);
|
|
44
|
+
write(type: ObjectType, content: Uint8Array): Promise<ObjectId>;
|
|
45
|
+
read(hash: ObjectId): Promise<RawObject>;
|
|
46
|
+
exists(hash: ObjectId): Promise<boolean>;
|
|
47
|
+
ingestPack(packData: Uint8Array): Promise<number>;
|
|
48
|
+
/** Scan `.git/objects/pack/` for existing pack/idx pairs. */
|
|
49
|
+
private discover;
|
|
50
|
+
private doDiscover;
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
/** 40-character lowercase hex SHA-1 hash. */
|
|
32
54
|
type ObjectId = string;
|
|
33
55
|
/** The four Git object types. */
|
|
34
56
|
type ObjectType = "blob" | "tree" | "commit" | "tag";
|
|
57
|
+
/** An object as stored in .git/objects — type + raw content bytes. */
|
|
58
|
+
interface RawObject {
|
|
59
|
+
type: ObjectType;
|
|
60
|
+
content: Uint8Array;
|
|
61
|
+
}
|
|
35
62
|
/** Author or committer identity with timestamp. */
|
|
36
63
|
interface Identity {
|
|
37
64
|
name: string;
|
|
@@ -68,6 +95,32 @@ interface Index {
|
|
|
68
95
|
version: number;
|
|
69
96
|
entries: IndexEntry[];
|
|
70
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Bundles the filesystem handle with resolved repository paths.
|
|
100
|
+
* Threaded through all library functions so they don't need to
|
|
101
|
+
* re-discover the .git directory on every call.
|
|
102
|
+
*/
|
|
103
|
+
interface GitContext {
|
|
104
|
+
fs: FileSystem;
|
|
105
|
+
/** Absolute path to the .git directory. */
|
|
106
|
+
gitDir: string;
|
|
107
|
+
/** Absolute path to the working tree root, or null for bare repos. */
|
|
108
|
+
workTree: string | null;
|
|
109
|
+
/** Hook emitter for operation hooks and low-level events. */
|
|
110
|
+
hooks?: HookEmitter;
|
|
111
|
+
/** Operator-provided credential resolver (bypasses env vars). */
|
|
112
|
+
credentialProvider?: CredentialProvider;
|
|
113
|
+
/** Operator-provided identity override for author/committer. */
|
|
114
|
+
identityOverride?: IdentityOverride;
|
|
115
|
+
/** Custom fetch function for HTTP transport. Falls back to globalThis.fetch. */
|
|
116
|
+
fetchFn?: FetchFunction;
|
|
117
|
+
/** Network access policy. `false` blocks all HTTP access. */
|
|
118
|
+
networkPolicy?: NetworkPolicy | false;
|
|
119
|
+
/** Resolves remote URLs to GitContexts on potentially different VFS instances. */
|
|
120
|
+
resolveRemote?: RemoteResolver;
|
|
121
|
+
/** Cached object store instance. Lazily created by object-db. */
|
|
122
|
+
objectStore?: PackedObjectStore;
|
|
123
|
+
}
|
|
71
124
|
|
|
72
125
|
type HttpAuth = {
|
|
73
126
|
type: "basic";
|
|
@@ -90,6 +143,12 @@ interface IdentityOverride {
|
|
|
90
143
|
email: string;
|
|
91
144
|
locked?: boolean;
|
|
92
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Resolves a remote URL to a GitContext, enabling cross-VFS transport.
|
|
148
|
+
* Called before local filesystem lookup for non-HTTP URLs.
|
|
149
|
+
* Return null to fall back to local filesystem resolution.
|
|
150
|
+
*/
|
|
151
|
+
type RemoteResolver = (url: string) => GitContext | null | Promise<GitContext | null>;
|
|
93
152
|
type FetchFunction = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
94
153
|
interface NetworkPolicy {
|
|
95
154
|
/**
|
|
@@ -366,6 +425,12 @@ interface GitOptions {
|
|
|
366
425
|
disabled?: GitCommandName[];
|
|
367
426
|
/** Network policy. Set to `false` to block all HTTP access. */
|
|
368
427
|
network?: NetworkPolicy | false;
|
|
428
|
+
/**
|
|
429
|
+
* Resolve a remote URL to a GitContext on a potentially different VFS.
|
|
430
|
+
* Called before local filesystem lookup for non-HTTP remote URLs.
|
|
431
|
+
* Return null to fall back to local filesystem resolution.
|
|
432
|
+
*/
|
|
433
|
+
resolveRemote?: RemoteResolver;
|
|
369
434
|
}
|
|
370
435
|
/**
|
|
371
436
|
* Bundle of operator-level extensions threaded into command handlers
|
|
@@ -377,6 +442,7 @@ interface GitExtensions {
|
|
|
377
442
|
identityOverride?: IdentityOverride;
|
|
378
443
|
fetchFn?: FetchFunction;
|
|
379
444
|
networkPolicy?: NetworkPolicy | false;
|
|
445
|
+
resolveRemote?: RemoteResolver;
|
|
380
446
|
}
|
|
381
447
|
declare class Git {
|
|
382
448
|
readonly name = "git";
|
|
@@ -392,4 +458,12 @@ declare class Git {
|
|
|
392
458
|
}
|
|
393
459
|
declare function createGit(options?: GitOptions): Git;
|
|
394
460
|
|
|
395
|
-
|
|
461
|
+
/**
|
|
462
|
+
* Walk up from `startPath` looking for a git repository.
|
|
463
|
+
* Checks for both normal repos (`.git/` subdirectory) and bare repos
|
|
464
|
+
* (`HEAD` + `objects/` + `refs/` directly in the directory).
|
|
465
|
+
* Returns a GitContext if found, null otherwise.
|
|
466
|
+
*/
|
|
467
|
+
declare function findGitDir(fs: FileSystem, startPath: string): Promise<GitContext | null>;
|
|
468
|
+
|
|
469
|
+
export { type AbortResult, type CommandContext, type CommandEvent, type CommandExecOptions, type CommitMsgEvent, type CredentialProvider, type ExecResult, type FetchFunction, type FileStat, type FileSystem, Git, type GitCommandName, type GitContext, type GitExtensions, type GitOptions, type HookEventMap, type HookHandler, type IdentityOverride, type MergeMsgEvent, type Middleware, type NetworkPolicy, type ObjectWriteEvent, type PostCheckoutEvent, type PostCherryPickEvent, type PostCleanEvent, type PostCloneEvent, type PostCommitEvent, type PostFetchEvent, type PostMergeEvent, type PostPullEvent, type PostPushEvent, type PostResetEvent, type PostRevertEvent, type PostRmEvent, type PostStashEvent, type PreCheckoutEvent, type PreCherryPickEvent, type PreCleanEvent, type PreCloneEvent, type PreCommitEvent, type PreFetchEvent, type PreMergeCommitEvent, type PrePullEvent, type PrePushEvent, type PreRebaseEvent, type PreResetEvent, type PreRevertEvent, type PreRmEvent, type PreStashEvent, type RefDeleteEvent, type RefUpdateEvent, type RemoteResolver, createGit, findGitDir };
|