Skip to main content
libvcs logo

libvcs

A typed Python interface for Git, Mercurial, and Subversion repositories.

PyPI version Python versions Tests status Coverage License

libvcs parses and validates Git, Mercurial, and Subversion URLs, wraps each VCS's command-line tool in a typed Python object, and synchronizes a local checkout against a remote — cloning it if it does not exist, fetching and updating it if it does. It also ships a pytest plugin for creating disposable repositories in your own test suite.

It powers vcspull, which uses it to sync many repositories from a single config file.


Features at a Glance

  • Repository synchronization: One obtain() / update_repo() call clones a repository if it is missing and fetches it if it already exists, the same way for git, hg, and svn.
  • Command abstraction: Call git, hg, and svn through typed Python objects instead of shelling out and parsing text yourself.
  • URL parsing: Parse, validate, and transform VCS URLs, including SCP-style git@host:path remotes.
  • Pytest fixtures: Create disposable local git, hg, and svn repositories for your own tests, with per-test isolation.

Installation

$ pip install libvcs

With uv:

$ uv add libvcs

Try it interactively:

$ uvx --with libvcs ipython

libvcs is pre-1.0: a minor version bump (0.45 to 0.46) may change the public API. Pin a version range in projects to avoid surprises:

# pyproject.toml
dependencies = ["libvcs>=0.45,<0.46"]

Usage

1. Synchronize Repositories

GitSync, HgSync, and SvnSync give the same two calls regardless of the underlying VCS: obtain() clones if the path does not exist yet, and update_repo() does that or fetches and updates an existing checkout — call it either way and let libvcs decide.

Learn more about Synchronization

import pathlib
from libvcs.sync.git import GitSync

# Define your repository
repo = GitSync(
    url="https://github.com/vcs-python/libvcs",
    path=pathlib.Path.cwd() / "libvcs",
    remotes={"gitlab": "https://gitlab.com/vcs-python/libvcs"},
)

# Clone (if not exists) or fetch & update (if exists)
result = repo.update_repo()

if result.ok:
    print(f"Current revision: {repo.get_revision()}")
else:
    for error in result.errors:
        print(f"Sync failed at {error.step}: {error.message}")

2. Command Abstraction

Git, Hg, and Svn wrap the binary directly — each call maps to one subprocess invocation of the real VCS tool, so there is no divergent reimplementation to trust. Branches, remotes, and tags are also reachable through QueryList, which filters like a Django ORM queryset.

Learn more about Command Abstraction

import pathlib
from libvcs.cmd.git import Git

# Initialize the wrapper
git = Git(path=pathlib.Path.cwd() / "libvcs")

# Run commands directly
git.clone(url="https://github.com/vcs-python/libvcs.git")
git.checkout(ref="master")

# Traverse branches with ORM-like filtering
git.branches.create("feature/new-gui")
print(git.branches.ls())  # Returns QueryList for filtering

# Target specific entities with contextual commands
git.remotes.set_url(name="origin", url="git@github.com:vcs-python/libvcs.git")
git.tags.create(name="v1.0.0", message="Release version 1.0.0")

3. URL Parsing

GitURL, HgURL, and SvnURL parse and validate VCS URLs — including SCP-style git remotes — without hand-written regular expressions, and let you rewrite a parsed URL's parts back into a valid URL string.

Learn more about URL Parsing

from libvcs.url.git import GitURL

# Validate URLs
GitURL.is_valid(url="https://github.com/vcs-python/libvcs.git")  # True

# Parse complex URLs
url = GitURL(url="git@github.com:vcs-python/libvcs.git")

print(url.user)  # 'git'
print(url.hostname)  # 'github.com'
print(url.path)  # 'vcs-python/libvcs'

# Transform URLs
url.hostname = "gitlab.com"
print(url.to_url())  # 'git@gitlab.com:vcs-python/libvcs.git'

4. Testing with Pytest

The bundled pytest plugin builds a real, temporary VCS repository per test and tears it down after — no network access, no shared state between tests. A VCS's fixtures are only available when its binary is installed.

Learn more about Pytest Fixtures

import pathlib
from libvcs.pytest_plugin import CreateRepoFn
from libvcs.sync.git import GitSync


def test_my_git_tool(create_git_remote_repo: CreateRepoFn, tmp_path: pathlib.Path):
    # Spin up a real, temporary Git server
    git_server = create_git_remote_repo()

    # Clone it to a temporary directory
    checkout_path = tmp_path / "checkout"
    repo = GitSync(path=checkout_path, url=f"file://{git_server}")
    repo.obtain()

    assert checkout_path.exists()
    assert (checkout_path / ".git").is_dir()

