Skip to content

Python API Reference

from vost import GitStore, FS, Batch, WriteEntry, StaleSnapshotError, retry_write
from vost import ChangeReport, ChangeAction, ChangeActionKind, ChangeError, FileEntry, FileType
from vost import MirrorDiff, RefChange, ReflogEntry, Signature, WalkEntry
from vost import NoteDict, NoteNamespace, NotesBatch
from vost import ExcludeFilter, BlobOid, StatResult, disk_glob

GitStore

vost.GitStore(repo: _Repository, author: str, email: str)

A versioned filesystem backed by a bare git repository.

Open or create a store with :meth:open. Access snapshots via :attr:branches, :attr:tags, and :attr:notes.

branches = RefDict(self, 'refs/heads/') instance-attribute

tags = RefDict(self, 'refs/tags/') instance-attribute

notes = NoteDict(self) instance-attribute

open(path: str | Path, *, create: bool = True, branch: str | None = 'main', author: str = 'vost', email: str = 'vost@localhost', compression: int | None = None, big_file_threshold: int | None = None) -> GitStore classmethod

Open or create a bare git repository.

Parameters:

Name Type Description Default
path str | Path

Path to the bare repository.

required
create bool

If True (default), create the repo when it doesn't exist. If False, raise FileNotFoundError when missing.

True
branch str | None

Initial branch name when creating (default "main"). None to create a bare repo with no branches.

'main'
author str

Default author name for commits.

'vost'
email str

Default author email for commits.

'vost@localhost'
compression int | None

Zlib compression level for git objects (0-9). None uses the git default (6). 0 disables compression, which is ideal for pre-compressed data like Zarr chunks.

None
big_file_threshold int | None

Blobs larger than this (bytes) skip delta compression during packing. 0 means all blobs skip deltas. None uses the git default (512 MiB).

None

fs(ref: str, *, back: int = 0) -> FS

Get an FS snapshot for any ref (branch, tag, or commit hash).

Resolution order: branches → tags → commit hash. Writable for branches, read-only for tags and commit hashes.

Parameters:

Name Type Description Default
ref str

Branch name, tag name, or commit hash (full or short).

required
back int

Walk back N ancestor commits (default 0).

0

Returns:

Type Description
FS

FS snapshot for the resolved ref.

Raises:

Type Description
KeyError

If ref cannot be resolved.

read_by_hash(hash: str | bytes, *, offset: int = 0, size: int | None = None) -> bytes

Read raw blob data by hash, bypassing tree/ref resolution.

This is the fastest path to blob data — no FS, no tree walk, just a direct object store lookup. Ideal for content-addressed access.

has_hash(hash: str | bytes) -> bool

Check if a blob with the given hash exists in the object store.

pack(*, progress: Callable | None = None) -> int

Pack loose objects into a packfile.

Consolidates loose git objects into a single packfile for better performance and disk usage. Implementations may also perform additional housekeeping (e.g. garbage collection) as a side effect.

Parameters:

Name Type Description Default
progress Callable | None

Optional progress callback.

None

Returns:

Type Description
int

Number of objects packed.

gc(*, progress: Callable | None = None) -> int

Run garbage collection: clean up temporary files and pack loose objects.

Cleans up incomplete temporary pack files, then consolidates loose objects into packfiles. This is a native implementation — it does not require git to be installed.

Note: this does not prune unreachable objects. For full GC with pruning, use git gc directly on the repository.

Parameters:

Name Type Description Default
progress Callable | None

Optional progress callback.

None

Returns:

Type Description
int

Number of objects packed.

backup(url: str, *, dry_run: bool = False, progress: Callable | None = None, refs: list[str] | dict[str, str] | None = None, format: str | None = None, squash: bool = False) -> MirrorDiff

Push refs to url, or write a bundle file.

Without refs this is a full mirror: remote-only refs are deleted. With refs only the specified refs are pushed (no deletes). If url ends with .bundle (or format is "bundle"), a portable bundle file is written instead of pushing to a remote.

refs may be a list of names (identity mapping) or a dict mapping source names to destination names for renaming on the remote side.

When squash is True and writing a bundle, each ref gets a parentless commit with the same tree (stripping history).

Parameters:

Name Type Description Default
url str

Remote URL, local path, or .bundle file path.

required
dry_run bool

Compute diff without pushing.

False
progress Callable | None

Optional progress callback.

None
refs list[str] | dict[str, str] | None

Ref names to include (short or full), or a dict mapping source to destination names. None = all refs.

None
format str | None

"bundle" to force bundle format.

None
squash bool

Strip history — each ref becomes a single parentless commit. Only supported for bundle output.

False

Returns:

Name Type Description
A MirrorDiff

class:MirrorDiff describing what changed (or would change).

