|
1 | | -# `libvcs` · [](https://pypi.org/project/libvcs/) [](https://github.com/vcs-python/libvcs/blob/master/LICENSE) [](https://codecov.io/gh/vcs-python/libvcs) |
| 1 | +# libvcs |
2 | 2 |
|
3 | | -libvcs is a lite, [typed](https://docs.python.org/3/library/typing.html), pythonic tool box for |
4 | | -detection and parsing of URLs, commanding, and syncing with `git`, `hg`, and `svn`. Powers |
5 | | -[vcspull](https://www.github.com/vcs-python/vcspull/). |
| 3 | +[](https://pypi.org/project/libvcs/) |
| 4 | +[](https://pypi.org/project/libvcs/) |
| 5 | +[](https://github.com/vcs-python/libvcs/actions) |
| 6 | +[](https://codecov.io/gh/vcs-python/libvcs) |
| 7 | +[](https://github.com/vcs-python/libvcs/blob/master/LICENSE) |
6 | 8 |
|
7 | | -## Overview |
| 9 | +> **The Swiss Army Knife for Version Control Systems in Python.** |
8 | 10 |
|
9 | | -### Key Features |
| 11 | +**libvcs** provides a unified, [typed](https://docs.python.org/3/library/typing.html), and pythonic interface for managing Git, Mercurial, and Subversion repositories. Whether you're building a deployment tool, a developer utility, or just need to clone a repo in a script, libvcs handles the heavy lifting. |
10 | 12 |
|
11 | | -- **URL Detection and Parsing**: Validate and parse Git, Mercurial, and Subversion URLs. |
12 | | -- **Command Abstraction**: Interact with VCS systems through a Python API. |
13 | | -- **Repository Synchronization**: Clone and update repositories locally via |
14 | | - Python API. |
15 | | -- **py.test fixtures**: Create temporary local repositories and working copies for testing for unit tests. |
| 13 | +It powers [vcspull](https://github.com/vcs-python/vcspull) and simplifies VCS interactions down to a few lines of code. |
16 | 14 |
|
17 | | -_Supports Python 3.10 and above, Git (including AWS CodeCommit), Subversion, and Mercurial._ |
| 15 | +--- |
18 | 16 |
|
19 | | -To **get started**, see the [quickstart guide](https://libvcs.git-pull.com/quickstart.html) for more information. |
| 17 | +## Features at a Glance |
20 | 18 |
|
21 | | -```console |
22 | | -$ pip install --user libvcs |
23 | | -``` |
24 | | - |
25 | | -## URL Detection and Parsing |
26 | | - |
27 | | -Easily validate and parse VCS URLs using the |
28 | | -[`libvcs.url`](https://libvcs.git-pull.com/url/index.html) module: |
| 19 | +- **🔄 Repository Synchronization**: Clone, update, and manage local repository copies with a high-level API. |
| 20 | +- **🛠 Command Abstraction**: Speak fluent `git`, `hg`, and `svn` through fully-typed Python objects. |
| 21 | +- **🔗 URL Parsing**: Robustly validate, parse, and manipulate VCS URLs (including SCP-style). |
| 22 | +- **🧪 Pytest Fixtures**: Batteries-included fixtures for spinning up temporary repositories in your test suite. |
29 | 23 |
|
30 | | -### Validate URLs |
| 24 | +## Installation |
31 | 25 |
|
32 | | -```python |
33 | | ->>> from libvcs.url.git import GitURL |
34 | | - |
35 | | ->>> GitURL.is_valid(url='https://github.com/vcs-python/libvcs.git') |
36 | | -True |
| 26 | +```bash |
| 27 | +pip install libvcs |
37 | 28 | ``` |
38 | 29 |
|
39 | | -### Parse and adjust Git URLs: |
| 30 | +## Usage |
40 | 31 |
|
41 | | -```python |
42 | | ->>> from libvcs.url.git import GitURL |
| 32 | +### 1. Synchronize Repositories |
| 33 | +Clone and update repositories with a consistent API, regardless of the VCS. |
43 | 34 |
|
44 | | ->>> git_location = GitURL(url='git@github.com:vcs-python/libvcs.git') |
45 | | - |
46 | | ->>> git_location |
47 | | -GitURL(url=git@github.com:vcs-python/libvcs.git, |
48 | | - user=git, |
49 | | - hostname=github.com, |
50 | | - path=vcs-python/libvcs, |
51 | | - suffix=.git, |
52 | | - rule=core-git-scp) |
53 | | -``` |
54 | | - |
55 | | -Switch repo libvcs -> vcspull: |
| 35 | +[**Learn more about Synchronization**](https://libvcs.git-pull.com/sync/) |
56 | 36 |
|
57 | 37 | ```python |
58 | | ->>> from libvcs.url.git import GitURL |
59 | | - |
60 | | ->>> git_location = GitURL(url='git@github.com:vcs-python/libvcs.git') |
61 | | - |
62 | | ->>> git_location.path = 'vcs-python/vcspull' |
| 38 | +import pathlib |
| 39 | +from libvcs.sync.git import GitSync |
63 | 40 |
|
64 | | ->>> git_location.to_url() |
65 | | -'git@github.com:vcs-python/vcspull.git' |
| 41 | +# Define your repository |
| 42 | +repo = GitSync( |
| 43 | + url="https://github.com/vcs-python/libvcs", |
| 44 | + path=pathlib.Path.cwd() / "libvcs", |
| 45 | + remotes={ |
| 46 | + 'gitlab': 'https://gitlab.com/vcs-python/libvcs' |
| 47 | + } |
| 48 | +) |
66 | 49 |
|
67 | | -# Switch them to gitlab: |
68 | | ->>> git_location.hostname = 'gitlab.com' |
| 50 | +# Clone (if not exists) or fetch & update (if exists) |
| 51 | +repo.update_repo() |
69 | 52 |
|
70 | | -# Export to a `git clone` compatible URL. |
71 | | ->>> git_location.to_url() |
72 | | -'git@gitlab.com:vcs-python/vcspull.git' |
| 53 | +print(f"Current revision: {repo.get_revision()}") |
73 | 54 | ``` |
74 | 55 |
|
75 | | -See more in the [parser document](https://libvcs.git-pull.com/parse/index.html). |
76 | | - |
77 | | -## Command Abstraction |
78 | | - |
79 | | -Abstracts CLI commands for `git(1)`, `hg(1)`, `svn(1)` via a lightweight [`subprocess`](https://docs.python.org/3/library/subprocess.html) wrapper. |
| 56 | +### 2. Command Abstraction |
| 57 | +Access the full power of the underlying CLI tools without parsing string output manually. |
80 | 58 |
|
81 | | -### Run Git Commands |
| 59 | +[**Learn more about Command Abstraction**](https://libvcs.git-pull.com/cmd/) |
82 | 60 |
|
83 | 61 | ```python |
84 | 62 | import pathlib |
85 | 63 | from libvcs.cmd.git import Git |
86 | 64 |
|
87 | | -git = Git(path=pathlib.Path.cwd() / 'my_git_repo') |
88 | | -git.clone(url='https://github.com/vcs-python/libvcs.git') |
89 | | -``` |
90 | | - |
91 | | -Above: [`libvcs.cmd.git.Git`](https://libvcs.git-pull.com/cmd/git.html#libvcs.cmd.git.Git) using |
92 | | -[`Git.clone()`](http://libvcs.git-pull.com/cmd/git.html#libvcs.cmd.git.Git.clone). |
93 | | - |
94 | | -### Manage Branches, Tags, and More |
95 | | - |
96 | | -Work with git subcommands using typed Python objects: |
| 65 | +# Initialize the wrapper |
| 66 | +git = Git(path=pathlib.Path.cwd() / 'libvcs') |
97 | 67 |
|
98 | | -```python |
99 | | -from libvcs.cmd.git import Git |
100 | | - |
101 | | -git = Git(path='/path/to/repo') |
102 | | - |
103 | | -# Branches |
104 | | -branches = git.branches.ls() # List all branches |
105 | | -git.branches.create('feature-branch') # Create a branch |
| 68 | +# Run commands intuitively |
| 69 | +git.clone(url='https://github.com/vcs-python/libvcs.git') |
| 70 | +git.checkout(ref='master') |
106 | 71 |
|
107 | | -# Tags |
108 | | -git.tags.create(name='v1.0.0', message='Release') |
109 | | -tags = git.tags.ls() |
| 72 | +# Branch management |
| 73 | +git.branches.create('feature/new-gui') |
| 74 | +print(git.branches.ls()) # List all branches |
110 | 75 |
|
111 | | -# Remotes |
112 | | -remotes = git.remotes.ls() |
113 | | -remote = git.remotes.get(remote_name='origin') |
114 | | -remote.prune() |
| 76 | +# Remote management |
| 77 | +git.remotes.set_url(name='origin', url='git@github.com:vcs-python/libvcs.git') |
115 | 78 | ``` |
116 | 79 |
|
117 | | -See the [Manager/Cmd pattern documentation](https://libvcs.git-pull.com/cmd/git/index.html) for more. |
118 | | - |
119 | | -## Repository Synchronization |
| 80 | +### 3. URL Parsing |
| 81 | +Stop writing regex for Git URLs. Let `libvcs` handle the edge cases. |
120 | 82 |
|
121 | | -Synchronize your repositories using the |
122 | | -[`libvcs.sync`](https://libvcs.git-pull.com/sync/) module. |
123 | | - |
124 | | -### Clone and Update Repositories |
| 83 | +[**Learn more about URL Parsing**](https://libvcs.git-pull.com/url/) |
125 | 84 |
|
126 | 85 | ```python |
127 | | -import pathlib |
128 | | -from libvcs.sync.git import GitSync |
| 86 | +from libvcs.url.git import GitURL |
129 | 87 |
|
130 | | -repo = GitSync( |
131 | | - url="https://github.com/vcs-python/libvcs", |
132 | | - path=pathlib.Path().cwd() / "my_repo", |
133 | | - remotes={ |
134 | | - 'gitlab': 'https://gitlab.com/vcs-python/libvcs' |
135 | | - } |
136 | | -) |
| 88 | +# Parse complex URLs |
| 89 | +url = GitURL(url='git@github.com:vcs-python/libvcs.git') |
137 | 90 |
|
138 | | -# Update / clone repo: |
139 | | ->>> repo.update_repo() |
| 91 | +print(url.user) # 'git' |
| 92 | +print(url.hostname) # 'github.com' |
| 93 | +print(url.path) # 'vcs-python/libvcs' |
140 | 94 |
|
141 | | -# Get revision: |
142 | | ->>> repo.get_revision() |
143 | | -u'5c227e6ab4aab44bf097da2e088b0ff947370ab8' |
| 95 | +# Transform URLs |
| 96 | +url.hostname = 'gitlab.com' |
| 97 | +print(url.to_url()) # 'git@gitlab.com:vcs-python/libvcs.git' |
144 | 98 | ``` |
145 | 99 |
|
146 | | -Above: [`libvcs.sync.git.GitSync`](https://libvcs.git-pull.com/projects/git.html#libvcs.sync.git.GitSync) repository |
147 | | -object using |
148 | | -[`GitSync.update_repo()`](https://libvcs.git-pull.com/sync/git.html#libvcs.sync.git.GitSync.update_repo) |
149 | | -and |
150 | | -[`GitSync.get_revision()`](https://libvcs.git-pull.com/sync/git.html#libvcs.sync.git.GitSync.get_revision). |
| 100 | +### 4. Testing with Pytest |
| 101 | +Writing a tool that interacts with VCS? Use our fixtures to keep your tests clean and isolated. |
151 | 102 |
|
152 | | -## Pytest plugin: Temporary VCS repositories for testing |
153 | | - |
154 | | -libvcs [pytest plugin](https://libvcs.git-pull.com/pytest-plugin.html) provides [py.test fixtures] to swiftly create local VCS repositories and working repositories to test with. Repositories are automatically cleaned on test teardown. |
155 | | - |
156 | | -[py.test fixtures]: https://docs.pytest.org/en/8.2.x/explanation/fixtures.html |
157 | | - |
158 | | -### Use temporary, local VCS in py.test |
| 103 | +[**Learn more about Pytest Fixtures**](https://libvcs.git-pull.com/pytest-plugin.html) |
159 | 104 |
|
160 | 105 | ```python |
161 | 106 | import pathlib |
162 | | - |
163 | 107 | from libvcs.pytest_plugin import CreateRepoPytestFixtureFn |
164 | 108 | from libvcs.sync.git import GitSync |
165 | 109 |
|
166 | | - |
167 | | -def test_repo_git_remote_checkout( |
| 110 | +def test_my_git_tool( |
168 | 111 | create_git_remote_repo: CreateRepoPytestFixtureFn, |
169 | | - tmp_path: pathlib.Path, |
170 | | - projects_path: pathlib.Path, |
171 | | -) -> None: |
| 112 | + tmp_path: pathlib.Path |
| 113 | +): |
| 114 | + # Spin up a real, temporary Git server |
172 | 115 | git_server = create_git_remote_repo() |
173 | | - git_repo_checkout_dir = projects_path / "my_git_checkout" |
174 | | - git_repo = GitSync(path=str(git_repo_checkout_dir), url=f"file://{git_server!s}") |
| 116 | + |
| 117 | + # Clone it to a temporary directory |
| 118 | + checkout_path = tmp_path / "checkout" |
| 119 | + repo = GitSync(path=checkout_path, url=f"file://{git_server}") |
| 120 | + repo.obtain() |
| 121 | + |
| 122 | + assert checkout_path.exists() |
| 123 | + assert (checkout_path / ".git").is_dir() |
| 124 | +``` |
175 | 125 |
|
176 | | - git_repo.obtain() |
177 | | - git_repo.update_repo() |
| 126 | +## Project Information |
178 | 127 |
|
179 | | - assert git_repo.get_revision() == "initial" |
| 128 | +- **Python Support**: 3.10+ |
| 129 | +- **VCS Support**: Git, Mercurial (hg), Subversion (svn) |
| 130 | +- **License**: MIT |
180 | 131 |
|
181 | | - assert git_repo_checkout_dir.exists() |
182 | | - assert pathlib.Path(git_repo_checkout_dir / ".git").exists() |
183 | | -``` |
| 132 | +## Links & Resources |
| 133 | + |
| 134 | +- **Documentation**: [libvcs.git-pull.com](https://libvcs.git-pull.com) |
| 135 | +- **Source Code**: [github.com/vcs-python/libvcs](https://github.com/vcs-python/libvcs) |
| 136 | +- **Issue Tracker**: [GitHub Issues](https://github.com/vcs-python/libvcs/issues) |
| 137 | +- **Changelog**: [History](https://libvcs.git-pull.com/history.html) |
| 138 | +- **PyPI**: [pypi.org/project/libvcs](https://pypi.org/project/libvcs/) |
| 139 | + |
| 140 | +## Support |
| 141 | + |
| 142 | +Your donations fund development of new features, testing, and support. |
184 | 143 |
|
185 | | -Under the hood: fixtures bootstrap a temporary `$HOME` environment in a |
186 | | -[`TmpPathFactory`](https://docs.pytest.org/en/7.1.x/reference/reference.html#tmp-path-factory-factory-api) |
187 | | -for automatic cleanup and `pytest-xdist` compatibility.. |
188 | | - |
189 | | -## Donations |
190 | | - |
191 | | -Your donations fund development of new features, testing and support. Your money will go directly to |
192 | | -maintenance and development of the project. If you are an individual, feel free to give whatever |
193 | | -feels right for the value you get out of the project. |
194 | | - |
195 | | -See donation options at <https://tony.sh/support.html>. |
196 | | - |
197 | | -## More information |
198 | | - |
199 | | -- Python support: 3.9+, pypy |
200 | | -- VCS supported: git(1), svn(1), hg(1) |
201 | | -- Source: <https://github.com/vcs-python/libvcs> |
202 | | -- Docs: <https://libvcs.git-pull.com> |
203 | | -- Changelog: <https://libvcs.git-pull.com/history.html> |
204 | | -- APIs for git, hg, and svn: |
205 | | - - [`libvcs.url`](https://libvcs.git-pull.com/url/): URL Parser |
206 | | - - [`libvcs.cmd`](https://libvcs.git-pull.com/cmd/): Commands |
207 | | - - [`libvcs.sync`](https://libvcs.git-pull.com/sync/): Clone and update |
208 | | -- Issues: <https://github.com/vcs-python/libvcs/issues> |
209 | | -- Test Coverage: <https://codecov.io/gh/vcs-python/libvcs> |
210 | | -- pypi: <https://pypi.python.org/pypi/libvcs> |
211 | | -- Open Hub: <https://www.openhub.net/p/libvcs> |
212 | | -- License: [MIT](https://opensource.org/licenses/MIT). |
213 | | - |
214 | | -[](https://libvcs.git-pull.com/) |
215 | | -[](https://github.com/vcs-python/libvcs/actions?query=workflow%3A%22tests%22) |
| 144 | +- [Donation Options](https://tony.sh/support.html) |
0 commit comments