Skip to main content

rusty-git

GitLab CI PyPI version License: Apache 2.0

High-speed pure Rust Git engine (gix + git2) compiled via PyO3 with both native async (Tokio) and GIL-released sync APIs.

rusty-git provides in-process Git operations with zero OS subprocess forks and statically-compiled native wheels (no dynamic libgit2.so dependencies required).


Installation

pip install rusty-git
# or with uv:
uv add rusty-git

Quickstart: 100% In-Process Demo (Zero Subprocesses)

Copy-paste this into example.py to test immediately in any environment:

import asyncio
import os
import tempfile
import rusty_git


async def main():
    with tempfile.TemporaryDirectory() as tmp_dir:
        repo_path = os.path.join(tmp_dir, "demo.git")

        # 1. Initialize a bare repository in-process (ZERO subprocesses)
        await rusty_git.init_bare_repository(repo_path)

        # 2. Create the initial root commit in-process
        res = await rusty_git.create_commit(
            repo_path,
            branch="main",
            files={
                "README.md": b"# Hello from rusty-git!\n",
                "src/main.py": b"print('Hello World')\n",
            },
            message="Initial commit",
            author_name="Alice",
            author_email="alice@example.com",
        )
        print("Root Commit SHA:", res["commit_sha"])

        # 3. Inspect commit in-process
        commit = await rusty_git.get_commit(repo_path, "HEAD")
        print(f"Author:  {commit['author_name']} <{commit['author_email']}>")
        print(f"Message: {commit['message']}")

        # 4. Read tree blob without disk checkout
        blob = await rusty_git.get_tree_blob(repo_path, "HEAD", "README.md")
        print("Blob Content:", blob.decode("utf-8").strip())

        # 5. List branches
        branches = await rusty_git.list_branches(repo_path)
        print("Branches:", branches)


asyncio.run(main())

Dual-Color Usage: Async & Sync

1. Asynchronous API (Default - for Litestar, FastAPI, Granian, Uvicorn)

All blocking Git I/O is offloaded to a Tokio multi-threaded worker pool, releasing the Python GIL:

import asyncio
import rusty_git


async def main():
    repo_path = "/path/to/your/repo"

    # 1. Inspect commits
    commit = await rusty_git.get_commit(repo_path, "HEAD")
    print(commit["sha"], commit["message"], commit["author_name"])

    # 2. Read tree blobs without disk checkout
    readme = await rusty_git.get_tree_blob(repo_path, "main", "README.md")
    print(readme.decode("utf-8"))

    # 3. Fast unified diffs
    hunks = await rusty_git.compare_refs(repo_path, "main~1", "main")
    for hunk in hunks:
        print(hunk["new_path"], hunk["content"])

    # 4. Dry run: show conflicts before anyone clicks "Merge"
    preview = await rusty_git.preview_merge(repo_path, base_ref="main", head_ref="feature")
    if preview["status"] == "conflict":
        print("Conflicts:", preview["conflicts"])  # nothing was written
    else:
        print("Would produce tree:", preview["tree_sha"])

    # 5. 3-Way Merge (update_ref=True moves `main` to the result atomically).
    #    strategy: "merge" (default) | "squash" | "fast-forward"
    result = await rusty_git.execute_merge(
        repo_path,
        base_ref="main",
        head_ref="feature",
        author_name="Automated Merge",
        author_email="bot@example.com",
        update_ref=True,
        strategy="squash",
    )
    if result["status"] == "merged":
        print("Merged Commit SHA:", result["commit_sha"], "ref moved:", result["ref_updated"])
    elif result["status"] == "up-to-date":
        print("Already up to date at", result["commit_sha"])


asyncio.run(main())

2. Synchronous API (rusty_git.sync - for CLI tools, Celery, scripts)

Direct execution on the calling thread with the Python GIL cleanly released (py.detach):

import rusty_git

# Read commit synchronously
commit = rusty_git.sync.get_commit("/path/to/repo.git", "HEAD")
print(commit["sha"], commit["author_name"])