restore(url: str, *, dry_run: bool = False, progress: Callable | None = None, refs: list[str] | dict[str, str] | None = None, format: str | None = None) -> MirrorDiff

Fetch refs from url, or import a bundle file.

Restore is additive: refs are added and updated but local-only refs are never deleted. HEAD (the current branch pointer) is not restored — use store.branches.current = "name" afterwards if needed.

refs may be a list of names (identity mapping) or a dict mapping source names to destination names for renaming locally.

Parameters:

Name Type Description Default
url str

Remote URL, local path, or .bundle file path.

required
dry_run bool

Compute diff without fetching.

False
progress Callable | None

Optional progress callback.

None
refs list[str] | dict[str, str] | None

Ref names to include (short or full), or a dict mapping source to destination names. None = all refs.

None
format str | None

"bundle" to force bundle format.

None

Returns:

Name Type Description
A MirrorDiff

class:MirrorDiff describing what changed (or would change).

bundle_export(path: str, *, refs: list[str] | dict[str, str] | None = None, squash: bool = False, progress: Callable | None = None) -> None

Export refs to a bundle file.

refs may be a list of names (identity mapping) or a dict mapping source names to destination names for renaming in the bundle.

When squash is True each ref in the bundle gets a parentless commit whose tree matches the original tip, stripping all history.

Parameters:

Name Type Description Default
path str

Destination .bundle file path.

required
refs list[str] | dict[str, str] | None

Ref names to include (short or full), or a dict mapping source to destination names. None = all refs.

None
squash bool

Strip history — each ref becomes a single parentless commit.

False
progress Callable | None

Optional progress callback.

None

bundle_import(path: str, *, refs: list[str] | dict[str, str] | None = None, progress: Callable | None = None) -> None

Import refs from a bundle file (additive — no deletes).

refs may be a list of names (identity mapping) or a dict mapping source names to destination names for renaming on import.

Parameters:

Name Type Description Default
path str

Source .bundle file path.

required
refs list[str] | dict[str, str] | None

Ref names to include (short or full), or a dict mapping source to destination names. None = all refs.

None
progress Callable | None

Optional progress callback.

None

Operations Overview

vost has four ways to move data. They differ in what they transfer and how much they replace at the destination.

Operation What it transfers Destination behavior Scope
copy Individual files and directories Additive — existing files are kept unless --delete is passed Selected paths
sync A directory tree Exact mirror — destination matches source, extras are deleted One directory tree
archive A snapshot as a single file Exports to (or imports from) a .zip/.tar archive One branch or tag
backup / restore The entire repository All branches, tags, and history are pushed to (or fetched from) a remote git repo or bundle file Whole repo

copy and sync work with individual files between disk and repo (or within the repo). The difference is that copy is additive by default — it only adds or updates files — while sync makes the destination an exact replica of the source, deleting anything extra.

When --exclude patterns are used with either copy --delete or sync, excluded files in the destination are preserved (not deleted). This matches rsync's semantics: excluded files are invisible to the operation in both source and destination.

archive serializes one snapshot (branch, tag, or historical commit) into a single archive file, or imports one back. No git history is preserved — just the file tree at that point in time.

backup and restore operate at the git level. They push or fetch all refs (branches, tags) and their full commit history to another git repository. This is for disaster recovery and replication, not for working with individual files.

I want to... Use
Copy specific files into or out of the repo copy_in / copy_out (cp)
Make a repo directory match a local directory sync_in / sync_out (sync)
Export a snapshot as a zip/tar archive_out / archive_in
Replicate the entire repo to another location backup / restore
Create a portable bundle file bundle_export / bundle_import

FS (Snapshot)

vost.FS(gitstore: GitStore, commit_oid, ref_name: str | None = None, *, writable: bool | None = None)

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

Snapshot Properties

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

writable: bool property

Whether this snapshot can be written to.

commit_hash: str property

The 40-character hex SHA of this snapshot's commit.

ref_name: str | None property

The branch or tag name, or None for detached snapshots.

tree_hash: str property

The 40-char hex SHA of the root tree.

message: str property

The commit message (trailing newline stripped).

time: datetime property

Timezone-aware commit timestamp.

author_name: str property

The commit author's name.

author_email: str property

The commit author's email address.

changes: ChangeReport | None property

Report of the operation that created this snapshot.

Querying Files

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

exists(path: str | os.PathLike[str]) -> bool

Return True if path exists (file or directory).

is_dir(path: str | os.PathLike[str]) -> bool

Return True if path is a directory (tree) in the repo.

file_type(path: str | os.PathLike[str]) -> FileType

Return the :class:FileType of path.

Returns FileType.BLOB, FileType.EXECUTABLE, FileType.LINK, or FileType.TREE.

Raises :exc:FileNotFoundError if the path does not exist.

size(path: str | os.PathLike[str]) -> int

