Skip to content

Release inventory

release_inventory

Read package metadata from one immutable Git tree without checking it out.

Package dataclass

One real distribution, identified by its normalized project name.

Source code in packages/axm-git/src/axm_git/core/release_inventory.py
Python
@dataclass(frozen=True)
class Package:
    """One real distribution, identified by its normalized project name."""

    name: str
    path: str
    prefix: str
    required: tuple[str, ...]
    optional: tuple[str, ...]
    private: bool

ReleaseInventory dataclass

Metadata and tags captured once for a resolved commit.

Source code in packages/axm-git/src/axm_git/core/release_inventory.py
Python
@dataclass(frozen=True)
class ReleaseInventory:
    """Metadata and tags captured once for a resolved commit."""

    root: Path
    ref: str
    packages: tuple[Package, ...]
    tags: tuple[tuple[str, str], ...]
    excluded: tuple[str, ...]

git_output(root, args)

Read Git output, refusing errors instead of inventing empty evidence.

Source code in packages/axm-git/src/axm_git/core/release_inventory.py
Python
def git_output(root: Path, args: list[str]) -> str:
    """Read Git output, refusing errors instead of inventing empty evidence."""
    result = run_git(args, root)
    if result.returncode:
        raise ValueError(result.stderr.strip() or f"git {args[0]} failed")
    return result.stdout

read_inventory(root, ref)

Capture the immutable manifest inventory and local tags exactly once.

Source code in packages/axm-git/src/axm_git/core/release_inventory.py
Python
def read_inventory(root: Path, ref: str) -> ReleaseInventory:
    """Capture the immutable manifest inventory and local tags exactly once."""
    commit = git_output(
        root, ["rev-parse", "--verify", "--end-of-options", f"{ref}^{{commit}}"]
    ).strip()
    config: dict[str, object] = tomllib.loads(
        git_output(root, ["show", f"{commit}:pyproject.toml"])
    )
    paths = git_output(root, ["ls-tree", "-r", "--name-only", "-z", commit]).split("\0")
    files = _member_files(config, paths)
    packages = []
    excluded = []
    for file, text in zip(files, _read_blobs(root, commit, files), strict=True):
        package = _package(file, text)
        if package is None:
            excluded.append(file)
        else:
            packages.append(package)
    _validate_unique(packages)
    if not packages:
        raise ValueError("No release packages in the selected tree")
    tags = _tag_records(root)
    return ReleaseInventory(root, commit, tuple(packages), tuple(tags), tuple(excluded))