Project Information

  • Python Support: 3.10+
  • VCS Support: Git (including AWS CodeCommit), Mercurial (hg), Subversion (svn)
  • License: MIT

Links & Resources

Support

Your donations fund development of new features, testing, and support.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

libvcs-0.46.0.tar.gz (689.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

libvcs-0.46.0-py3-none-any.whl (108.1 kB view details)

Uploaded Python 3

File details

Details for the file libvcs-0.46.0.tar.gz.

File metadata

  • Download URL: libvcs-0.46.0.tar.gz
  • Upload date:
  • Size: 689.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for libvcs-0.46.0.tar.gz
Algorithm Hash digest
SHA256 044736940c9c7db30ca070c87c681249933667eae603e46e75ac7519a3f4414c
MD5 406e3e9a6e89acd234d48feff6cd5db0
BLAKE2b-256 a2156a18d8dc2c44ce4f11fac06d03a2ea307c216deb32b4dbfc1cf3b986fb9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for libvcs-0.46.0.tar.gz:

Publisher: tests.yml on vcs-python/libvcs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file libvcs-0.46.0-py3-none-any.whl.

File metadata

  • Download URL: libvcs-0.46.0-py3-none-any.whl
  • Upload date:
  • Size: 108.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for libvcs-0.46.0-py3-none-any.whl
Algorithm Hash digest
SHA256 285f4e4c87db31922dd7ab523a306492a4618fd7c50274c14cd7229d3a634e9b
MD5 50ea52fe083e769152dd0e465f9db6f0
BLAKE2b-256 bd4e004f622d8b2865ebcb00870b0254ccc20de177b7fd35fca26f6afbb04056

See more details on using hashes here.

Provenance

The following attestation bundles were made for libvcs-0.46.0-py3-none-any.whl:

Publisher: tests.yml on vcs-python/libvcs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.46.0 This release

2 files

0.45.1

2 files

0.45.0

2 files

0.44.0

2 files

0.43.0

2 files

0.42.0

2 files

0.41.0

2 files

0.40.0

2 files

0.39.0

2 files

0.38.6

2 files

0.38.5

2 files

0.38.4

2 files

0.38.3

2 files

0.38.2

2 files

0.38.1

2 files

0.38.0

2 files

0.37.0

2 files

0.36.0

2 files

0.35.1

2 files

0.35.0

2 files

0.34.0

2 files

0.33.0

2 files

0.32.3

2 files

0.32.2

2 files

0.32.1

2 files

0.32.0

2 files

0.31.0

2 files

0.30.1

2 files

0.30.0

2 files

0.29.0

2 files

0.28.2

2 files

0.28.1

2 files

0.28.0

2 files

0.27.0

2 files

0.26.0

2 files

0.25.1

2 files

0.25.0

2 files

0.24.0

2 files

0.23.0.post0

2 files

0.23.0

2 files

0.22.2

2 files

0.22.1

2 files

0.22.0

2 files

0.21.2

2 files

0.21.1

2 files

0.21.0

2 files

0.20.0

2 files

0.19.1

2 files

0.19.0

2 files

0.18.1

2 files

0.18.0

2 files

0.17.0

2 files

0.16.5

2 files

0.16.4

2 files

0.16.3

2 files

0.16.2

2 files

0.16.1

2 files

0.16.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.7

2 files

0.13.6

2 files

0.13.5

2 files

0.13.4

2 files

0.13.3

2 files

0.13.2

2 files

0.13.1

2 files

0.13.0

2 files

0.12.4

2 files

0.12.3

2 files

0.12.2

2 files

0.12.1

2 files

0.12.0

2 files

0.11.1

2 files

0.11.0

2 files

0.10.1

2 files

0.10.0

2 files

0.9.0

2 files

0.5.0

2 files

0.4.4

1 file

0.4.3

1 file

0.4.2

1 file

0.4.1

1 file

0.4.0

1 file

0.3.3

1 file

0.3.2

1 file

0.3.1.post1

1 file

0.3.1

1 file

0.3.0

1 file

0.2.3

1 file

0.2.2

1 file

0.2.1

1 file

0.2.0

1 file

0.1.7

1 file

0.1.6

1 file

0.1.5

1 file

0.1.4

1 file

0.1.3

1 file

0.1.2

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