Return the size in bytes of the object at path.

Works without reading the full blob into memory.

Raises :exc:FileNotFoundError if the path does not exist.

object_hash(path: str | os.PathLike[str]) -> str

Return the 40-character hex SHA of the object at path.

For files this is the blob SHA; for directories the tree SHA.

Raises :exc:FileNotFoundError if the path does not exist.

stat(path: str | os.PathLike[str] | None = None) -> StatResult

Return a :class:StatResult for path (or root if None).

Combines file_type, size, oid, nlink, and mtime in a single call — the hot path for FUSE getattr.

Reading Files

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

read(path: str | os.PathLike[str], *, offset: int = 0, size: int | None = None) -> bytes

Read file contents as bytes.

Parameters:

Name Type Description Default
path str | PathLike[str]

File path in the repo.

required
offset int

Byte offset to start reading from.

0
size int | None

Maximum number of bytes to return (None for all).

None

Raises:

Type Description
FileNotFoundError

If path does not exist.

IsADirectoryError

If path is a directory.

read_text(path: str | os.PathLike[str], encoding: str = 'utf-8') -> str

Read file contents as a string.

Parameters:

Name Type Description Default
path str | PathLike[str]

File path in the repo.

required
encoding str

Text encoding (default "utf-8").

'utf-8'

read_by_hash(hash: str | bytes, *, offset: int = 0, size: int | None = None) -> bytes

Read raw blob data by hash, bypassing tree lookup.

FUSE pattern: stat() → cache hash → read_by_hash(hash).

Read the target of a symlink.

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

ls(path: str | os.PathLike[str] | None = None) -> list[str]

List entry names at path (or root if None).

Parameters:

Name Type Description Default
path str | PathLike[str] | None

Directory path, or None for the repo root.

None

Raises:

Type Description
NotADirectoryError

If path is a file.

listdir(path: str | os.PathLike[str] | None = None) -> list[WalkEntry]

List directory entries with name, oid, and mode.

Like :meth:ls but returns :class:WalkEntry objects so callers get entry types (useful for FUSE readdir d_type).

walk(path: str | os.PathLike[str] | None = None) -> Iterator[tuple[str, list[str], list[WalkEntry]]]

Walk the repo tree recursively, like :func:os.walk.

Yields (dirpath, dirnames, file_entries) tuples. Each file entry is a :class:WalkEntry with name, oid, and mode.

Parameters:

Name Type Description Default
path str | PathLike[str] | None

Subtree to walk, or None for root.

None

Raises:

Type Description
NotADirectoryError

If path is a file.

glob(pattern: str) -> list[str]

Expand a glob pattern against the repo tree.

Supports *, ?, and **. * and ? do not match a leading . unless the pattern segment itself starts with .. ** matches zero or more directory levels, skipping directories whose names start with .. Returns a sorted, deduplicated list of matching paths (files and directories).

iglob(pattern: str) -> Iterator[str]

Expand a glob pattern against the repo tree, yielding unique matches.

Like :meth:glob but returns an unordered iterator instead of a sorted list. Useful when you only need to iterate once and don't need sorted output.

A /./ pivot marker (rsync -R style) is preserved in the output so that callers can reconstruct partial source paths.

Writing Files

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

write(path: str | os.PathLike[str], data: bytes, *, message: str | None = None, mode: FileType | int | None = None, parents: list[FS] | None = None) -> FS

Write data to path and commit, returning a new :class:FS.

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
data bytes

Raw bytes to write.

required
message str | None

Commit message (auto-generated if None).

None
mode FileType | int | None

File mode override (e.g. FileType.EXECUTABLE).

None

Raises:

Type Description
PermissionError

If this snapshot is read-only.

StaleSnapshotError

If the branch has advanced since this snapshot.

write_text(path: str | os.PathLike[str], text: str, *, encoding: str = 'utf-8', message: str | None = None, mode: FileType | int | None = None, parents: list[FS] | None = None) -> FS

Write text to path and commit, returning a new :class:FS.

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
text str

String content (encoded with encoding).

required
encoding str

Text encoding (default "utf-8").

'utf-8'
message str | None

Commit message (auto-generated if None).

None
mode FileType | int | None

File mode override (e.g. FileType.EXECUTABLE).

None

Raises:

Type Description
PermissionError

If this snapshot is read-only.

StaleSnapshotError

If the branch has advanced since this snapshot.

write_from_file(path: str | os.PathLike[str], local_path: str | os.PathLike[str], *, message: str | None = None, mode: FileType | int | None = None, parents: list[FS] | None = None) -> FS

Write a local file into the repo and commit, returning a new :class:FS.

Executable permission is auto-detected from disk unless mode is set.

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
local_path str | PathLike[str]

Path to the local file.

required
message str | None

Commit message (auto-generated if None).

None
mode FileType | int | None

