Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

btv.git_local

btv.git_local.discover(path)

discover(path) -> promise of { root, git_dir, prefix }. path is any path inside the repo. Replaces rev-parse --show-toplevel / --absolute-git-dir / --show-prefix. Rejects (ENOREPO) when path is not inside a repository.

Defined in git.lua.

btv.git_local.head(path)

head(path) -> promise of { branch, detached, sha }. branch is nil on a detached HEAD (detached then true); sha is the full resolved commit oid (empty on an unborn HEAD). Replaces rev-parse --abbrev-ref HEAD.

Defined in git.lua.

btv.git_local.show(file, rev)

show(file, rev) -> promise of the RAW bytes of file (an absolute path) as it was at rev (e.g. "HEAD"). Replaces git show HEAD:<rel>, but you pass the plain file path — the repo-relative path is computed for you (symlink-safe). Rejects (ENOENT) when the file has no version at rev (new / untracked file).

Defined in git.lua.

btv.git_local.diff_file(path, file)

diff_file(path, file) -> promise of { added, changed, removed, hunks } for file’s working tree vs its HEAD blob (each hunk { old_start, old_count, new_start, new_count }). Replaces git diff -U0 -- <file> plus hunk parsing. path locates the repo (any path inside it); file is the file to diff.

Defined in git.lua.

btv.git_local.status(path, opts)

status(path, opts) -> promise of { dirty, entries } in git status --porcelain XY terms. Each entry is { path, index, worktree, orig_path }:

path       repo-relative path of the changed file
index      the staged (index-vs-HEAD) column, one letter
worktree   the unstaged (worktree-vs-index) column, one letter
orig_path  where the content came from, for a rename/copy; "" otherwise

A column is " " when the file is unmodified in it. There is exactly ONE entry per path: a file that is staged and then edited again arrives once with both columns set (porcelain’s MM), never as two entries carrying one column each. An untracked file is porcelain’s ?? — both columns.

Unlike git status, an unstaged rename IS detected: it reads R on the destination with orig_path set, where git prints a deletion plus an untracked file.

opts.ignored (default false) additionally reports git-ignored paths as porcelain’s !! — both columns — like git status --porcelain --ignored. It is opt-in because the default walk PRUNES ignored directories, which is what keeps a status over a repo with a large target/ fast; asked for, the walk must descend into them. A wholly-ignored directory collapses to ONE entry naming the directory (target, not its 50k files), exactly like a collapsed untracked directory — so a consumer resolves directory-ness from its own model and matches descendants by path prefix:

local st = btv.await(btv.git.status(root, { ignored = true }))
for _, e in ipairs(st.entries) do
  if e.index == "!" then ignored[e.path] = true end   -- a file OR a directory
end

A repository that is not trusted — owned by another user and not listed in safe.directory, git’s rule — has its own config ignored, so the filter drivers it defines (filter.<name>.clean and friends) do not run and files are compared unfiltered. The result then carries notice, a message naming the repository and the skipped drivers, and the first such notice per repository is also shown with btv.notify at WARN.

Defined in git.lua.

btv.git_local.clone(url, dir, opts)

clone(url, dir, opts) -> promise of the created dir. opts.depth makes it a shallow clone (1 = only the tip commit); opts.branch checks out a named branch or tag instead of the remote default. Replaces git clone. (git’s --filter=blob:none has no gix analog — a shallow depth supplies the same speed-up.) Rejects (EGIT) on any clone/fetch failure.

Defined in git.lua.

btv.git_local.checkout(dir, rev, opts)

checkout(dir, rev, opts) -> promise resolving nil. Checks out rev in the repo at dir, updating the worktree to match. Two modes:

btv.git.checkout(dir, sha, { detach = true })  -- git checkout --detach <sha>
btv.git.checkout(dir, "main")                  -- git checkout main

With opts.detach the rev is any revision (a sha, tag, or ref) and HEAD is left pointing straight at that commit — how an exact pin is applied. Without it, rev names a BRANCH and HEAD stays symbolic on it; a branch that exists only as a remote-tracking ref (the usual case for anything but the default branch of a fresh clone) is created locally from it first, as git checkout <branch> does.

Attaching is what makes a detached checkout movable again: pull fast-forwards the current branch, so it rejects outright while HEAD names a bare commit. Rejects (ENOENT) when an attach target is neither a local nor a remote-tracking branch.

Defined in git.lua.

btv.git_local.fetch(dir, opts)

fetch(dir, opts) -> promise resolving nil. Fetches the repo’s remote, updating the remote-tracking refs and leaving HEAD and the worktree alone — the half of pull that touches no working state. Replaces git fetch.

opts.unshallow drops a shallow clone’s boundary (git fetch --unshallow), so history a depth = 1 clone omitted becomes reachable. That is the prerequisite for checking out an arbitrary older revision in place — without it, a shallow clone simply does not contain the commit and the checkout rejects. A no-op on a repo that was never shallow.

Defined in git.lua.

btv.git_local.pull(dir)

pull(dir) -> promise of { updated, sha }. Fetches the repo’s remote and fast-forwards only the current branch (rejecting ENOTFF on a divergence, never merging). updated is false when already current. Replaces git pull --ff-only.

Defined in git.lua.

btv.git_local.submodule_update(dir, opts)

submodule_update(dir, opts) -> promise resolving nil. Clones-if-missing (opts.init) and checks out every submodule to its recorded commit, opts.recursive-ly into nested ones. Replaces git submodule update --init --recursive.

Defined in git.lua.