# List branches synchronously
branches = rusty_git.sync.list_branches("/path/to/repo.git")
print("Branches:", branches)

# Read file directly from commit tree
blob = rusty_git.sync.get_tree_blob("/path/to/repo.git", "HEAD", "pyproject.toml")

# Create a commit directly on any branch (new or existing)
res = rusty_git.sync.create_commit(
    "/path/to/repo.git",
    branch="feature-x",
    files={"hello.txt": b"Hello world!\n"},
    message="feat: add hello.txt",
)

# 3-Way Merge synchronously (strategy: "merge" | "squash" | "fast-forward")
result = rusty_git.sync.execute_merge(
    "/path/to/repo.git",
    "main",
    "feature",
    author_name="Merge Bot",
    author_email="bot@example.com",
    update_ref=True,  # move `main` to the merge result under the ref lock
    strategy="fast-forward",  # raise GitRepositoryError instead of merging
)

# Dry run first - writes nothing (no tree, commit, or ref)
preview = rusty_git.sync.preview_merge("/path/to/repo.git", "main", "feature")
print(preview["status"], preview["conflicts"], preview["tree_sha"])

Architectural Note: Forges & Branch Management

rusty-git is designed for high-performance server-side forges and tools operating on bare repositories:

  • Creating branches with commits: Passing any branch name to create_commit(...) will create or advance that branch atomically.
  • Creating a branch without a commit: update_ref(repo_path, "feature", sha) moves refs/heads/feature through a gix ref transaction — it takes the same ref locks as git, appends to the reflog, and keeps packed-refs consistent. Never write refs/heads/* by hand: that bypasses locking, races with concurrent pushes, and resurrects deleted refs once the name is also in packed-refs. Pass expected_old="" to create-only, a 40-hex SHA for compare-and-swap, and target=None to delete. Non-fast-forward branch moves are refused unless force=True.
  • Switching active branch (HEAD): set_head(...) moves the symbolic HEAD reference under the same transaction. Editing the HEAD file directly has the same hazards as writing a branch by hand.
  • Merge strategies: execute_merge(..., strategy=...) offers the three forge buttons. "merge" (default) fast-forwards when it can and otherwise writes a two-parent merge commit; "squash" always writes exactly one commit on the base, defaulting to the concatenated feature commit summaries; "fast-forward" refuses anything that is not a fast-forward with GitRepositoryError (cannot fast-forward). A head that is already contained in the base reports "up-to-date" — a success, not a conflict.
  • Dry-run merges: preview_merge(repo_path, base_ref, head_ref) runs the same ORT tree merge and writes nothing — no tree, no commit, no ref — returning status, conflicts, and the tree_sha the merge would produce. Use it to show conflicts before the user clicks "Merge".

Engine Architecture: Pure gix vs. git2 Wire Streaming

rusty-git intentionally separates user-facing operations from network pack streaming:

  • 100% Pure gix Core (WebAssembly / Pyodide Ready): commit (atomic in-memory trees & commits), inspect (refs, tree blobs, histogram unified diffs), merge (3-way ORT tree merge, dry-run previews, and the merge/squash/fast-forward strategies) and ops (has_object, repository_stats, fsck, pack_refs) run entirely on pure-Rust gix. They require zero C headers and run in browsers and Pyodide.
  • Wire Protocol Pack Streaming (git2): Ingesting thin packs (git push) and streaming sliding-window delta packs (git clone/git fetch) use libgit2's battle-tested pack engine. Once gix-pack high-level streaming pack generation reaches full maturity, these remaining wire endpoints will transition to gix, completing the journey to 100% pure Rust.
  • Native-only maintenance (git2): repack and gc reuse that same pack engine — folding a whole object database into one delta-compressed pack is exactly the code not to hand-roll — so the gc module is compiled only for non-wasm32 targets (#[cfg(not(target_arch = "wasm32"))]), like the wire modules. fork_repository stays portable: it copies object and ref files (gix + std::fs) and never rewrites a pack.

This keeps rusty-git focused entirely on performance-critical operations without unnecessary file-I/O wrapper overhead.


Scope and Non-Goals

rusty-git is a Git engine, not a forge and not a web framework. That boundary is deliberate: the library does Git work in-process and the application owns everything around it.

In scope

  • In-process Git object, ref and merge operations on bare repositories — create_commit, update_ref, set_head, execute_merge, preview_merge, the inspect read surface, and the ops maintenance primitives (has_object, repository_stats, fsck, pack_refs, fork_repository, repack, gc — the last two native-only, see the architecture note above).
  • Smart-HTTP wire serving as bytes in / bytes out (advertise, upload_pack, receive_pack) with zero OS subprocesses.
  • Engine paths that stay pure gix and therefore compile for wasm32 (Pyodide) as well as native.

Out of scope - the application's job

Item Why it does not belong here
HTTP transport, routing, auth, TLS Not Git. The wire API is deliberately bytes-in/bytes-out; sockets, certificates and sessions belong to the server.
Hook execution (pre-receive etc.) Needs a process model and a trust boundary. The server should expose results, not run arbitrary code in-process.
Working-tree checkout / reset / clean This is a bare-repository library: no index, no worktree. create_commit builds trees in memory by design.
Submodule recursion / submodule update Requires network and a worktree; list_tree reports gitlinks, which is all a forge UI needs.
Git LFS A separate protocol (batch API) plus a storage service.
GPG/SSH signature verification Needs keyrings and a trust policy supplied by the application.
Code search, syntax highlighting, diff rendering Application/UI concerns; compare_refs returns data, not presentation.
PR/MR/issue objects, review comments, webhooks, notifications Product model, not Git.
Interactive rebase / cherry-pick / git am machinery preview_merge plus create_commit cover the forge merge-button strategies; interactive history rewriting is out of scope.
Repository deletion or renaming on disk Plain filesystem operations with no locking subtlety to encapsulate.
Credential helpers, ~/.gitconfig handling The library takes explicit arguments and never reads user configuration.

If a downstream project asks for one of these, the answer is the table above plus the recommended application-side approach - not a new export. The repo-root TODO-missing.md is the backlog and outcome log for the gaps that are in scope, and a boundary change has to be recorded there before it becomes a task.


Smart-HTTP Protocol Wire Support

rusty-git can drive Git HTTP and SSH protocol negotiation completely in-process:

Note on Transport & Auth (SSH / TLS): rusty-git operates directly on request/response byte streams rather than managing sockets. Transport encryption and authentication (SSH keys via asyncssh/OpenSSH, or TLS/mTLS client certs via Nginx/Caddy/HTTPX) happen cleanly at the transport layer before passing payloads to rusty-git.

import rusty_git

# Ref advertisement for git-upload-pack (git clone / fetch)
advert = await rusty_git.advertise("/srv/repos/myorg/backend.git", "git-upload-pack")

# Handle pack negotiation and streaming
upload_res = await rusty_git.upload_pack("/srv/repos/myorg/backend.git", request_body)

# Ingest inbound git push packfile atomically
push_res = await rusty_git.receive_pack("/srv/repos/myorg/backend.git", push_body)
print("Updated Refs:", push_res["updated_refs"])

Operations & Maintenance

Seven operations a long-lived forge needs, all in-process and exposed at the package root and on rusty_git.sync (they live in the ops and gc Rust modules):

import rusty_git

# Do we already have this object? (index lookup, no object is inflated)
if not await rusty_git.has_object("/srv/repos/app.git", sha):
    ...

# Dashboard numbers: refs, branches, tags, loose objects, packs, size
stats = await rusty_git.repository_stats("/srv/repos/app.git", deep=True)
print(stats["branch_count"], stats["object_count"], stats["disk_size_bytes"])

# Integrity check before a user finds the damage
report = await rusty_git.fsck("/srv/repos/app.git")
if not report["ok"]:
    print(report["errors"])  # sorted, each names the object and the ref/edge
print(report["dangling"])  # unreachable objects: reported, not an error

# Fold thousands of loose ref files into one sorted `packed-refs`
packed = await rusty_git.pack_refs("/srv/repos/app.git")  # 0 => already packed

# Fork: copy objects (hardlinked by default) and refs into a new bare repo
await rusty_git.fork_repository("/srv/repos/app.git", "/srv/repos/app-fork.git")

# Compact: fold every pack into one (a crash can only leave debris, never damage)
print(
    await rusty_git.repack("/srv/repos/app.git")
)  # {"packs_before": 12, "packs_after": 1, "objects": 431}

# Full maintenance: repack + pack-refs + de-duplicate loose objects.
# Pruning is opt-in because "unreachable" is not "unwanted": pass a grace period.
stats = await rusty_git.gc("/srv/repos/app.git", prune_expire_days=14)
print(stats["pack_count"], stats["loose_objects"], stats["disk_size_bytes"])

What each operation promises, and what it does not

  • has_object answers from the object index (loose names and pack indexes), so True means "present", not "decodes". A sha that is not 40 hex characters raises ValueError — a typo must not look like an absent object.

  • repository_stats reads the layout for loose_objects, pack_count and disk_size_bytes (so the numbers match git count-objects/du) and the object store for object_count. object_count is None unless deep=True because it walks the whole store and holds one hash set of ids: counts and sizes are O(files), object_count is O(objects) in time and memory. disk_size_bytes covers the git directory (.git for a non-bare repo), never the worktree, and is None under Pyodide.

  • fsck detects two classes of damage: dangling references (a ref, commit parent, commit tree, tag target or tree entry naming an object that is absent) and — with strict=True, the default — undecodable objects. It does not verify pack trailer hashes or recompute object ids, so a valid pack holding an object under the wrong id is invisible here; that is the same trade-off git fsck makes without --full. strict=False is a connectivity check that still reads object headers (the walk cannot descend without them) but never decodes or validates a payload — useful as a cheap pre-push gate. Submodule (gitlink) targets are not required to exist, exactly as in git fsck. Peak memory is two hash sets of object ids, a few dozen bytes per object.

  • pack_refs folds the loose ref files under refs/ into one sorted packed-refs (# pack-refs with: peeled fully-peeled sorted, ^-peeled annotated tags, atomic rename) and returns how many refs it moved; 0 means the store was already packed, so calling it twice is a no-op. It goes through gix's packed-ref transaction, which takes packed-refs.lock, renames the new file into place and only then deletes the loose files — an interruption leaves a duplicate ref, never a missing one, and a lock held elsewhere for more than a second is an error rather than a bypass. all=True (default) packs everything; all=False packs only refs/tags/*, matching git pack-refs without --all, which keeps actively-updated branches loose and therefore cheap to compare-and-swap. HEAD and other symbolic refs stay untouched (the format cannot represent them), and no reflog entry is written because no ref value changes. git show-ref output is identical afterwards, and update_ref keeps working on the packed entries — including target=None, which removes the packed-refs line.

  • fork_repository only ever reads the source, so it is safe to fork a repository that is serving traffic. Objects are copied before refs: a push landing mid-copy therefore makes the fork stale, never inconsistent — re-fork to catch up. hardlink=True (the default) hardlinks object files, so the fork costs ref metadata instead of a full copy and stays readable even if the source is later pruned or deleted; filesystems that refuse a link (EXDEV, EPERM, FAT/SMB) fall back to a copy per file. Refs, HEAD, packed-refs and shallow are always copied, never linked — a shared ref file would let a push to the fork move a branch in the source. config is deliberately not copied (same reason git clone rewrites it): configure the fork yourself. A destination that exists and is not empty is refused with GitRepositoryError, and so is one that is, contains, or sits inside the source.

  • repack folds every object a reference (or HEAD) reaches into one pack, writes it beside the existing packs, fsyncs it, and only then deletes the packs it superseded — so a crash at any point leaves a readable repository, at worst with unreferenced debris that the next run folds in. A pack only becomes usable when its .idx exists, so a concurrent list_commits cannot see a half-written pack, and a reader already walking history keeps its open files alive. packs_after == 1 means the compaction worked; objects is the size of the new pack, which equals git rev-list --objects --all. Packs carrying a .keep file are left alone, and unreachable objects are neither copied nor deleted. Requires git2's pack builder, so it is native-only (no Pyodide).

  • gc runs repack, folds loose refs into packed-refs, and deletes the loose objects the new pack made redundant — losing the redundant file is what actually shrinks the repository. Pruning is opt-in: prune_expire_days defaults to None ("never delete"), because "no ref reaches it" does not mean "nothing needs it" — a push in flight and anything a reflog could recover are both unreachable and both young, so anything younger than the period survives whatever you pass. prune_expire_days=0 is for a caller who has just read the dangling list from fsck. Packs are never deleted beyond the ones the repack superseded. Run one gc per repository at a time: it does not take git gc's gc.pid lock, so a scheduled task should own the repository, not a request handler.

  • Push quarantine — receive_pack indexes the inbound pack into a private object database (objects/incoming-<unique>/, a throwaway bare repository whose objects/info/alternates names the real one, so thin-pack fix-up still resolves) and only migrates those objects into the real ODB once a ref is actually going to move. A refused push — non-fast-forward, stale lease, malformed pack — therefore leaves the repository byte-for-byte unchanged, which is what stops a client that can push from growing it without bound. The quarantine is deleted on every path, including a panic. Pass receive_pack(..., quarantine=False) for the previous behaviour (ingest straight into the real ODB); it is kept for one release as a fallback.

Not implemented, by design

  • Server-side clone from a remote URL — there is no network transport in this build: gix's clone/fetch path is gated behind blocking-network-client/async-network-client, and this crate enables neither (compiling PrepareFetch::fetch_only against the shipped feature set fails with error[E0599]). Enabling one means adding a TLS stack and credentials handling to a statically-linked wheel — a packaging decision, not an API gap. Import out of band (git clone --mirror in the pipeline, or a one-shot fetch in the application), then use fork_repository for in-process copies.
  • Reflog expiry, commit-graph and multi-pack-index writing — gc prunes by ref-reachability plus a grace period, deliberately not by reflog reachability: it never expires a reflog, so anything a reflog could recover is protected by age alone. Treat the grace period as the safety margin that git gc gets from its reflog expiry.

Development & Testing

Rust Tests

cargo test

Python Integration Tests

uv run pytest

License

Apache-2.0 © Framework M Contributors

Metadata

Release files for rusty-git 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rusty-git 0.4.0
File Size Uploaded Provenance Actions
rusty_git-0.4.0.tar.gz 180.6 kB Without provenance Details for rusty_git-0.4.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for rusty-git 0.4.0
File Actions
rusty_git-0.4.0-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details for rusty_git-0.4.0-cp312-abi3-win_amd64.whl
rusty_git-0.4.0-cp312-abi3-pyemscripten_2024_0_wasm32.whl CPython 3.12 abi3 PyEmscripten 2024.0+ WebAssembly Details for rusty_git-0.4.0-cp312-abi3-pyemscripten_2024_0_wasm32.whl
rusty_git-0.4.0-cp312-abi3-musllinux_1_2_x86_64.whl CPython 3.12 abi3 Linux musl 1.2+ x86-64 Details for rusty_git-0.4.0-cp312-abi3-musllinux_1_2_x86_64.whl
rusty_git-0.4.0-cp312-abi3-musllinux_1_2_aarch64.whl CPython 3.12 abi3 Linux musl 1.2+ ARM64 Details for rusty_git-0.4.0-cp312-abi3-musllinux_1_2_aarch64.whl
rusty_git-0.4.0-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.12 abi3 Linux glibc 2.17+ x86-64 Details for rusty_git-0.4.0-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
rusty_git-0.4.0-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.12 abi3 Linux glibc 2.17+ ARM64 Details for rusty_git-0.4.0-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
rusty_git-0.4.0-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details for rusty_git-0.4.0-cp312-abi3-macosx_11_0_arm64.whl
rusty_git-0.4.0-cp312-abi3-macosx_10_12_x86_64.whl CPython 3.12 abi3 macOS 10.12+ x86-64 Details for rusty_git-0.4.0-cp312-abi3-macosx_10_12_x86_64.whl

Total release size: 31.0 MB

Release files / rusty_git-0.4.0.tar.gz

Download URL rusty_git-0.4.0.tar.gz
Size 180.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f1ec57c0779cc001efef9fed8935364b73ac6a2761c301d25b672e8714a89d1d
BLAKE2b-256 checksum
How to use checksums
d589b4110cdbc77278ace5ab0f4ae04d041d931f74b9f83f06844a8391fe34d0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-win_amd64.whl

Download URL rusty_git-0.4.0-cp312-abi3-win_amd64.whl
Size 6.2 MB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
0e608a11177d7325141f36d76a45909a9f847f45458462c409192ebf72606f6b
BLAKE2b-256 checksum
How to use checksums
8427afde8a698f953528d2b4254d5c152c35196dfd9a2855f18d235507e7d6d4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-pyemscripten_2024_0_wasm32.whl

Download URL rusty_git-0.4.0-cp312-abi3-pyemscripten_2024_0_wasm32.whl
Size 1.9 MB
Tags CPython 3.12 PyEmscripten 2024.0+ WebAssembly abi3
SHA-256 checksum
How to use checksums
0029b4a0086db42c65c7447a92cd774c62d008680569b04de43a28ab163226ae
BLAKE2b-256 checksum
How to use checksums
ff8985828fa1c877c16b235cd5cee5361c653851381aa8f564e3918559d6b96b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-musllinux_1_2_x86_64.whl

Download URL rusty_git-0.4.0-cp312-abi3-musllinux_1_2_x86_64.whl
Size 3.9 MB
Tags CPython 3.12 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
cb73cd682524ab4d468934cda366cac95b7a454a0841f2e632243bce7cac2d9a
BLAKE2b-256 checksum
How to use checksums
44ff847eb4671a1db1d80cd5b2b7c299f3871ef4571fa4d37a1aaa9d097ba4e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-musllinux_1_2_aarch64.whl

Download URL rusty_git-0.4.0-cp312-abi3-musllinux_1_2_aarch64.whl
Size 3.6 MB
Tags CPython 3.12 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
7f7d941a58b3f35bc8b38c3e246ff2ef27881dce5fcdd3ddc0eaab42d35ce1ec
BLAKE2b-256 checksum
How to use checksums
360ecb7c71fac9f34fe8a69e5fa36491408ce86b32662fa26b9d26f8db46e376
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL rusty_git-0.4.0-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 3.8 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
180b2b213f6199d188b3c7239f8da954100d30839b40b1dae9c5870e2ac94624
BLAKE2b-256 checksum
How to use checksums
dd1566d1771edf58b5aeb40f51d01afc017a424490856075e5db18e08a316c34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL rusty_git-0.4.0-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 3.6 MB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
20e866f34faffbe176bb745ff963e7395006e168d4b6205d7b66084d1a67a3c7
BLAKE2b-256 checksum
How to use checksums
246d52d32f78801fb6b507cebf3e7864059873ae11059779b5ac9c34dc08edd8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-macosx_11_0_arm64.whl

Download URL rusty_git-0.4.0-cp312-abi3-macosx_11_0_arm64.whl
Size 3.8 MB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
3d40d2486415632876b812a1230079e29636678ea829697ef802176e8be7382e
BLAKE2b-256 checksum
How to use checksums
99e923dbbb536fd3920d80c1d2bac8afce9132b8fe98eceda59f2822822b3736
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Release files / rusty_git-0.4.0-cp312-abi3-macosx_10_12_x86_64.whl

Download URL rusty_git-0.4.0-cp312-abi3-macosx_10_12_x86_64.whl
Size 4.0 MB
Tags CPython 3.12 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
3dd60def90def995b26a47ac658700d71941270c8936f4edce297dfe58422daa
BLAKE2b-256 checksum
How to use checksums
09fe53550c60d0e79c18f2a75dc2b5e7aefa4b435f5f38e23c0b68d5c53e0752
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.16

Security for rusty-git 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page