File mode override (e.g. FileType.EXECUTABLE).

None

Raises:

Type Description
PermissionError

If this snapshot is read-only.

StaleSnapshotError

If the branch has advanced since this snapshot.

Create a symbolic link entry and commit, returning a new :class:FS.

Parameters:

Name Type Description Default
path str | PathLike[str]

Symlink path in the repo.

required
target str

The symlink target string.

required
message str | None

Commit message (auto-generated if None).

None

Raises:

Type Description
PermissionError

If this snapshot is read-only.

StaleSnapshotError

If the branch has advanced since this snapshot.

writer(path: str | os.PathLike[str], mode: str = 'wb')

Return a writable file-like that commits on close.

"wb" accepts bytes; "w" accepts strings (UTF-8 encoded).

Example::

with fs.writer("output.bin") as f:
    f.write(b"chunk1")
    f.write(b"chunk2")
fs = f.fs  # new snapshot

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
mode str

"wb" (binary, default) or "w" (text).

'wb'

Raises:

Type Description
PermissionError

If the snapshot is read-only.

batch(message: str | None = None, operation: str | None = None, parents: list[FS] | None = None)

Return a :class:Batch context manager for multiple writes in one commit.

Parameters:

Name Type Description Default
message str | None

Commit message (auto-generated if None).

None
operation str | None

Operation name for auto-generated messages.

None
parents list[FS] | None

Additional parent :class:FS snapshots (advisory merge parents).

None

Raises:

Type Description
PermissionError

If this snapshot is read-only.

Bulk Operations

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

copy_in(sources: str | list[str], dest: str, *, dry_run: bool = False, follow_symlinks: bool = False, message: str | None = None, mode: FileType | int | None = None, ignore_existing: bool = False, delete: bool = False, ignore_errors: bool = False, checksum: bool = True, exclude: ExcludeFilter | None = None, parents: list[FS] | None = None) -> FS

Copy local files into the repo.

Sources must be literal paths; use :func:~vost.disk_glob to expand patterns before calling.

Parameters:

Name Type Description Default
sources str | list[str]

Local path(s). Trailing / copies contents; /./ is a pivot marker.

required
dest str

Destination path in the repo.

required
dry_run bool

Preview only; returned FS has .changes set.

False
follow_symlinks bool

Dereference symlinks on disk.

False
message str | None

Commit message (auto-generated if None).

None
mode FileType | int | None

Override file mode for all files.

None
ignore_existing bool

Skip files that already exist at dest.

False
delete bool

Remove repo files under dest not in source. Excluded files (via exclude) are preserved (rsync behavior).

False
ignore_errors bool

Collect errors instead of aborting.

False
checksum bool

Compare by content hash (default True).

True
exclude ExcludeFilter | None

Gitignore-style exclude filter.

None

Returns:

Type Description
FS

A new :class:FS with .changes set.

Raises:

Type Description
PermissionError

If this snapshot is read-only.

copy_out(sources: str | list[str], dest: str, *, dry_run: bool = False, ignore_existing: bool = False, delete: bool = False, ignore_errors: bool = False, checksum: bool = True) -> FS

Copy repo files to local disk.

Sources must be literal repo paths; use :meth:glob to expand patterns before calling.

Parameters:

Name Type Description Default
sources str | list[str]

Repo path(s). Trailing / copies contents; /./ is a pivot marker.

required
dest str

Local destination directory.

required
dry_run bool

Preview only; returned FS has .changes set.

False
ignore_existing bool

Skip files that already exist at dest.

False
delete bool

Remove local files under dest not in source.

False
ignore_errors bool

Collect errors instead of aborting.

False
checksum bool

Compare by content hash (default True).

True

Returns:

Name Type Description
This FS

class:FS with .changes set.

sync_in(local_path: str, repo_path: str, *, dry_run: bool = False, message: str | None = None, ignore_errors: bool = False, checksum: bool = True, exclude: ExcludeFilter | None = None, parents: list[FS] | None = None) -> FS

Make repo_path identical to local_path (including deletes).

Parameters:

Name Type Description Default
local_path str

Local directory to sync from.

required
repo_path str

Repo directory to sync to.

required
dry_run bool

Preview only; returned FS has .changes set.

False
message str | None

Commit message (auto-generated if None).

None
ignore_errors bool

Collect errors instead of aborting.

False
checksum bool

Compare by content hash (default True).

True
exclude ExcludeFilter | None

Gitignore-style exclude filter.

None

Returns:

Type Description
FS

A new :class:FS with .changes set.

Raises:

Type Description
PermissionError

If this snapshot is read-only.

sync_out(repo_path: str, local_path: str, *, dry_run: bool = False, ignore_errors: bool = False, checksum: bool = True) -> FS

Make local_path identical to repo_path (including deletes).

Parameters:

