just-git 1.3.1 → 1.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.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![npm](https://img.shields.io/npm/v/just-git)](https://www.npmjs.com/package/just-git)
5
5
  [![bundle size](https://img.shields.io/bundlejs/size/just-git)](https://bundlejs.com/?q=just-git)
6
6
 
7
- Pure TypeScript git implementation. Zero dependencies. 35 commands. Works in Node, Bun, Deno, Cloudflare Workers, and the browser. [Tested against real git](docs/TESTING.md) across more than a million randomized operations.
7
+ Pure TypeScript git implementation. Zero dependencies. 36 commands. Works in Node, Bun, Deno, Cloudflare Workers, and the browser. [Tested against real git](docs/TESTING.md) across more than a million randomized operations.
8
8
 
9
9
  Two entry points: a **virtual filesystem client** for sandboxed environments (pairs with [just-bash](https://github.com/vercel-labs/just-bash), or use standalone), and an **[embeddable git server](docs/SERVER.md)** that any standard `git` client can clone, fetch, and push to.
10
10
 
@@ -110,7 +110,7 @@ See [REPO.md](docs/REPO.md) for the full API, the `GitRepo` interface, and the h
110
110
 
111
111
  ## Commands
112
112
 
113
- 35 commands: `init`, `clone`, `fetch`, `push`, `pull`, `add`, `rm`, `mv`, `commit`, `status`, `log`, `show`, `diff`, `grep`, `blame`, `branch`, `tag`, `checkout`, `switch`, `restore`, `reset`, `merge`, `rebase`, `cherry-pick`, `revert`, `stash`, `remote`, `config`, `bisect`, `clean`, `reflog`, `gc`, `repack`, `rev-parse`, `ls-files`. Each implements a subset of real git's flags; see [CLI.md](docs/CLI.md) for details.
113
+ 36 commands: `init`, `clone`, `fetch`, `push`, `pull`, `add`, `rm`, `mv`, `commit`, `status`, `log`, `show`, `diff`, `grep`, `blame`, `describe`, `branch`, `tag`, `checkout`, `switch`, `restore`, `reset`, `merge`, `rebase`, `cherry-pick`, `revert`, `stash`, `remote`, `config`, `bisect`, `clean`, `reflog`, `gc`, `repack`, `rev-parse`, `ls-files`. Each implements a subset of real git's flags; see [CLI.md](docs/CLI.md) for details.
114
114
 
115
115
  ### Transport
116
116
 
@@ -647,4 +647,4 @@ interface GitHooks {
647
647
  */
648
648
  declare function composeGitHooks(...hookSets: (GitHooks | undefined)[]): GitHooks;
649
649
 
650
- export { type Identity as $, type AfterCommandEvent as A, type BeforeCommandEvent as B, type CredentialProvider as C, type PrePullEvent as D, type ExecResult as E, type FileSystem as F, type GitHooks as G, type HttpAuth as H, type IdentityOverride as I, type PrePushEvent as J, type PreRebaseEvent as K, type PreResetEvent as L, type MergeMsgEvent as M, type NetworkPolicy as N, type ObjectStore as O, type PostCheckoutEvent as P, type PreRevertEvent as Q, type RemoteResolver as R, type PreRmEvent as S, type PreStashEvent as T, type RefDeleteEvent as U, type RefEntry as V, type RefUpdateEvent as W, type Rejection as X, composeGitHooks as Y, isRejection as Z, type ObjectId as _, type RefStore as a, type TreeDiffEntry as a0, type Commit as a1, type ObjectType as a2, type RawObject as a3, type PackObject as a4, type Ref as a5, type ConfigOverrides as b, type FileStat as c, type GitContext as d, type CommitMsgEvent as e, type GitRepo as f, type ObjectWriteEvent as g, type PostCherryPickEvent as h, type PostCleanEvent as i, type PostCloneEvent as j, type PostCommitEvent as k, type PostFetchEvent as l, type PostMergeEvent as m, type PostPullEvent as n, type PostPushEvent as o, type PostResetEvent as p, type PostRevertEvent as q, type PostRmEvent as r, type PostStashEvent as s, type PreCheckoutEvent as t, type PreCherryPickEvent as u, type PreCleanEvent as v, type PreCloneEvent as w, type PreCommitEvent as x, type PreFetchEvent as y, type PreMergeCommitEvent as z };
650
+ export { type Ref as $, type AfterCommandEvent as A, type BeforeCommandEvent as B, type CredentialProvider as C, type DirectRef as D, type ExecResult as E, type FileSystem as F, type GitHooks as G, type HttpAuth as H, type IdentityOverride as I, type PreCleanEvent as J, type PreCloneEvent as K, type PreCommitEvent as L, type MergeMsgEvent as M, type NetworkPolicy as N, type ObjectStore as O, type PackObject as P, type PreFetchEvent as Q, type RemoteResolver as R, type PreMergeCommitEvent as S, type PrePullEvent as T, type PrePushEvent as U, type PreRebaseEvent as V, type PreResetEvent as W, type PreRevertEvent as X, type PreRmEvent as Y, type PreStashEvent as Z, type RawObject as _, type RefStore as a, type RefDeleteEvent as a0, type RefEntry as a1, type RefUpdateEvent as a2, type Rejection as a3, type SymbolicRef as a4, composeGitHooks as a5, isRejection as a6, type TreeDiffEntry as a7, type ConfigOverrides as b, type FileStat as c, type GitContext as d, type Commit as e, type CommitMsgEvent as f, type GitRepo as g, type Identity as h, type ObjectId as i, type ObjectType as j, type ObjectWriteEvent as k, type PostCheckoutEvent as l, type PostCherryPickEvent as m, type PostCleanEvent as n, type PostCloneEvent as o, type PostCommitEvent as p, type PostFetchEvent as q, type PostMergeEvent as r, type PostPullEvent as s, type PostPushEvent as t, type PostResetEvent as u, type PostRevertEvent as v, type PostRmEvent as w, type PostStashEvent as x, type PreCheckoutEvent as y, type PreCherryPickEvent as z };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FileSystem, G as GitHooks, C as CredentialProvider, I as IdentityOverride, N as NetworkPolicy, R as RemoteResolver, O as ObjectStore, a as RefStore, b as ConfigOverrides, E as ExecResult, c as FileStat, d as GitContext } from './hooks-BtbyLyYE.js';
2
- export { A as AfterCommandEvent, B as BeforeCommandEvent, e as CommitMsgEvent, f as GitRepo, H as HttpAuth, M as MergeMsgEvent, g as ObjectWriteEvent, P as PostCheckoutEvent, h as PostCherryPickEvent, i as PostCleanEvent, j as PostCloneEvent, k as PostCommitEvent, l as PostFetchEvent, m as PostMergeEvent, n as PostPullEvent, o as PostPushEvent, p as PostResetEvent, q as PostRevertEvent, r as PostRmEvent, s as PostStashEvent, t as PreCheckoutEvent, u as PreCherryPickEvent, v as PreCleanEvent, w as PreCloneEvent, x as PreCommitEvent, y as PreFetchEvent, z as PreMergeCommitEvent, D as PrePullEvent, J as PrePushEvent, K as PreRebaseEvent, L as PreResetEvent, Q as PreRevertEvent, S as PreRmEvent, T as PreStashEvent, U as RefDeleteEvent, V as RefEntry, W as RefUpdateEvent, X as Rejection, Y as composeGitHooks, Z as isRejection } from './hooks-BtbyLyYE.js';
1
+ import { F as FileSystem, G as GitHooks, C as CredentialProvider, I as IdentityOverride, N as NetworkPolicy, R as RemoteResolver, O as ObjectStore, a as RefStore, b as ConfigOverrides, E as ExecResult, c as FileStat, d as GitContext } from './hooks-t3k-y0u_.js';
2
+ export { A as AfterCommandEvent, B as BeforeCommandEvent, e as Commit, f as CommitMsgEvent, D as DirectRef, g as GitRepo, H as HttpAuth, h as Identity, M as MergeMsgEvent, i as ObjectId, j as ObjectType, k as ObjectWriteEvent, P as PackObject, l as PostCheckoutEvent, m as PostCherryPickEvent, n as PostCleanEvent, o as PostCloneEvent, p as PostCommitEvent, q as PostFetchEvent, r as PostMergeEvent, s as PostPullEvent, t as PostPushEvent, u as PostResetEvent, v as PostRevertEvent, w as PostRmEvent, x as PostStashEvent, y as PreCheckoutEvent, z as PreCherryPickEvent, J as PreCleanEvent, K as PreCloneEvent, L as PreCommitEvent, Q as PreFetchEvent, S as PreMergeCommitEvent, T as PrePullEvent, U as PrePushEvent, V as PreRebaseEvent, W as PreResetEvent, X as PreRevertEvent, Y as PreRmEvent, Z as PreStashEvent, _ as RawObject, $ as Ref, a0 as RefDeleteEvent, a1 as RefEntry, a2 as RefUpdateEvent, a3 as Rejection, a4 as SymbolicRef, a5 as composeGitHooks, a6 as isRejection } from './hooks-t3k-y0u_.js';
3
3
 
4
4
  /** Options for subcommand execution (mirrors just-bash's CommandExecOptions). */
5
5
  interface CommandExecOptions {
package/dist/index.js CHANGED
@@ -776,7 +776,7 @@ ${m}`,exitCode:0}}ie();ce();$r();ge();is();function $d(e,t){e.command("tag",{des
776
776
  `)}if(n.list)return Pd(s,n.name||void 0);if(n.name){if(!vc(n.name))return I(`'${n.name}' is not a valid tag name`);let i=n.commit,a;if(i){let d=await wt(s,i,`Failed to resolve '${i}' as a valid ref.`);if(M(d))return d;a=d}else if(a=await Z(s),!a)return I("Failed to resolve 'HEAD' as a valid ref.");let c=`refs/tags/${n.name}`;if(await B(s,c)&&!n.force)return I(`tag '${n.name}' already exists`);if(n.annotate||n.message){if(!n.message)return I("no tag message specified (use -m)");let d=await nt(s,r.env);if(M(d))return d;let m=Mt(n.message),u=$c({type:"tag",object:a,objectType:"commit",name:n.name,tagger:d,message:m}),h=await Ae(s,"tag",u);await X(s,c,h)}else await X(s,c,a);return{stdout:"",stderr:"",exitCode:0}}return Pd(s)}})}async function Pd(e,t){let n=await pe(e,"refs/tags");if(n.length===0)return{stdout:"",stderr:"",exitCode:0};let r=n.map(o=>o.name.replace("refs/tags/",""));return t&&(r=r.filter(o=>on(t,o,0)===0)),r.length===0?{stdout:"",stderr:"",exitCode:0}:{stdout:`${r.join(`
777
777
  `)}
778
778
  `,stderr:"",exitCode:0}}var Od=new Set(["am","annotate","apply","archive","bugreport","bundle","cat-file","check-ignore","check-mailmap","check-ref-format","checkout-index","cherry","commit-tree","count-objects","credential","daemon","diff-files","diff-index","diff-tree","difftool","fast-export","fast-import","filter-branch","for-each-ref","format-patch","fsck","hash-object","instaweb","interpret-trailers","log--hierarchical","ls-remote","ls-tree","maintenance","merge-base","merge-tree","mergetool","multi-pack-index","name-rev","notes","pack-objects","pack-refs","patch-id","prune","range-diff","read-tree","receive-pack","replace","request-pull","rerere","rev-list","send-email","send-pack","shortlog","show-branch","show-ref","sparse-checkout","stash--helper","stripspace","submodule","symbolic-ref","unpack-objects","update-index","update-ref","upload-pack","var","verify-commit","verify-pack","verify-tag","whatchanged","worktree","write-tree"]),Iw={init:(e,t)=>Gl(e,t),clone:(e,t)=>ll(e,t),describe:(e,t)=>ul(e,t),fetch:(e,t)=>Il(e,t),pull:(e,t)=>nd(e,t),push:(e,t)=>rd(e,t),add:(e,t)=>Xc(e,t),blame:(e,t)=>Tf(e,t),commit:(e,t)=>ml(e,t),status:(e,t)=>kd(e,t),log:(e,t)=>Kl(e,t),branch:(e,t)=>Af(e,t),tag:(e,t)=>$d(e,t),checkout:(e,t)=>Mf(e,t),diff:(e,t)=>xl(e,t),reset:(e,t)=>ad(e,t),merge:(e,t)=>Xl(e,t),"cherry-pick":(e,t)=>Yf(e,t),revert:(e,t)=>dd(e,t),rebase:(e,t)=>td(e,t),mv:(e,t)=>Zl(e,t),rm:(e,t)=>ud(e,t),remote:(e,t)=>od(e,t),config:(e,t)=>wl(e,t),show:(e,t)=>md(e,t),stash:(e,t)=>Ed(e,t),"rev-parse":(e,t)=>ld(e,t),"ls-files":(e,t)=>Yl(e,t),clean:(e,t)=>Xf(e,t),switch:(e,t)=>xd(e,t),restore:(e,t)=>fd(e,t),reflog:(e,t)=>sd(e,t),repack:(e,t)=>Tl(e,t),gc:(e,t)=>Hl(e,t),bisect:(e,t)=>wf(e,t),grep:(e,t)=>jl(e,t)};function Id(e){let t=Xo("git",{description:"Git command"});for(let n of Object.values(Iw))n(t,e);return t.command("help",{description:"Display help information",args:[q.string().name("command").describe("Command to get help for").optional()],handler:async n=>{let r=n.command;if(!r)return{stdout:Er(t),stderr:"",exitCode:0};let o=t.children.get(r);return o?{stdout:Er(o),stderr:"",exitCode:0}:{stdout:"",stderr:`git: no help available for '${r}'
779
- `,exitCode:1}}}),t}var Sw="1.3.1";function vw(e,t){if(!e)return t;let n=e.locked?"locked":"defaults",r={"user.name":e.name,"user.email":e.email};return t?{...t,[n]:{...r,...t[n]}}:{[n]:r}}var qo=class{name="git";defaultFs;defaultCwd;blocked;hooks;inner;locks=new WeakMap;async withLock(t,n){let r=this.locks.get(t)??Promise.resolve(),o,s=new Promise(i=>{o=i});this.locks.set(t,s),await r;try{return await n()}finally{o()}}constructor(t){this.defaultFs=t?.fs,this.defaultCwd=t?.cwd??"/",this.hooks=t?.hooks,this.blocked=t?.disabled?.length?new Set(t.disabled):null;let n=t?.network,r=vw(t?.identity,t?.config),o={hooks:t?.hooks,credentialProvider:t?.credentials,identityOverride:t?.identity,fetchFn:typeof n=="object"?n.fetch:void 0,networkPolicy:n,resolveRemote:t?.resolveRemote,...t?.objectStore?{objectStore:t.objectStore}:{},...t?.refStore?{refStore:t.refStore}:{},...t?.gitDir?{gitDir:t.gitDir,workTree:this.defaultCwd}:{},...r?{configOverrides:r}:{}};this.inner=Id(o).toCommand()}exec=async(t,n)=>{let r=n?.fs??this.defaultFs;if(!r)throw new Error("No filesystem: pass `fs` in exec() options or in createGit()");let o=n?.cwd??this.defaultCwd,s=Tw(t),i=new Map;if(n?.env)for(let[a,c]of Object.entries(n.env))i.set(a,c);return this.execute(s,{fs:r,cwd:o,env:i,stdin:n?.stdin??""})};execute=(t,n)=>this.withLock(n.fs,async()=>{let r=t[0]??"";if(r==="--version"||r==="version")return{stdout:`just-git version ${Sw} (virtual git implementation)
779
+ `,exitCode:1}}}),t}var Sw="1.3.3";function vw(e,t){if(!e)return t;let n=e.locked?"locked":"defaults",r={"user.name":e.name,"user.email":e.email};return t?{...t,[n]:{...r,...t[n]}}:{[n]:r}}var qo=class{name="git";defaultFs;defaultCwd;blocked;hooks;inner;locks=new WeakMap;async withLock(t,n){let r=this.locks.get(t)??Promise.resolve(),o,s=new Promise(i=>{o=i});this.locks.set(t,s),await r;try{return await n()}finally{o()}}constructor(t){this.defaultFs=t?.fs,this.defaultCwd=t?.cwd??"/",this.hooks=t?.hooks,this.blocked=t?.disabled?.length?new Set(t.disabled):null;let n=t?.network,r=vw(t?.identity,t?.config),o={hooks:t?.hooks,credentialProvider:t?.credentials,identityOverride:t?.identity,fetchFn:typeof n=="object"?n.fetch:void 0,networkPolicy:n,resolveRemote:t?.resolveRemote,...t?.objectStore?{objectStore:t.objectStore}:{},...t?.refStore?{refStore:t.refStore}:{},...t?.gitDir?{gitDir:t.gitDir,workTree:this.defaultCwd}:{},...r?{configOverrides:r}:{}};this.inner=Id(o).toCommand()}exec=async(t,n)=>{let r=n?.fs??this.defaultFs;if(!r)throw new Error("No filesystem: pass `fs` in exec() options or in createGit()");let o=n?.cwd??this.defaultCwd,s=Tw(t),i=new Map;if(n?.env)for(let[a,c]of Object.entries(n.env))i.set(a,c);return this.execute(s,{fs:r,cwd:o,env:i,stdin:n?.stdin??""})};execute=(t,n)=>this.withLock(n.fs,async()=>{let r=t[0]??"";if(r==="--version"||r==="version")return{stdout:`just-git version ${Sw} (virtual git implementation)
780
780
  `,stderr:"",exitCode:0};if(this.blocked?.has(r))return{stdout:"",stderr:`git: '${r}' is not available in this environment
781
781
  `,exitCode:1};if(r&&Od.has(r))return{stdout:"",stderr:`git: '${r}' is not implemented. Run 'git help' for available commands.
782
782
  `,exitCode:1};if(this.hooks?.beforeCommand){let s=await this.hooks.beforeCommand({command:r,args:t.slice(1),fs:n.fs,cwd:n.cwd,env:n.env});if(ee(s))return{stdout:"",stderr:s.message??"",exitCode:1}}let o=await this.inner.execute(t,n);return this.hooks?.afterCommand&&await this.hooks.afterCommand({command:r,args:t.slice(1),result:o}),o})};function Tw(e){let t=[],n="",r=0;for(;r<e.length;){let o=e[r];if(o==='"'){for(r++;r<e.length&&e[r]!=='"';){if(e[r]==="\\"&&r+1<e.length){let s=e[r+1];if(s==='"'||s==="\\"){n+=s,r+=2;continue}}n+=e[r],r++}r++}else if(o==="'"){for(r++;r<e.length&&e[r]!=="'";)n+=e[r],r++;r++}else o===" "||o===" "?(n.length>0&&(t.push(n),n=""),r++):(n+=o,r++)}return n.length>0&&t.push(n),t.length>0&&t[0]==="git"&&t.shift(),t}function Hw(e){return new qo(e)}var Sd=new TextEncoder,Aw=new TextDecoder;function hn(e){let t=[];for(let n of e.split("/"))n==="."||n===""||(n===".."?t.pop():t.push(n));return"/"+t.join("/")}function zo(e){let t=e.lastIndexOf("/");return t<=0?"/":e.slice(0,t)}var Ca=class{data=new Map;constructor(t){if(this.data.set("/",{type:"directory",mode:16877,mtime:new Date}),t)for(let[n,r]of Object.entries(t)){let o=hn(n);this.ensureParents(o),this.data.set(o,{type:"file",content:typeof r=="string"?Sd.encode(r):r,mode:33188,mtime:new Date})}}ensureParents(t){let n=zo(t);n!=="/"&&(this.data.has(n)||(this.ensureParents(n),this.data.set(n,{type:"directory",mode:16877,mtime:new Date})))}resolve(t){let n="",r=new Set;for(let o of hn(t).slice(1).split("/")){n=`${n}/${o}`;let s=0,i=this.data.get(n);for(;i?.type==="symlink"&&s<40;){if(r.has(n))throw new Error(`ELOOP: too many levels of symbolic links, '${t}'`);r.add(n);let a=i.target;n=a.startsWith("/")?hn(a):hn(zo(n)+"/"+a),i=this.data.get(n),s++}if(s>=40)throw new Error(`ELOOP: too many levels of symbolic links, '${t}'`)}return n}resolveParent(t){let n=hn(t);if(n==="/")return"/";let r=n.slice(1).split("/");if(r.length<=1)return n;let o="",s=new Set;for(let i=0;i<r.length-1;i++){o=`${o}/${r[i]}`;let a=this.data.get(o),c=0;for(;a?.type==="symlink"&&c<40;){if(s.has(o))throw new Error(`ELOOP: too many levels of symbolic links, '${t}'`);s.add(o);let f=a.target;o=f.startsWith("/")?hn(f):hn(zo(o)+"/"+f),a=this.data.get(o),c++}}return`${o}/${r[r.length-1]}`}async readFile(t){return Aw.decode(await this.readFileBuffer(t))}async readFileBuffer(t){let n=this.data.get(this.resolve(t));if(!n)throw new Error(`ENOENT: no such file or directory, open '${t}'`);if(n.type!=="file")throw new Error(`EISDIR: illegal operation on a directory, read '${t}'`);return n.content}async writeFile(t,n){let r=this.resolve(t);this.ensureParents(r),this.data.set(r,{type:"file",content:typeof n=="string"?Sd.encode(n):n,mode:33188,mtime:new Date})}async exists(t){try{return this.data.has(this.resolve(t))}catch{return!1}}async stat(t){let n=this.data.get(this.resolve(t));if(!n)throw new Error(`ENOENT: no such file or directory, stat '${t}'`);return{isFile:n.type==="file",isDirectory:n.type==="directory",isSymbolicLink:!1,mode:n.mode,size:n.type==="file"?n.content.byteLength:0,mtime:n.mtime}}async lstat(t){let n=this.resolveParent(t),r=this.data.get(n);if(!r)throw new Error(`ENOENT: no such file or directory, lstat '${t}'`);return{isFile:r.type==="file",isDirectory:r.type==="directory",isSymbolicLink:r.type==="symlink",mode:r.mode,size:r.type==="file"?r.content.byteLength:r.type==="symlink"?r.target.length:0,mtime:r.mtime}}async mkdir(t,n){let r=hn(t);if(this.data.has(r)){if(this.data.get(r).type!=="directory")throw new Error(`EEXIST: file already exists, mkdir '${t}'`);if(!n?.recursive)throw new Error(`EEXIST: directory already exists, mkdir '${t}'`);return}let o=zo(r);if(o!=="/"&&!this.data.has(o))if(n?.recursive)await this.mkdir(o,{recursive:!0});else throw new Error(`ENOENT: no such file or directory, mkdir '${t}'`);this.data.set(r,{type:"directory",mode:16877,mtime:new Date})}async readdir(t){let n=this.resolve(t),r=this.data.get(n);if(!r)throw new Error(`ENOENT: no such file or directory, scandir '${t}'`);if(r.type!=="directory")throw new Error(`ENOTDIR: not a directory, scandir '${t}'`);let o=n==="/"?"/":`${n}/`,s=new Set;for(let i of this.data.keys())if(i!==n&&i.startsWith(o)){let c=i.slice(o.length).split("/")[0];c&&s.add(c)}return[...s].sort()}async rm(t,n){let r=hn(t),o=this.data.get(r);if(!o){if(n?.force)return;throw new Error(`ENOENT: no such file or directory, rm '${t}'`)}if(o.type==="directory"){if(!n?.recursive&&(await this.readdir(r)).length>0)throw new Error(`ENOTEMPTY: directory not empty, rm '${t}'`);let s=r==="/"?"/":`${r}/`;for(let i of[...this.data.keys()])i.startsWith(s)&&this.data.delete(i)}this.data.delete(r)}async readlink(t){let n=this.resolveParent(t),r=this.data.get(n);if(!r)throw new Error(`ENOENT: no such file or directory, readlink '${t}'`);if(r.type!=="symlink")throw new Error(`EINVAL: invalid argument, readlink '${t}'`);return r.target}async symlink(t,n){let r=hn(n);if(this.data.has(r))throw new Error(`EEXIST: file already exists, symlink '${n}'`);this.ensureParents(r),this.data.set(r,{type:"symlink",target:t,mode:40960,mtime:new Date})}};Gn();export{qo as Git,Ca as MemoryFileSystem,Th as composeGitHooks,Hw as createGit,rr as findRepo,ee as isRejection};