Name Type Description Default
repo_path str

Repo directory to sync from.

required
local_path str

Local directory to sync to.

required
dry_run bool

Preview only; returned FS has .changes set.

False
ignore_errors bool

Collect errors instead of aborting.

False
checksum bool

Compare by content hash (default True).

True

Returns:

Name Type Description
This FS

class:FS with .changes set.

remove(sources: str | list[str], *, recursive: bool = False, dry_run: bool = False, message: str | None = None, parents: list[FS] | None = None) -> FS

Remove files from the repo.

Sources must be literal paths; use :meth:glob to expand patterns before calling.

Parameters:

Name Type Description Default
sources str | list[str]

Repo path(s) to remove.

required
recursive bool

Allow removing directories.

False
dry_run bool

Preview only; returned FS has .changes set.

False
message str | None

Commit message (auto-generated if None).

None

Returns:

Type Description
FS

A new :class:FS with .changes set.

Raises:

Type Description
PermissionError

If this snapshot is read-only.

FileNotFoundError

If no source paths match.

move(sources: str | list[str], dest: str, *, recursive: bool = False, dry_run: bool = False, message: str | None = None, parents: list[FS] | None = None) -> FS

Move or rename files within the repo.

Sources must be literal paths; use :meth:glob to expand patterns before calling.

Parameters:

Name Type Description Default
sources str | list[str]

Repo path(s) to move.

required
dest str

Destination path in the repo.

required
recursive bool

Allow moving directories.

False
dry_run bool

Preview only; returned FS has .changes set.

False
message str | None

Commit message (auto-generated if None).

None

Returns:

Type Description
FS

A new :class:FS with .changes set.

Raises:

Type Description
PermissionError

If this snapshot is read-only.

copy_from_ref(source: FS | str, sources: str | list[str] = '', dest: str = '', *, delete: bool = False, dry_run: bool = False, message: str | None = None, parents: list[FS] | None = None) -> FS

Copy files from source into this branch in a single atomic commit.

Follows the same rsync trailing-slash conventions as copy_in/copy_out:

  • "config" → directory mode — copies config/ as config/ under dest.
  • "config/" → contents mode — pours the contents of config/ into dest.
  • "file.txt" → file mode — copies the single file into dest.
  • "" or "/" → root contents mode — copies everything.

Since both snapshots share the same object store, blobs are referenced by OID — no data is read into memory regardless of file size.

Parameters:

Name Type Description Default
source FS | str

Any FS (branch, tag, detached commit), or a branch/tag name string that will be resolved to an FS. Read-only; not modified.

required
sources str | list[str]

Source path(s) in source. Accepts a single string or a list of strings. Defaults to "" (root = everything).

''
dest str

Destination path in this branch. Defaults to "" (root).

''
delete bool

Remove dest files under the target that aren't in source.

False
dry_run bool

Compute changes but don't commit. Returned FS has .changes set.

False
message str | None

Commit message (auto-generated if None).

None

Returns:

Type Description
FS

A new :class:FS for the dest branch with the commit applied.

Raises:

Type Description
ValueError

If source belongs to a different repo or cannot be resolved.

FileNotFoundError

If a source path does not exist.

PermissionError

If this FS is read-only.

apply(writes: dict[str, WriteEntry | bytes | str | Path] | None = None, removes: str | list[str] | set[str] | None = None, *, message: str | None = None, operation: str | None = None, parents: list[FS] | None = None) -> FS

Apply multiple writes and removes in a single atomic commit.

writes maps repo paths to content. Values may be:

  • bytes — raw blob data
  • str — UTF-8 text (encoded automatically)
  • :class:~pathlib.Path — read from local file (mode auto-detected)
  • :class:WriteEntry — full control over source, mode, and symlinks

removes lists repo paths to delete (str, list, or set).

Returns a new :class:FS snapshot with the changes committed.

History & Navigation

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

parent: FS | None property

The parent snapshot, or None for the initial commit.

back(n: int = 1) -> FS

Return the FS at the n-th ancestor commit.

Raises ValueError if n < 0 or history is too short.

log(path: str | os.PathLike[str] | None = None, *, match: str | None = None, before: datetime | None = None) -> Iterator[FS]

Walk the commit history, yielding ancestor :class:FS snapshots.

All filters are optional and combine with AND.

Parameters:

Name Type Description Default
path str | PathLike[str] | None

Only yield commits that changed this file.

None
match str | None

Message pattern (*/? wildcards via :func:fnmatch).

None
before datetime | None

Only yield commits on or before this time.

None

undo(steps: int = 1) -> FS

Move branch back N commits.

Walks back through parent commits and updates the branch pointer. Automatically writes a reflog entry.

Parameters:

Name Type Description Default
steps int

Number of commits to undo (default 1)

1

Returns:

Type Description
FS

New FS snapshot at the parent commit

Raises:

Type Description
PermissionError

If called on read-only snapshot (tag)

ValueError

If not enough history exists

Example

fs = repo.branches["main"] fs = fs.undo() # Go back 1 commit fs = fs.undo(3) # Go back 3 commits

redo(steps: int = 1) -> FS

Move branch forward N steps using reflog.

Reads the reflog to find where the branch was before the last N movements. This can resurrect "orphaned" commits after undo.

The reflog tracks all branch movements chronologically. Each redo step moves back one entry in the reflog (backwards in time through the log, but forward in commit history).

Parameters:

Name Type Description Default
steps int

Number of reflog entries to go back (default 1)

1

Returns:

Type Description
FS

New FS snapshot at the target position

Raises:

Type Description
PermissionError

If called on read-only snapshot (tag)

ValueError

If not enough redo history exists

Example

fs = fs.undo(2) # Creates 1 reflog entry moving back 2 commits fs = fs.redo() # Go back 1 reflog entry (to before the undo)

Lifecycle

An immutable snapshot of a committed tree.

Read-only when writable is False (tag snapshot). Writable when writable is True — writes auto-commit and return a new FS.

close() -> None

Release cached resources (ObjectSizer file descriptors).


Batch

vost.Batch(fs: FS, message: str | None = None, operation: str | None = None, parents: list[FS] | None = None)

Accumulates writes and removes, committing them in a single atomic commit.

Use as a context manager or call :meth:commit explicitly. Nothing is committed if an exception occurs inside the with block.

Attributes:

Name Type Description
fs FS | None

The resulting :class:~vost.FS after commit, or None if uncommitted or aborted.

write(path: str | os.PathLike[str], data: bytes, *, mode: FileType | int | None = None) -> None

Stage a file write.

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
data bytes

Raw bytes to write.

required
mode FileType | int | None

File mode override (e.g. FileType.EXECUTABLE).

None

write_from_file(path: str | os.PathLike[str], local_path: str | os.PathLike[str], *, mode: FileType | int | None = None) -> None

Stage a write from a local file.

Executable permission is auto-detected from disk unless mode is set.

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
local_path str | PathLike[str]

Path to the local file.

required
mode FileType | int | None

File mode override (e.g. FileType.EXECUTABLE).

None

write_text(path: str | os.PathLike[str], text: str, *, encoding: str = 'utf-8', mode: FileType | int | None = None) -> None

Stage a text write (convenience wrapper around :meth:write).

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
text str

String content (encoded with encoding).

required
encoding str

Text encoding (default "utf-8").

'utf-8'
mode FileType | int | None

File mode override (e.g. FileType.EXECUTABLE).

None

Stage a symbolic link entry.

Parameters:

Name Type Description Default
path str | PathLike[str]

Symlink path in the repo.

required
target str

The symlink target string.

required

remove(path: str | os.PathLike[str]) -> None

Stage a file removal.

Parameters:

Name Type Description Default
path str | PathLike[str]

Path to remove from the repo.

required

Raises:

Type Description
FileNotFoundError

If path does not exist in the repo or pending writes.

IsADirectoryError

If path is a directory.

writer(path: str | os.PathLike[str], mode: str = 'wb')

Return a writable file-like that stages to the batch on close.

"wb" accepts bytes; "w" accepts strings (UTF-8 encoded).

Example::

with fs.batch() as b:
    with b.writer("log.txt", "w") as f:
        f.write("line 1\n")
        f.write("line 2\n")

Parameters:

Name Type Description Default
path str | PathLike[str]

Destination path in the repo.

required
mode str

"wb" (binary, default) or "w" (text).

'wb'

commit() -> FS

Explicitly commit the batch, like __exit__ with no exception.

After calling this the batch is closed and no further writes are allowed. Returns the resulting FS.


Branches & Tags

vost.RefDict(store: GitStore, prefix: str)

Bases: MutableMapping

Dict-like access to branches or tags.

store.branches and store.tags are both RefDict instances. Supports [], del, in, len, and iteration.

current: FS | None property writable

The FS for the repository's current (HEAD) branch, or None if HEAD is dangling.

Only valid for branches; raises ValueError for tags.

current_name: str | None property

The repository's current (HEAD) branch name, or None if HEAD is dangling.

Only valid for branches; raises ValueError for tags. Cheap — does not construct an FS object.

set(name: str, fs: FS) -> FS

Set branch to FS snapshot and return writable FS bound to it.

This is a convenience method that combines setting and getting:

fs_new = repo.branches.set('feature', fs)

Is equivalent to:

repo.branches['feature'] = fs
fs_new = repo.branches['feature']

Parameters:

Name Type Description Default
name str

Branch name

required
fs FS

FS snapshot to set (can be read-only)

required

Returns:

Type Description
FS

New writable FS bound to the branch

Example

fs_wow = repo.branches.set('wow', fs_main) fs_wow.ref_name # 'wow' (not 'main')

reflog(name: str) -> list[ReflogEntry]

Read reflog entries for a branch.

Parameters:

Name Type Description Default
name str

Branch name (e.g., "main")

required

Returns:

Type Description
list[ReflogEntry]

List of :class:ReflogEntry objects.

Raises:

Type Description
KeyError

If branch doesn't exist

FileNotFoundError

If no reflog exists

Example

entries = repo.branches.reflog("main") for e in entries: ... print(f"{e.message}: {e.new_sha[:7]}")

vost.Signature(name: str, email: str) dataclass

Author/committer identity used for commits.

Attributes:

Name Type Description
name str

Author name (e.g. "vost").

email str

Author email (e.g. "vost@localhost").

vost.ReflogEntry(old_sha: str, new_sha: str, committer: str, timestamp: float, message: str) dataclass

A single reflog entry recording a branch movement.

Attributes:

Name Type Description
old_sha str

Previous 40-char hex commit SHA.

new_sha str

New 40-char hex commit SHA.

committer str

Identity string of the committer.

timestamp float

POSIX epoch seconds of the entry.

message str

Reflog message (e.g. "commit: + file.txt").


Notes

vost.NoteDict(store: GitStore)

Outer container for git notes namespaces on a :class:GitStore.

store.notes.commits → default namespace (refs/notes/commits). store.notes['reviews'] → custom namespace.

commits: NoteNamespace property

The default refs/notes/commits namespace.

vost.NoteNamespace(store: GitStore, namespace: str)

Bases: MutableMapping

One git notes namespace, backed by refs/notes/<name>.

Maps commit hashes to UTF-8 note text. Keys can be 40-char hex commit hashes or ref names (branch/tag), which are resolved to the tip commit hash. Supports [], del, in, len, and iteration.

for_current_branch: str property writable

Note for the current HEAD commit.

batch() -> NotesBatch

Return a context manager that batches writes into a single commit.

vost.NotesBatch(ns: NoteNamespace)

Collects note writes/deletes and applies them in one commit on exit.

Usage::

with store.notes.commits.batch() as b:
    b[hash1] = "note 1"
    b[hash2] = "note 2"
    del b[hash3]
# single commit

Backup & Restore

See GitStore.backup() and GitStore.restore().

For direct bundle file operations without the full backup/restore logic, see GitStore.bundle_export() and GitStore.bundle_import().


Exclude Filter

vost.ExcludeFilter(*, patterns: Sequence[str] | None = None, exclude_from: str | None = None, gitignore: bool = False)

Gitignore-style exclude filter for disk-to-repo operations.

Combines --exclude patterns, --exclude-from file, and automatic .gitignore loading into a single predicate.

Parameters:

Name Type Description Default
patterns Sequence[str] | None

Gitignore-style patterns to exclude.

None
exclude_from str | None

Path to a file containing exclude patterns.

None
gitignore bool

Load .gitignore files from walked directories.

False

active: bool property

True if any filtering is configured.

is_excluded(rel_path: str, *, is_dir: bool = False) -> bool

Check against base patterns only (for post-filtering).

enter_directory(abs_dir: Path, rel_dir: str) -> None

Load .gitignore from abs_dir if gitignore mode is on.

is_excluded_in_walk(rel_path: str, *, is_dir: bool = False) -> bool

Check base patterns + loaded .gitignore hierarchy.

Called during os.walk() after enter_directory has been invoked for every ancestor.


Exceptions

vost.StaleSnapshotError

Bases: Exception

Raised when a write is attempted on a snapshot whose branch has advanced.

Re-fetch the branch via store.branches["name"] and retry, or use :func:~vost.retry_write for automatic retry with backoff.


Utility Functions

vost.retry_write(store: GitStore, branch: str, path: str | os.PathLike[str], data: bytes, *, message: str | None = None, mode: FileType | int | None = None, retries: int = 5, parents: list[FS] | None = None) -> FS

Write data to a branch with automatic retry on concurrent modification.

Re-fetches the branch FS on each attempt. Uses exponential backoff with jitter (base 10ms, factor 2x, cap 200ms) to avoid thundering-herd.

Raises StaleSnapshotError if all attempts are exhausted. Raises KeyError if the branch does not exist.

vost.resolve_credentials(url: str) -> str

Inject credentials into an HTTPS URL if available.

Tries git credential fill first (works with any configured helper: osxkeychain, wincred, libsecret, gh auth setup-git, etc.). Falls back to gh auth token for GitHub hosts. Non-HTTPS URLs and URLs that already contain credentials are returned unchanged.

vost.disk_glob(pattern: str) -> list[str]

Expand a glob pattern against the local filesystem.

Same dotfile rules as the repo-side fs.glob(). Returns a sorted list of matching paths.


Data Types

Types returned by API methods. Most are opaque — you rarely need to construct or import them directly.

vost.StatResult(mode: int, file_type: FileType, size: int, hash: str, nlink: int, mtime: float) dataclass

POSIX-like stat result for a vost path.

Attributes:

Name Type Description
mode int

Raw git filemode (e.g. 0o100644, 0o040000).

file_type FileType

:class:FileType enum value.

size int

Object size in bytes (0 for directories).

hash str

40-char hex SHA of the object (inode proxy).

nlink int

1 for files/symlinks, 2 + subdirs for directories.

mtime float

Commit timestamp as POSIX epoch seconds.

vost.WalkEntry

Bases: NamedTuple

A file entry yielded by :meth:~vost.FS.walk and :meth:~vost.FS.listdir.

Attributes:

Name Type Description
name str

Entry name (file or directory basename).

oid bytes

Raw object ID (bytes).

mode int

Git filemode integer (e.g. 0o100644).

file_type property

Return the :class:~vost.copy._types.FileType for this entry.

vost.FileType

Bases: str, Enum

Git file type enum.

Members: BLOB, EXECUTABLE, LINK, TREE.

filemode: int property

Return the git filemode integer for this type.

from_filemode(mode: int) -> FileType classmethod

Convert a git filemode integer to a :class:FileType.

vost.FileEntry(path: str, type: FileType, src: str | None = None) dataclass

A file path with type information, used in :class:ChangeReport lists.

Attributes:

Name Type Description
path str

Relative path (repo-style forward slashes).

type FileType

:class:FileType of the entry.

src str | None

Source path (local file, repo path, or None for direct data).

from_mode(path: str, mode: int, src: str | None = None) -> FileEntry classmethod

Create FileEntry from path and git filemode.

vost.BlobOid

Bases: bytes

A blob SHA used as a marker in write dicts to avoid re-hashing.

Subclass of :class:bytes. When a value in a write dict is a BlobOid, the tree builder uses it directly instead of calling create_blob.

vost.WriteEntry(data: bytes | str | Path | None = None, mode: FileType | int | None = None, target: str | None = None) dataclass

Describes a single file write for :meth:FS.apply.

Exactly one of data or target must be provided.

data may be bytes, str (UTF-8 text), or a :class:~pathlib.Path to a local file. mode optionally overrides the filemode (e.g. FileType.EXECUTABLE).

target creates a symbolic link entry; mode is not allowed with it.

vost.ChangeReport(add: list[FileEntry] = list(), update: list[FileEntry] = list(), delete: list[FileEntry] = list(), errors: list[ChangeError] = list(), warnings: list[ChangeError] = list()) dataclass

Result of a copy, sync, move, or remove operation.

Available on the :attr:~vost.FS.changes property of the resulting snapshot (both dry-run and real).

Attributes:

Name Type Description
add list[FileEntry]

Files added.

update list[FileEntry]

Files updated.

delete list[FileEntry]

Files deleted.

errors list[ChangeError]

Per-file errors (populated when ignore_errors=True).

warnings list[ChangeError]

Non-fatal warnings.

in_sync: bool property

True if there are no add, update, or delete actions.

total: int property

Total number of add + update + delete actions.

actions() -> list[ChangeAction]

Return all actions as a flat list sorted by path.

vost.ChangeAction(path: str, action: ChangeActionKind) dataclass

A single add/update/delete action in a :class:ChangeReport.

Attributes:

Name Type Description
path str

Relative path (repo-style forward slashes).

action ChangeActionKind

:class:ChangeActionKind value.

vost.ChangeActionKind

Bases: str, Enum

Kind of change action: ADD, UPDATE, or DELETE.

vost.ChangeError(path: str, error: str) dataclass

A file that failed during an operation.

Attributes:

Name Type Description
path str

The path that caused the error.

error str

Human-readable error message.

vost.MirrorDiff(add: list[RefChange] = list(), update: list[RefChange] = list(), delete: list[RefChange] = list()) dataclass

Result of a :meth:~vost.GitStore.backup or :meth:~vost.GitStore.restore operation.

Attributes:

Name Type Description
add list[RefChange]

Refs to create.

update list[RefChange]

Refs to update.

delete list[RefChange]

Refs to delete.

in_sync: bool property

True if there are no changes.

total: int property

Total number of ref changes.

vost.RefChange(ref: str, old_target: str | None = None, new_target: str | None = None) dataclass

A single ref change in a :class:MirrorDiff.

Attributes:

Name Type Description
ref str

Full ref name (e.g. "refs/heads/main").

old_target str | None

Previous 40-char hex SHA, or None for creates.

new_target str | None

New 40-char hex SHA, or None for deletes.