diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 8bfb3542b..000000000
--- a/.coveragerc
+++ /dev/null
@@ -1,14 +0,0 @@
-[run]
-omit =
-    */_*
-    pkg/*
-    */log.py
-    */conftest.py
-
-[report]
-exclude_lines =
-    pragma: no cover
-    def __repr__
-    raise NotImplementedError
-    if __name__ == .__main__.:
-    def parse_args
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index e69de29bb..000000000
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
deleted file mode 100644
index db0347ee1..000000000
--- a/.pre-commit-config.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-repos:
--   repo: https://github.com/psf/black
-    rev: 22.3.0
-    hooks:
-    - id: black
-      language_version: python3.10
-- repo: https://github.com/pycqa/isort
-  rev: 5.10.1
-  hooks:
-    - id: isort
-      name: isort (python)
--   repo: https://github.com/PyCQA/flake8
-    rev: 4.0.1
-    hooks:
-    - id: flake8
diff --git a/.tmuxp-before-script.sh b/.tmuxp-before-script.sh
deleted file mode 100755
index 0721faabd..000000000
--- a/.tmuxp-before-script.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-poetry shell --no-ansi --no-interaction &2> /dev/null
-poetry install --no-ansi --no-interaction &2> /dev/null
diff --git a/.tmuxp.yaml b/.tmuxp.yaml
deleted file mode 100644
index e9c122e38..000000000
--- a/.tmuxp.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-session_name: libvcs
-start_directory: ./ # load session relative to config location (project root).
-before_script: ./.tmuxp-before-script.sh
-shell_command_before:
-- '[ -f .venv/bin/activate ] && source .venv/bin/activate && reset'
-windows:
-- window_name: libvcs
-  focus: True
-  layout: main-horizontal
-  options:
-    main-pane-height: 35
-  panes:
-  - focus: true
-  - pane
-  - make start
-- window_name: docs
-  layout: main-horizontal
-  options:
-    main-pane-height: 35
-  start_directory: docs/
-  panes:
-  - focus: true
-  - pane
-  - pane
-  - make start
diff --git a/CHANGES b/CHANGES
deleted file mode 100644
index c1ea56454..000000000
--- a/CHANGES
+++ /dev/null
@@ -1,680 +0,0 @@
-# Changelog
-
-To install the unreleased libvcs version, see
-[developmental releases](https://libvcs.git-pull.com/quickstart.html#developmental-releases).
-
-[pip](https://pip.pypa.io/en/stable/):
-
-```console
-$ pip install --user --upgrade --pre libvcs
-```
-
-## libvcs 0.14.0 (unreleased)
-
-- _Add your latest changes from PRs here_
-
-### What's new
-
-- New and improved logo
-- **Parser**: Experimental VCS URL parsing added ({issue}`376`, {issue}`381`, {issue}`384`,
-  {issue}`386`):
-
-  VCS Parsers return {func}`dataclasses.dataclass` instances. The new tools support validation,
-  parsing, mutating and exporting into URLs consumable by the VCS.
-
-  ::: {warning}
-
-  APIs are unstable and subject to break until we get it right.
-
-  :::
-
-  - {mod}`libvcs.parse.git`
-
-    - {class}`~libvcs.parse.git.GitBaseURL` - Parse git URLs, `git(1)` compatible
-
-      - {meth}`~libvcs.parse.git.GitBaseURL.is_valid`
-      - {meth}`~libvcs.parse.git.GitBaseURL.to_url` - export `git clone`-compatible URL
-
-    - {class}`~libvcs.parse.git.GitPipURL` - Pip URLs, {meth}`~libvcs.parse.git.GitPipURL.is_valid`,
-      {meth}`~libvcs.parse.git.GitPipURL.to_url`
-
-    - {class}`~libvcs.parse.git.GitURL` - Compatibility focused,
-      {meth}`~libvcs.parse.git.GitURL.is_valid` {meth}`~libvcs.parse.git.GitURL.to_url`
-
-  - {mod}`libvcs.parse.hg`
-
-    - {class}`~libvcs.parse.hg.HgURL` - Parse Mercurial URLs
-      - {meth}`~libvcs.parse.hg.HgURL.is_valid`
-      - {meth}`~libvcs.parse.hg.HgURL.to_url` - export `hg clone`-compatible URL
-
-  - {mod}`libvcs.parse.svn`
-
-    - {class}`~libvcs.parse.svn.SvnURL` - Parse Subversion URLs
-      - {meth}`~libvcs.parse.svn.SvnURL.is_valid`
-      - {meth}`~libvcs.parse.svn.SvnURL.to_url` - export `svn checkout`-compatible URL
-
-  Detection can be extended through writing {class}`~libvcs.parse.base.Matcher`s and adding them to
-  the classes' {class}`~libvcs.parse.base.MatcherRegistry`
-
-  You can write your own VCS parser by implementing {class}`~libvcs.parse.base.URLProtocol`, but it
-  would be most efficient if you studied the source of the `git(1)` parser to see how it's done.
-
-### Breaking changes
-
-- {issue}`379` Support for `git+git` URLs removed. Pip removed these in 21.0 due to them being
-  insecure [^pip-git+git]
-- {issue}`372` Typings moved from `libvcs.types` -> {mod}`libvcs._internal.types`
-- {issue}`377` Remove deprecated functions and exceptions
-
-  - Removed `libvcs.shortcuts`
-    - Removed `libvcs.shortcuts.create_project_from_pip_url()`: This will be replaced in future
-      versions by {issue}`376` / parsing utilities
-    - Moved `libvcs.shortcuts.create_project()` to {func}`libvcs._internal.shortcuts.create_project`
-  - Removed {exc}`libvcs.exc.InvalidPipURL`
-
-[^pip-git+git]: pip removes `git+git@` <https://github.com/pypa/pip/pull/7543>
-
-### Fixes
-
-- Minor spelling fix in Git's `convert_pip_url()` exception
-- Fix mercurial cloning in {class}`libvcs.projects.hg.MercurialProject`
-
-  _Backport from 0.13.1_
-
-### Typings
-
-- Rename `VcsLiteral` -> `VCSLiteral`
-
-  _Backport from 0.13.4_
-
-- {func}`~libvcs.shortcuts.create_project`: Add overloads that return the typed project (e.g.
-  {class}`~libvcs.projects.git.GitProject`)
-
-  _Backport from 0.13.3_
-
-### Cleanup
-
-- {issue}`378` {issue}`380` Remove duplicate `uses_netloc` scheme for `git+ssh` (this was in cpython
-  since 2.7 / 3.1 [^git+ssh][^python:bugs:8657])
-
-[^git+ssh]: `uses_netloc` added `'git'` and `'git+ssh'` in {mod}`urllib.parse`
-
-    [python/cpython@ead169d]
-
-[python/cpython@ead169d]:
-  https://github.com/python/cpython/commit/ead169d3114ed0f1041b5b59ca20293449608c50
-
-[^python:bugs:8657]: <https://bugs.python.org/issue8657>
-
-## libvcs 0.13.6 (2022-06-18)
-
-### Development
-
-- Move `libvcs.shortcuts` to {mod}`libvcs._internal.shortcuts`
-
-## libvcs 0.13.5 (2022-06-18)
-
-### Development
-
-- Note upcoming deprecation of `create_project_from_pip_url` in v0.14
-- Note `create_project` becoming internal API in upcoming release v0.14
-- Fix import in `libvcs.shortcuts` (in v0.14 this module will not exist)
-
-## libvcs 0.13.4 (2022-06-18)
-
-### Typing
-
-- Rename `VcsLiteral` -> `VCSLiteral`
-
-## libvcs 0.13.3 (2022-06-18)
-
-### Typings
-
-- `create_project()`: Add overloads that return the typed project (e.g.
-  {class}`~libvcs.projects.git.GitProject`)
-
-## libvcs 0.13.2 (2022-06-12)
-
-### Typings
-
-- {func}`libvcs.projects.git.GitProject.remotes`: Add overload
-
-## libvcs 0.13.1 (2022-06-01)
-
-### Fixes
-
-- Fix mercurial cloning in {class}`libvcs.projects.hg.MercurialProject`
-
-## libvcs 0.13.0, "Jane" (2022-05-30)
-
-### Breaking changes
-
-- {issue}`343`: `libvcs.cmd.core` moved to `libvcs._internal.run` to make it more clear the API is
-  closed.
-
-  This includes {func}`~libvcs._internal.run.run`
-
-  Before in 0.13:
-
-  ```python
-  from libvcs.cmd.core import run
-  ```
-
-  New module in >=0.13:
-
-  ```python
-  from libvcs._internal.run import run
-  ```
-
-- {issue}`361`: {class}`~libvcs._internal.run.run`'s params are now a pass-through to
-  {class}`subprocess.Popen`.
-
-  - `run(cmd, ...)` is now `run(args, ...)` to match `Popen`'s convention.
-
-- {class}`libvcs.projects.base.BaseProject`:
-
-  - Removed `parent_dir`:
-
-    Before: `project.parent_dir`
-
-    After: `project.parent.dir`.
-
-  - `repo_name` switched from attribute to property
-
-- Keyword-only arguments via [PEP 3102], [PEP 570]
-
-  - {issue}`366`: `libvcs.cmd` for hg, git, and svn updated to use
-
-  - {issue}`364`: Project classes no longer accept positional arguments.
-
-    Deprecated in >=0.13:
-
-    ```python
-    GitProject('https://github.com/vcs-python/libvcs.git')
-    ```
-
-    New style in >=0.13:
-
-    ```python
-    GitProject(url='https://github.com/vcs-python/libvcs.git')
-    ```
-
-[pep 570]: https://peps.python.org/pep-0570/
-[pep 3102]: https://peps.python.org/pep-3102/#specification
-
-### What's new
-
-- **Commands**: Experimental command wrappers added ({issue}`346`):
-
-  - {class}`libvcs.cmd.git.Git`
-
-    - {meth}`libvcs.cmd.git.Git.help`
-    - {meth}`libvcs.cmd.git.Git.reset`
-    - {meth}`libvcs.cmd.git.Git.checkout`
-    - {meth}`libvcs.cmd.git.Git.status`
-    - {meth}`libvcs.cmd.git.Git.config` via {issue}`360`
-
-- **Command**: Now support `-C` (which accepts `.git` dirs, see git's manual) in addition to `cwd`
-  (subprocess-passthrough), {issue}`360`
-
-### Bug fixes
-
-- Fix argument input for commands, e.g. `git config --get color.diff` would not properly
-  pass-through to subprocess. git: {issue}`360`, svn and hg: {issue}`365`
-
-### Internals
-
-- {issue}`362` [mypy] support added:
-
-  - Basic mypy tests now pass
-  - Type annotations added, including improved typings for:
-
-    - {func}`libvcs._internal.run.run`
-    - {meth}`libvcs._internal.subprocess.SubprocessCommand.Popen`
-    - {meth}`libvcs._internal.subprocess.SubprocessCommand.check_output`
-    - {meth}`libvcs._internal.subprocess.SubprocessCommand.run`
-
-  - `make mypy` and `make watch_mypy`
-  - Automatic checking on CI
-
-- {issue}`345` `libvcs.utils` -> `libvcs._internal` to make it more obvious the APIs are strictly
-  closed.
-- `StrOrPath` -> `StrPath`
-- {issue}`336`: {class}`~libvcs._internal.subprocess.SubprocessCommand`: Encapsulated
-  {mod}`subprocess` call in a {func}`dataclasses.dataclass` for introspecting, modifying, mocking
-  and controlling execution.
-- Dataclass helper: {class}`~libvcs._internal.dataclasses.SkipDefaultFieldsReprMixin`
-
-  Skip default fields in object representations.
-
-  Credit: Pietro Oldrati, 2022-05-08,
-  [StackOverflow Post](https://stackoverflow.com/a/72161437/1396928)
-
-### Documentation
-
-- Document `libvcs.types`
-- {issue}`362`: Improve developer documentation to note [mypy] and have tabbed examples for flake8.
-
-[mypy]: http://mypy-lang.org/
-
-### Packaging
-
-- Update description and keywords
-
-## libvcs 0.12.4 (2022-05-30)
-
-- _Backport from 0.13.x_ Fix argument input for hg and svn commands, would not properly pass-through
-  to subprocess. {issue}`365`
-
-## libvcs 0.12.3 (2022-05-28)
-
-### Bug fixes
-
-- _Backport from 0.13.x_. Fix argument input for git commands, e.g. `git config --get color.diff`
-  would not properly pass-through to subprocess. {issue}`360`
-
-## libvcs 0.12.2 (2022-05-10)
-
-### Packaging
-
-- Update [trove classifiers](https://pypi.org/classifiers/)
-
-## libvcs 0.12.1 (2022-05-10)
-
-### Packaging
-
-- Add keywords and update subscription
-- Add `py.typed` file to `libvcs/py.typed`
-
-## libvcs 0.12.0, "Nimbus" (2022-04-24)
-
-### Breaking
-
-- `GitRepo`, `SVNRepo`, `MercurialRepo`, `BaseRepo` have been renamed to `GitProject`, `SVNProject`,
-  `MercurialProject`, `BaseProject` ({issue}`327`)
-- `GitProject`, `SVNProject`, `MercurialProject`, `BaseProject` have been moved to
-  `libvcs.projects.{module}.{Module}Project`
-- `repo_dir` param is renamed to `dir`:
-
-  Before: `GitProject(url='...', repo_dir='...')`
-
-  After: `GitProject(url='...', dir='...')`
-
-  {issue}`324`
-
-- `dir` to `pathlib`, `BaseProject.path` -> `BaseProject.dir`
-- Logging functions moved to {attr}`libvcs.projects.base.BaseProject.log` ({issue}`322`)
-- Rename `ProjectLoggingAdapter` to `CmdLoggingAdapter`
-- `CmdLoggingAdapter`: Rename `repo_name` param to `keyword`
-- `create_repo` -> `create_project`
-- `GitRemote` and `GitStatus`: Move to {func}`dataclasses.dataclass` ({issue}`329`)
-- `extract_status()`: Move to `GitStatus.from_stdout` ({issue}`329`)
-
-### What's new
-
-- **Commands**: Experimental command wrappers added ({issue}`319`):
-
-  - {class}`libvcs.cmd.git.Git`
-
-    - {meth}`libvcs.cmd.git.Git.run`
-    - {meth}`libvcs.cmd.git.Git.clone`
-    - {meth}`libvcs.cmd.git.Git.init`
-    - {meth}`libvcs.cmd.git.Git.pull`
-    - {meth}`libvcs.cmd.git.Git.rebase`
-
-  - {class}`libvcs.cmd.svn.Svn`
-
-    - {meth}`libvcs.cmd.svn.Svn.run`
-    - {meth}`libvcs.cmd.svn.Svn.checkout`
-    - {meth}`libvcs.cmd.svn.Svn.update`
-    - {meth}`libvcs.cmd.svn.Svn.status`
-    - {meth}`libvcs.cmd.svn.Svn.auth`
-    - {meth}`libvcs.cmd.svn.Svn.blame`
-    - {meth}`libvcs.cmd.svn.Svn.commit`
-
-  - {class}`libvcs.cmd.hg.Hg`
-
-    - {meth}`libvcs.cmd.hg.Hg.run`
-    - {meth}`libvcs.cmd.hg.Hg.clone`
-
-- {class}`libvcs.projects.git.GitProject` now accepts remotes in `__init__`
-
-  ```python
-  repo = GitProject(
-      url="https://github.com/vcs-python/libvcs",
-      repo_dir=checkout,
-      remotes={
-          'gitlab': 'https://gitlab.com/vcs-python/libvcs',
-      }
-  )
-  ```
-
-  ```python
-  repo = GitProject(
-      url="https://github.com/vcs-python/libvcs",
-      repo_dir=checkout,
-      remotes={
-          'gitlab': {
-              'fetch_url': 'https://gitlab.com/vcs-python/libvcs',
-              'push_url': 'https://gitlab.com/vcs-python/libvcs',
-          },
-      }
-  )
-  ```
-
-- {meth}`libvcs.projects.git.GitProject.update_repo` now accepts `set_remotes=True`
-
-### Compatibility
-
-- Python 3.7 and 3.8 dropped (#308)
-
-  Maintenance and bug support exists in
-  [`v0.11.x`](https://github.com/vcs-python/libvcs/tree/v0.11.x)
-
-### Development
-
-- Add codeql analysis ({issue}`303`)
-- git test suite: Lots of parametrization ({issue}`309`)
-- CI: Use poetry caching from
-  [@actions/setup v3.1](https://github.com/actions/setup-python/releases/tag/v3.1.0), ({issue}`316`)
-- New constants for `str` -> class mappings
-
-  - {data}`libvcs.projects.constants.DEFAULT_VCS_CLASS_MAP`
-  - {data}`libvcs.projects.constants.DEFAULT_VCS_CLASS_UNION`
-  - {data}`libvcs.projects.constants.DEFAULT_VCS_LITERAL`
-
-- Remove tox and tox-poetry-installer. It turns out installing poetry inside a poetry project
-  doesn't work well. (`poetry update`, `poetry publish`, etc. commands would fail)
-- Add [doctest](https://docs.python.org/3/library/doctest.html) w/
-  [pytest + doctest](https://docs.pytest.org/en/7.1.x/how-to/doctest.html), ({issue}`321`).
-- Publish to PyPI via CI when git tags are set.
-
-### Documentation
-
-- API: Split documentation of modules to separate pages
-- Fix sphinx-issues ({issue}`321`)
-- Experiment with sphinx-autoapi ({issue}`328`) for table of contents support
-
-## libvcs 0.11.1 (2022-03-12)
-
-### CVE-2022-21187: Command Injection with mercurial repositories
-
-- By setting a mercurial URL with an alias it is possible to execute arbitrary shell commands via
-  `.obtain()` or in the case of uncloned destinations, `.update_repo()`.
-  ([#306](https://github.com/vcs-python/libvcs/pull/306), credit: Alessio Della Libera)
-
-  See also: [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21187),
-  [nvd.nist.gov](https://nvd.nist.gov/vuln/detail/CVE-2022-21187),
-  [snyk](https://security.snyk.io/vuln/SNYK-PYTHON-LIBVCS-2421204).
-
-### Development
-
-- Run pyupgrade formatting (#305)
-- Tests:
-  - Move from pytest `tmp_dir` (`py.path.local`) to `tmp_path` (`pathlib.Path`)
-  - Text fixture updates: Use home directory via `tmp_path_factory`, generate config for git and hg.
-
-### Documentation
-
-- Move to furo theme
-- Root: `make start_docs`, `make design_docs`
-- docs/: `make start`, `make design`
-
-## libvcs 0.11.0, "Phebe" (2022-01-08)
-
-### Compatibility
-
-- Add python 3.10 (#300)
-- Drop python 3.6 (#300)
-
-### Development
-
-- Poetry: 1.1.7 -> 1.1.12 (#300)
-- Add `.pre-commit-config.yaml`
-
-## libvcs 0.10.1 (2021-11-30)
-
-- #295: Checkout remote branch before git rebase. Thank you @jensens!
-- #293: Fix revision handling with pip-urls. Thank you @jensens!
-- #279: Update poetry to 1.1
-  - CI: Use poetry 1.1.7 and `install-poetry.py` installer
-  - Relock poetry.lock at 1.1 (w/ 1.1.7's fix)
-
-## libvcs 0.10 (2021-06-16)
-
-- #311: Convert to markdown
-
-## libvcs 0.9 (2021-06-14)
-
-Generally speaking, refactor / magic is in the process of being stripped out in the next few
-releases. The API is subject to change significantly in pre-1.0 builds.
-
-[#271]:
-
-- Big version bump (0.5 -> 0.9)
-- Remove Python 2.7 support
-- Add annotations
-- Change `libvcs.git.GitRepo.status()` to return `GitStatus` named tuple
-- Breaking change: Repo objects now require `repo_dir` to be passed
-- Update black to 21.6b0
-
-[#271]: https://github.com/vcs-python/libvcs/pull/271
-
-## libvcs 0.5 (2020-08-11)
-
-- [refactor] [#267] overhaul docs
-
-  - Move sphinx api format to Numpy-style
-
-  - Move from reStructuredText to Markdown (via recommonmark). The master plan is to eliminate
-    docutils and sphinx as a bottleneck completely in favor of something else (e.g. gatsby with a
-    source that inspects our modules and can source intersphinx)
-
-  - Move from RTD to GitHub Action, full support of poetry extras packages, deploys straight to S3
-    and CloudFront
-
-- [#270] Build and publish packages via poetry
-- [#270] Overhaul development docs
-
-[#270]: https://github.com/vcs-python/libvcs/pull/270
-[#267]: https://github.com/vcs-python/libvcs/pull/267
-
-## libvcs 0.4.4 (2020-08-05)
-
-- [#268] `libvcs.base.BaseRepo`:
-  - no longer sets `**kwargs` to dictionary on the object
-  - remove `__slot__` and rename `name` attribute to `repo_name`
-
-[#268]: https://github.com/vcs-python/libvcs/pull/268
-
-## libvcs 0.4.3 (2020-08-01)
-
-- \[bug\] `libvcs.git.extract_status()` Fix issue capturing branch names with special characters
-
-## libvcs 0.4.2 (2020-08-01)
-
-- \[bug\] `libvcs.git.GitRepo.get_current_remote_name()` Handle case where upstream is unpushed
-- \[feature\] `libvcs.git.GitRepo.status()` - Retrieve status of repo
-- \[feature\] `libvcs.git.extract_status()` - Return structured info from `git status`
-
-## libvcs 0.4.1 (2020-08-01)
-
-- Remove log statement
-
-## libvcs 0.4 (2020-08-01)
-
-**Breaking changes**
-
-Internal functionality relating to remotes have been reorganized to avoid implicit behavior.
-
-- `~libvcs.git.GitRepo` methods have been renamed, they will be deprecated in 0.5:
-
-  - `GitRepo.remotes_get` renamed to `libvcs.git.GitRepo.remotes()`
-  - `GitRepo.remote_get` renamed to `libvcs.git.GitRepo.remote()`
-  - `GitRepo.remote_set` renamed to `libvcs.git.GitRepo.set_remote()`
-
-- `~libvcs.git.GitRepo` the `remotes` argument is deprecated and no longer used. Use
-  `libvcs.git.GitRepo.set_remote` after repo is instantiated.
-
-- `libvcs.git.GitRepo.obtain` no longer set remotes based on a `dict` passed to
-  `~libvcs.git.GitRepo`. This was deemed to specialized / implicit.
-
-- `libvcs.git.GitRepo.set_remote()` (formerly `remote_set`)
-
-  The new method accepts `name` and `url` (in that order). `name` no longer has a default value (was
-  `origin`).
-
-- `libvcs.git.GitRepo.remote()` (formerly `remote_get`):
-
-  - `remote` argument renamed to `name`. It will be removed in 0.5.0
-
-    The default value of `'origin'` has been removed
-
-  - Now returns `~libvcs.git.GitRemote` (a :py`collections.namedtuple` object)
-
-    The tuple is similar to the old output, except there is an additional value at the beginning,
-    the name of the remote, e.g. `('origin', '<fetch_url>', '<push_url>')`
-
-- `libvcs.git.GitRepo.remotes()` (formerly `remotes_get`) are now methods instead of properties.
-
-  Passing `flat=True` to return a `dict` of `tuple` instead of `dict`
-
-- New method: `libvcs.git.GitRepo.get_git_version()`
-
-- New method: `libvcs.git.GitRepo.get_current_remote_name()`
-
-## libvcs 0.3.3 (2020-07-29)
-
-- Remove f-string from test
-- `libvcs.git.GitRepo.obtain` Overwrite remote if exists
-
-## libvcs 0.3.2 (2020-07-26)
-
-- `258` `libvcs.git.GitRepo.remote_set`
-  - Fix updating of remote URLs
-  - Add new param: `overwrite`, usage: `repo.remote_set(url, 'origin', overwrite=True)`
-
-## libvcs 0.3.1post1 (2020-07-26)
-
-- Fix version in pyroject.toml
-- Update developer docs
-
-## libvcs 0.3.1 (2020-07-25)
-
-- Fix issue with subprocess.Popen loud warning on Python 3.8
-- [#296] - Move from Pipfile to poetry
-- Sort imports
-- Add isort package, isort configuration in setup.cfg, and `make isort` task to Makefile.
-- Add `project_urls` to setup.py
-
-[#296] https://github.com/vcs-python/libvcs/pull/296
-
-## libvcs 0.3.0 (2018-03-12)
-
-- Move vcspull to the vcs-python organization
-- Fix issue where VCS objects failed to set attribute in Ubuntu 18.04.
-
-## libvcs 0.2.3 (2016-12-22)
-
-- Update documentation to point to libvcs.git-pull.com
-- Switch doc theme to alabaster
-- Pin and update libraries via pyup
-  - update vulture 0.8.1 to 0.11
-  - update flake8 from 2.5.4 to 3.2.1
-  - update pytest-mock from 1.4.0 to 1.5.0
-  - update pytest from 3.0.4 to 3.0.5
-  - pin alabaster to 0.7.9
-  - pin sphinx to 1.5.1
-
-## libvcs 0.2.2 (2016-11-23)
-
-- Fix bug with unused `support` module in vcspull. See [vcspull#43]
-
-[vcspull#43]: https://github.com/vcs-python/vcspull/pull/43
-
-## libvcs 0.2.1 (2016-09-13)
-
-- Update pytest to 3.0.2, remove unused pytest-raisesregexp dependency.
-- Fix bug in `which` when executable is not found. Allow specifying search paths manually.
-- Better support for missing VCS when testing on git and subversion.
-
-## libvcs 0.2.0 (2016-06-24)
-
-- [#9] Support for `progress_callback` to use realtime output from commands in progress (such as
-  `git fetch`).
-- [#9] More tests, internal factoring and documentation, thanks @jcfr
-- [#9] Official support for pypy, pypy3
-- [#11] : Fix unbound local when updating git repos
-
-[#9]: https://github.com/vcs-python/libvcs/pull/9
-[#11]: https://github.com/vcs-python/libvcs/pull/11
-
-## libvcs 0.1.7 (2016-06-21)
-
-- `7` Add `check_returncode` property to run, thanks @jcfr
-- `8` Remove all cases of `run_buffered` / buffering from the library.
-
-## libvcs 0.1.6 (2016-06-21)
-
-- `5` Remove colorama dependency
-
-- `6` Remove log module. Logging defaults.
-
-  The library user can still use formatters and set log levels, for an example, see the vcspull
-  logging setup.
-
-  An example:
-
-        import logging
-
-        # your app
-        log.setLevel(level)
-        log.addHandler(logging.StreamHandler())
-
-        # vcslib logging options
-        vcslogger = logging.getLogger('libvcs')
-        vcslogger.propagate = False # don't pass libvcs settings up scope
-        vcslogger.addHandler(logging.StreamHandler())
-        vcslogger.setLevel(level)
-
-  You can also use `logging.Formatter` variables `repo_name` and `bin_name` with repos:
-
-        repo_channel = logging.StreamHandler()
-        repo_formatter = logging.Formatter(
-            '[%(repo_name)s] (%(bin_name)s) %(levelname)1.1s: %(message)s'
-        )
-        repo_channel.setFormatter(repo_formatter)
-        vcslogger = logging.getLogger('libvcs')
-        vcslogger.propagate = False # don't pass libvcs settings up scope
-        vcslogger.addHandler(repo_channel)
-        vcslogger.setLevel(level)
-
-## libvcs 0.1.5 (2016-06-21)
-
-- Fix issue where repo context wouldn't pass to repo logging adapter
-
-## libvcs 0.1.4 (2016-06-20)
-
-- Fix print_stdout_on_progress_end signature in git update
-
-## libvcs 0.1.3 (2016-06-20)
-
-- `create_repo` function for regular vcs urls
-- API docs updated
-
-## libvcs 0.1.2 (2016-06-20)
-
-- change signature on `create_repo_from_pip_url` to accept `pip_url` instead of `url`.
-- `Base` to accept `repo_dir` instead of `name` and `parent_dir`.
-
-## libvcs 0.1.1 (2016-06-20)
-
-- remove unneeded pyyaml, kaptan and click dependencies
-
-## libvcs 0.1.0 (2016-06-20)
-
-- libvcs split from [vcspull](https://github.com/vcs-python/vcspull)
-
-<!---
-vim: set filetype=markdown:
--->
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 631356f7a..000000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include README.md LICENSE CHANGES pyproject.toml .tmuxp.yaml
-recursive-include docs *.md
diff --git a/README.md b/README.md
index 7376add91..dd9ef1b30 100644
--- a/README.md
+++ b/README.md
@@ -1,141 +1,32 @@
 # `libvcs` &middot; [![Python Package](https://img.shields.io/pypi/v/libvcs.svg)](https://pypi.org/project/libvcs/) [![License](https://img.shields.io/github/license/vcs-python/libvcs.svg)](https://github.com/vcs-python/libvcs/blob/master/LICENSE) [![Code Coverage](https://codecov.io/gh/vcs-python/libvcs/branch/master/graph/badge.svg)](https://codecov.io/gh/vcs-python/libvcs)
 
-libvcs is a lite, [typed](https://docs.python.org/3/library/typing.html), pythonic tool box for
-detection and parsing of URLs, commanding, and syncing with `git`, `hg`, and `svn`. Powers
-[vcspull](https://www.github.com/vcs-python/vcspull/).
+Example of [sphinx-autoapi] documenting imports, issue
+https://github.com/readthedocs/sphinx-autoapi/issues/342
 
-## Overview
+## Reproduction
 
-Features for Git, Subversion, and Mercurial:
+https://github.com/vcs-python/libvcs/tree/autoapi-duplicates
 
-- **Detect and parse** VCS URLs
-- **Command** VCS via python API
-- **Sync** repos locally
+### Versions
 
-To **get started**, see the [quickstart](https://libvcs.git-pull.com/quickstart.html) for more.
+sphinx 5.1.2 sphinx-autoapi 1.9.0
 
-```console
-$ pip install --user libvcs
-```
-
-## URL Parsing (experimental)
-
-You can validate and parse Git, Mercurial, and Subversion URLs through
-[`libvcs.parse`](https://libvcs.git-pull.com/parse/index.html):
-
-Validate:
-
-```python
->>> from libvcs.parse.git import GitUrl
+### Configuration
 
->>> GitURL.is_valid(url='https://github.com/vcs-python/libvcs.git')
-True
-```
-
-Parse and adjust a Git URL:
+[conf.py](https://github.com/vcs-python/libvcs/blob/autoapi-duplicates/docs/conf.py)
 
 ```
-from libvcs.parse.git import GitUrl
-
->>> git_location = GitURL(url='git@github.com:vcs-python/libvcs.git')
+extensions = [
+    "sphinx.ext.napoleon",
+    "autoapi.extension",
+    "sphinx.ext.autodoc",
+    "sphinx.ext.todo",
+    "sphinx.ext.intersphinx",
+    "myst_parser",
+]
 
->>> git_location
-GitURL(url=git@github.com:vcs-python/libvcs.git,
-        hostname=github.com,
-        path=vcs-python/libvcs,
-        user=git,
-        suffix=.git,
-        matcher=core-git-scp)
+# sphinx-autoapi
+autoapi_type = "python"
+autoapi_dirs = [project_root / "libvcs"]
+autoapi_generate_api_docs = False  # when False, use directives
 ```
-
-Switch repo libvcs -> vcspull:
-
-```python
->>> git_location.path = 'vcs-python/vcspull'
-
->>> git_location.to_url()
-'git@github.com:vcs-python/vcspull.git'
-
-# Switch them to gitlab:
->>> git_location.hostname = 'gitlab.com'
-
-# Export to a `git clone` compatible URL.
->>> git_location.to_url()
-'git@gitlab.com:vcs-python/vcspull.git'
-```
-
-See more in the [parser document](https://libvcs.git-pull.com/parse/index.html).
-
-## Commands (experimental)
-
-Simple [`subprocess`](https://docs.python.org/3/library/subprocess.html) wrappers around `git(1)`,
-`hg(1)`, `svn(1)`. Here is [`Git`](https://libvcs.git-pull.com/cmd/git.html#libvcs.cmd.git.Git) w/
-[`Git.clone`](http://libvcs.git-pull.com/cmd/git.html#libvcs.cmd.git.Git.clone):
-
-```python
-import pathlib
-from libvcs.cmd.git import Git
-
-git = Git(dir=pathlib.Path.cwd() / 'my_git_repo')
-git.clone(url='https://github.com/vcs-python/libvcs.git')
-```
-
-## Projects
-
-Create a
-[`GitProject`](https://libvcs.git-pull.com/projects/git.html#libvcs.projects.git.GitProject) object
-of the project to inspect / checkout / update:
-
-```python
-import pathlib
-from libvcs.projects.git import GitProject
-
-repo = GitProject(
-   url="https://github.com/vcs-python/libvcs",
-   dir=pathlib.Path().cwd() / "my_repo",
-   remotes={
-       'gitlab': 'https://gitlab.com/vcs-python/libvcs'
-   }
-)
-```
-
-Update / clone repo:
-
-```python
->>> r.update_repo()
-```
-
-Get revision:
-
-```python
->>> r.get_revision()
-u'5c227e6ab4aab44bf097da2e088b0ff947370ab8'
-```
-
-## Donations
-
-Your donations fund development of new features, testing and support. Your money will go directly to
-maintenance and development of the project. If you are an individual, feel free to give whatever
-feels right for the value you get out of the project.
-
-See donation options at <https://www.git-pull.com/support.html>.
-
-## More information
-
-- Python support: 3.9+, pypy
-- VCS supported: git(1), svn(1), hg(1)
-- Source: <https://github.com/vcs-python/libvcs>
-- Docs: <https://libvcs.git-pull.com>
-- Changelog: <https://libvcs.git-pull.com/history.html>
-- APIs for git, hg, and svn:
-  - [`libvcs.parse`](https://libvcs.git-pull.com/parse/): Detect and Parse
-  - [`libvcs.cmd`](https://libvcs.git-pull.com/cmd/): Commands
-  - [`libvcs.projects`](https://libvcs.git-pull.com/projects/): High-level synchronization commands
-- Issues: <https://github.com/vcs-python/libvcs/issues>
-- Test Coverage: <https://codecov.io/gh/vcs-python/libvcs>
-- pypi: <https://pypi.python.org/pypi/libvcs>
-- Open Hub: <https://www.openhub.net/p/libvcs>
-- License: [MIT](https://opensource.org/licenses/MIT).
-
-[![Docs](https://github.com/vcs-python/libvcs/workflows/docs/badge.svg)](https://libvcs.git-pull.com/)
-[![Build Status](https://github.com/vcs-python/libvcs/workflows/tests/badge.svg)](https://github.com/vcs-python/libvcs/actions?query=workflow%3A%22tests%22)
diff --git a/assets/css/custom.css b/assets/css/custom.css
deleted file mode 100644
index 8f578b18b..000000000
--- a/assets/css/custom.css
+++ /dev/null
@@ -1,47 +0,0 @@
-.mkapi-node {
-  font-size: 0.85em;
-}
-
-.mkapi-node a.mkapi-src-link, a.mkapi-docs-link {
-  font-size: 0.8em;
-}
-
-.mkapi-node .mkapi-object.code h3.mkapi-object-body {
-  font-size: 1.2em;
-}
-
-.mkapi-node .mkapi-section-name .mkapi-section-name-body {
-  font-size: 1em;
-}
-
-.mkapi-node .mkapi-base {
-  font-size: .9em;
-}
-
-.mkapi-node code.mkapi-item-name,
-.mkapi-node code.mkapi-object-signature,
-.mkapi-node code.mkapi-object-parenthesis,
-.mkapi-node span.mkapi-item-dash,
-.mkapi-node span.mkapi-item-type {
-  font-size: 0.9em;
-}
-
-.mkapi-node .mkapi-item-name,
-.mkapi-node .mkapi-object,
-.mkapi-node .mkapi-object code,
-.mkapi-node .mkapi-object.code h2.mkapi-object-body,
-.mkapi-node h2 .mkapi-object {
-  font-size: 1em;
-}
-
-.mkapi-node ul.mkapi-items li::before {
-  font-size: 80%;
-}
-
-.mkapi-section-name {
-  padding: 0px 8px 2px 8px;
-}
-
-.mkapi-object.plain .mkapi-object-kind {
-  font-weight: normal;
-}
diff --git a/assets/images/favicon.ico b/assets/images/favicon.ico
deleted file mode 120000
index c50b150ee..000000000
--- a/assets/images/favicon.ico
+++ /dev/null
@@ -1 +0,0 @@
-../../docs/_static/favicon.ico
\ No newline at end of file
diff --git a/assets/images/libvcs.svg b/assets/images/libvcs.svg
deleted file mode 120000
index 9a858af61..000000000
--- a/assets/images/libvcs.svg
+++ /dev/null
@@ -1 +0,0 @@
-../../docs/_static/img/libvcs.svg
\ No newline at end of file
diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css
deleted file mode 100644
index 3bf24f5ef..000000000
--- a/docs/_static/css/custom.css
+++ /dev/null
@@ -1,37 +0,0 @@
-h2 {
-  margin-bottom: 1.25rem;
-  margin-top: 1.25rem;
-  scroll-margin-top: 0.5rem;
-}
-
-h3 {
-  margin-bottom: 1.25rem;
-  margin-top: 1.25rem;
-  scroll-margin-top: 0.5rem;
-}
-
-h4 {
-  margin-bottom: 1.25rem;
-  scroll-margin-top: 0.5rem;
-}
-
-.sidebar-tree p.indented-block {
-  padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0
-    var(--sidebar-item-spacing-horizontal);
-  margin-bottom: 0;
-}
-
-.sidebar-tree p.indented-block span.indent {
-  margin-left: var(--sidebar-item-spacing-horizontal);
-  display: block;
-}
-
-.sidebar-tree p.indented-block .project-name {
-  font-size: var(--sidebar-item-font-size);
-  font-weight: bold;
-  margin-right: calc(var(--sidebar-item-spacing-horizontal) / 2.5);
-}
-
-.sidebar-tree .active {
-  font-weight: bold;
-}
diff --git a/docs/_static/favicon.ico b/docs/_static/favicon.ico
deleted file mode 100644
index d90c1606b..000000000
Binary files a/docs/_static/favicon.ico and /dev/null differ
diff --git a/docs/_static/img/icons/android-icon-144x144.png b/docs/_static/img/icons/android-icon-144x144.png
deleted file mode 100644
index 742a7fb1a..000000000
Binary files a/docs/_static/img/icons/android-icon-144x144.png and /dev/null differ
diff --git a/docs/_static/img/icons/android-icon-192x192.png b/docs/_static/img/icons/android-icon-192x192.png
deleted file mode 100644
index 96fe1a180..000000000
Binary files a/docs/_static/img/icons/android-icon-192x192.png and /dev/null differ
diff --git a/docs/_static/img/icons/android-icon-72x72.png b/docs/_static/img/icons/android-icon-72x72.png
deleted file mode 100644
index f7248e8ef..000000000
Binary files a/docs/_static/img/icons/android-icon-72x72.png and /dev/null differ
diff --git a/docs/_static/img/icons/android-icon-96x96.png b/docs/_static/img/icons/android-icon-96x96.png
deleted file mode 100644
index 5821c1894..000000000
Binary files a/docs/_static/img/icons/android-icon-96x96.png and /dev/null differ
diff --git a/docs/_static/img/icons/browserconfig.xml b/docs/_static/img/icons/browserconfig.xml
deleted file mode 100644
index c55414822..000000000
--- a/docs/_static/img/icons/browserconfig.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
\ No newline at end of file
diff --git a/docs/_static/img/icons/icon-128x128.png b/docs/_static/img/icons/icon-128x128.png
deleted file mode 100644
index 1f571dcea..000000000
Binary files a/docs/_static/img/icons/icon-128x128.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-144x144.png b/docs/_static/img/icons/icon-144x144.png
deleted file mode 100644
index 96c5ac7a9..000000000
Binary files a/docs/_static/img/icons/icon-144x144.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-152x152.png b/docs/_static/img/icons/icon-152x152.png
deleted file mode 100644
index 710113528..000000000
Binary files a/docs/_static/img/icons/icon-152x152.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-16x16.png b/docs/_static/img/icons/icon-16x16.png
deleted file mode 100644
index 4081c9003..000000000
Binary files a/docs/_static/img/icons/icon-16x16.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-192x192.png b/docs/_static/img/icons/icon-192x192.png
deleted file mode 100644
index 68802e72f..000000000
Binary files a/docs/_static/img/icons/icon-192x192.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-32x32.png b/docs/_static/img/icons/icon-32x32.png
deleted file mode 100644
index 5f0170882..000000000
Binary files a/docs/_static/img/icons/icon-32x32.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-384x384.png b/docs/_static/img/icons/icon-384x384.png
deleted file mode 100644
index a1f4ca3a3..000000000
Binary files a/docs/_static/img/icons/icon-384x384.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-512x512.png b/docs/_static/img/icons/icon-512x512.png
deleted file mode 100644
index 3bbccb202..000000000
Binary files a/docs/_static/img/icons/icon-512x512.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-72x72.png b/docs/_static/img/icons/icon-72x72.png
deleted file mode 100644
index 17236cc38..000000000
Binary files a/docs/_static/img/icons/icon-72x72.png and /dev/null differ
diff --git a/docs/_static/img/icons/icon-96x96.png b/docs/_static/img/icons/icon-96x96.png
deleted file mode 100644
index 850eae213..000000000
Binary files a/docs/_static/img/icons/icon-96x96.png and /dev/null differ
diff --git a/docs/_static/img/icons/ms-icon-144x144.png b/docs/_static/img/icons/ms-icon-144x144.png
deleted file mode 100644
index 742a7fb1a..000000000
Binary files a/docs/_static/img/icons/ms-icon-144x144.png and /dev/null differ
diff --git a/docs/_static/img/icons/ms-icon-150x150.png b/docs/_static/img/icons/ms-icon-150x150.png
deleted file mode 100644
index 7d83d2bf7..000000000
Binary files a/docs/_static/img/icons/ms-icon-150x150.png and /dev/null differ
diff --git a/docs/_static/img/icons/ms-icon-310x310.png b/docs/_static/img/icons/ms-icon-310x310.png
deleted file mode 100644
index f740c3007..000000000
Binary files a/docs/_static/img/icons/ms-icon-310x310.png and /dev/null differ
diff --git a/docs/_static/img/icons/ms-icon-70x70.png b/docs/_static/img/icons/ms-icon-70x70.png
deleted file mode 100644
index a09239d8b..000000000
Binary files a/docs/_static/img/icons/ms-icon-70x70.png and /dev/null differ
diff --git a/docs/_static/img/libvcs-dark.svg b/docs/_static/img/libvcs-dark.svg
deleted file mode 100644
index 5be4cd149..000000000
--- a/docs/_static/img/libvcs-dark.svg
+++ /dev/null
@@ -1,201 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   width="512"
-   height="512"
-   viewBox="0 0 135.46667 135.46667"
-   version="1.1"
-   id="svg5"
-   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
-   sodipodi:docname="libvcs-dark.svg"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:dc="http://purl.org/dc/elements/1.1/">
-  <title
-     id="title393">logo (dark)</title>
-  <sodipodi:namedview
-     id="namedview7"
-     pagecolor="#505050"
-     bordercolor="#000000"
-     borderopacity="1"
-     inkscape:pageshadow="0"
-     inkscape:pageopacity="0"
-     inkscape:pagecheckerboard="true"
-     inkscape:document-units="mm"
-     showgrid="false"
-     inkscape:showpageshadow="false"
-     showborder="true"
-     borderlayer="true"
-     inkscape:zoom="0.94867184"
-     inkscape:cx="198.69885"
-     inkscape:cy="249.2959"
-     inkscape:window-width="1350"
-     inkscape:window-height="1230"
-     inkscape:window-x="628"
-     inkscape:window-y="61"
-     inkscape:window-maximized="0"
-     inkscape:current-layer="layer1"
-     inkscape:deskcolor="#505050" />
-  <defs
-     id="defs2">
-    <linearGradient
-       x1="0"
-       y1="0"
-       x2="1"
-       y2="0"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0,86.542561,-86.542561,0,109.17781,96.083295)"
-       spreadMethod="pad"
-       id="linearGradient1191">
-      <stop
-         style="stop-opacity:1;stop-color:#858585"
-         offset="0"
-         id="stop1187" />
-      <stop
-         style="stop-opacity:1;stop-color:#7e7e7e"
-         offset="1"
-         id="stop1189" />
-    </linearGradient>
-    <linearGradient
-       x1="0"
-       y1="0"
-       x2="1"
-       y2="0"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0,67.63151,-67.63151,0,104.41712,78.165762)"
-       spreadMethod="pad"
-       id="linearGradient1223">
-      <stop
-         style="stop-opacity:1;stop-color:#565656"
-         offset="0"
-         id="stop1219" />
-      <stop
-         style="stop-opacity:1;stop-color:#2f2e2e"
-         offset="1"
-         id="stop1221" />
-    </linearGradient>
-    <linearGradient
-       x1="0"
-       y1="0"
-       x2="1"
-       y2="0"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0,41.305517,-41.305517,0,94.412207,128.26021)"
-       spreadMethod="pad"
-       id="linearGradient1255">
-      <stop
-         style="stop-opacity:1;stop-color:#565656"
-         offset="0"
-         id="stop1251" />
-      <stop
-         style="stop-opacity:1;stop-color:#2f2e2e"
-         offset="1"
-         id="stop1253" />
-    </linearGradient>
-  </defs>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-45.411955,-68.2879)">
-    <path
-       d="m 180.87851,136.02017 c 0,37.40758 -30.3252,67.73227 -67.73344,67.73227 -37.407905,0 -67.733117,-30.32469 -67.733117,-67.73227 0,-37.407254 30.325212,-67.73227 67.733117,-67.73227 37.40824,0 67.73344,30.325016 67.73344,67.73227"
-       style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264582"
-       id="Circle-object-shape"
-       inkscape:label="Circle-object-shape">
-      <title
-         id="title2462">Circle object (shape)</title>
-    </path>
-    <g
-       id="Gear-object-Group"
-       inkscape:label="Gear-object-Group"
-       transform="matrix(1.2447326,0,0,1.244711,-11.113788,-16.7108)"
-       style="stroke-width:0.803393">
-      <title
-         id="title1863">Gear object (Group)</title>
-      <path
-         d="m 107.84563,94.393541 c -0.6559,0 -1.28058,0.15875 -1.82827,0.441854 v 0 c -0.0794,0.03969 -0.1561,0.08493 -0.23018,0.129911 v 0 c -0.0876,0.05239 -0.16934,0.108214 -0.25136,0.166423 v 0 c -0.0926,0.06615 -0.18256,0.137583 -0.26987,0.211666 v 0 c -0.0476,0.03969 -0.0926,0.07937 -0.13785,0.121709 v 0 c -0.10292,0.0926 -0.19817,0.195791 -0.29078,0.301625 v 0 0.0026 c -0.11377,0.127264 -0.21431,0.264583 -0.30956,0.407458 v 0 c -0.0476,0.07408 -0.0926,0.148166 -0.13494,0.22225 v 0 c -0.10054,0.179916 -0.18785,0.365125 -0.26194,0.558271 v 0 c -0.0185,0.05027 -0.0368,0.0979 -0.0532,0.148166 v 0 c -0.12144,0.362744 -0.19023,0.748771 -0.20082,1.150938 v 0 l -0.21404,8.490478 c -0.006,0.16404 -0.0212,0.32543 -0.0479,0.48418 v 0 c -0.0135,0.0688 -0.0265,0.13759 -0.0421,0.20373 v 0 c -0.0505,0.20109 -0.12197,0.39423 -0.20664,0.5768 v 0 c -0.058,0.12435 -0.12409,0.24368 -0.19579,0.35983 v 0 c -0.045,0.0714 -0.0953,0.14023 -0.14526,0.20902 v 0 c -0.10081,0.13494 -0.21193,0.25929 -0.33628,0.37835 v 0 c -0.30163,0.29634 -0.67205,0.53182 -1.08771,0.68792 v 0 c -1.066,0.39688 -2.105815,0.84138 -3.124461,1.32821 v 0 c -1.187715,0.5715 -2.606146,0.35189 -3.563938,-0.55563 v 0 l -5.971646,-5.67795 c -1.561041,-1.48432 -4.01902,-1.45257 -5.54011,0.0688 v 0 l -9.371806,9.37154 c -0.251354,0.25135 -0.463021,0.52917 -0.635,0.8255 v 0 c -0.05821,0.10054 -0.108479,0.20108 -0.156104,0.30427 v 0 c -0.02646,0.0582 -0.05292,0.11642 -0.07673,0.17727 v 0 c -0.0926,0.23283 -0.164042,0.4736 -0.214313,0.71993 v 0 c -0.0026,0.005 -0.0026,0.0103 -0.0026,0.0156 v 0 c -0.02646,0.12436 -0.04233,0.24871 -0.05292,0.37571 v 0 c -0.01587,0.16669 -0.02117,0.33338 -0.01587,0.50006 v 0 c -0.0026,0.037 0,0.0741 0.0026,0.11113 v 0 c -0.0026,0.0106 0,0.0212 0,0.0318 v 0 c -0.0079,0.13229 -0.0079,0.26458 0,0.39661 v 0 c -0.0079,0.14314 -0.0079,0.28601 0,0.43153 v 0 c -0.0079,0.14261 -0.0079,0.28549 0,0.42863 v 0 c -0.0079,0.14287 -0.0079,0.28575 0,0.43127 v 0 c -0.0079,0.14287 -0.0079,0.28575 0,0.42862 v 0 c -0.0079,0.14288 -0.0079,0.28575 0,0.43128 v 0 c -0.0079,0.14287 -0.0079,0.28575 0,0.42862 v 0 c -0.05556,1.0504 0.301625,2.12196 1.082145,2.94217 v 0 l 5.855229,6.1595 c 0.148167,0.15584 0.278078,0.32279 0.388938,0.5027 v 0 0.003 c -0.0979,0.22199 -0.193146,0.4445 -0.288396,0.66702 v 0 c -0.280458,0.67177 -0.545042,1.35175 -0.788458,2.04231 v 0 c -0.436563,1.24381 -1.595438,2.08757 -2.913063,2.12196 v 0 l -8.233833,0.20638 c -0.224896,0.006 -0.4445,0.0291 -0.656167,0.0714 v 0 h -0.0026 c -0.727605,0.14023 -1.383771,0.4789 -1.910292,0.9578 v 0 c -0.07673,0.0659 -0.150813,0.14023 -0.219604,0.21431 v 0 c -0.03969,0.0394 -0.07408,0.0794 -0.108479,0.11933 v 0 c -0.0344,0.0368 -0.06615,0.0738 -0.0926,0.1135 v 0 c -0.08996,0.11113 -0.174625,0.22754 -0.253735,0.34925 v 0 c -0.106098,0.16404 -0.198702,0.33602 -0.278077,0.51329 v 0 c -0.07937,0.17701 -0.145785,0.36248 -0.201083,0.55298 v 0 c -0.02646,0.0952 -0.05001,0.19315 -0.06879,0.29104 v 0 c -0.05027,0.25162 -0.07673,0.51065 -0.07673,0.77788 v 0 13.25271 0.006 3.43958 c 0,2.15371 1.7145,3.91319 3.868208,3.96875 v 0 l 8.490479,0.21432 c 0.116417,0.003 0.227542,0.0132 0.341048,0.0291 v 0 c 0,0 0,0.003 0.0026,0 v 0 c 0.913077,0.11933 1.722702,0.635 2.222764,1.39144 v 0 c 0,0.003 0.0026,0.003 0.0026,0.003 v 0 c 0.129646,0.1958 0.238125,0.41011 0.322792,0.63739 v 0 c 0.34925,0.93689 0.738187,1.85234 1.156229,2.75193 v 0 c -0.0026,0.003 -0.0026,0.005 -0.0053,0.008 v 0 c -0.02646,0.0426 -0.05556,0.0847 -0.08467,0.127 v 0 c -0.08731,0.12727 -0.185209,0.24898 -0.293688,0.36248 v 0 l -5.593291,5.88434 c 7.554118,3.97404 16.158104,6.22035 25.286229,6.22035 v 0 c 7.728483,0 15.078873,-1.61131 21.738173,-4.5167 v 0 c -2.23838,0.5506 -4.58021,0.83106 -6.9903,0.80989 v 0 c -2.92655,-0.0238 -5.75204,-0.50033 -8.40845,-1.36525 v 0 c -0.17727,-0.0582 -0.35455,-0.11668 -0.52917,-0.17727 v 0 c -0.17463,-0.0609 -0.34925,-0.12436 -0.52388,-0.18786 v 0 c -2.08994,-0.76438 -4.06373,-1.77535 -5.89518,-2.99243 v 0 c -0.454554,-0.30427 -0.904875,-0.62177 -1.341173,-0.95012 v 0 c -0.132291,-0.10028 -0.264583,-0.20082 -0.394493,-0.30136 v 0 c -0.195263,-0.15346 -0.391055,-0.30957 -0.584465,-0.46541 v 0 c -0.1905,-0.15927 -0.381,-0.31776 -0.568854,-0.4818 v 0 c -0.388938,-0.33338 -0.764646,-0.67998 -1.132417,-1.03981 v 0 c -0.124354,-0.11907 -0.246062,-0.23813 -0.367771,-0.35984 v 0 c -0.161395,-0.15875 -0.3175,-0.3175 -0.470958,-0.48154 v 0 c -0.145521,-0.15081 -0.28575,-0.30401 -0.428625,-0.46037 v 0 c -0.320146,-0.34661 -0.629708,-0.70115 -0.928687,-1.06627 v 0 c -0.100542,-0.12171 -0.198438,-0.24342 -0.296334,-0.36513 v 0 c -0.174625,-0.21722 -0.344223,-0.43921 -0.513291,-0.66146 v 0 c -0.01058,-0.0159 -0.02143,-0.0317 -0.0344,-0.045 v 0 c -0.127,-0.16933 -0.254,-0.34131 -0.373063,-0.51329 v 0 c -0.132291,-0.18256 -0.259027,-0.36777 -0.386291,-0.55298 v 0 c -0.129646,-0.18521 -0.254,-0.37306 -0.372798,-0.56356 v 0 c -0.119327,-0.17965 -0.233363,-0.35983 -0.344223,-0.5424 v 0 c -0.0079,-0.0103 -0.01323,-0.0185 -0.01561,-0.0291 v 0 c -0.121708,-0.19315 -0.238389,-0.38629 -0.349514,-0.58208 v 0 c -0.227542,-0.38894 -0.4445,-0.78582 -0.650875,-1.18798 v 0 c -0.08493,-0.15875 -0.164042,-0.3175 -0.243417,-0.4789 v 0 c -0.04498,-0.0847 -0.08731,-0.17462 -0.127,-0.26194 v 0 c -0.07144,-0.14287 -0.140229,-0.28839 -0.203729,-0.43391 v 0 l -0.03175,-0.0635 c -0.0926,-0.20109 -0.182563,-0.40191 -0.267229,-0.6059 v 0 c -0.0926,-0.20637 -0.177006,-0.41539 -0.261938,-0.62706 v 0 -0.005 c -0.08731,-0.2114 -0.169333,-0.42334 -0.245798,-0.63527 v 0 c -0.08228,-0.21405 -0.159279,-0.42836 -0.233362,-0.64505 v 0 c -0.07382,-0.21722 -0.147902,-0.43418 -0.216694,-0.65088 v 0 c -0.01058,-0.032 -0.02117,-0.0661 -0.03175,-0.0982 v 0 c -0.0291,-0.087 -0.05556,-0.17727 -0.08202,-0.26749 v 0 c -0.02672,-0.0897 -0.05265,-0.17965 -0.07937,-0.26961 v 0 c -0.0026,-0.0106 -0.0053,-0.0212 -0.01058,-0.0317 v 0 c -0.06323,-0.21961 -0.124619,-0.43947 -0.182562,-0.65881 v 0 c -0.06085,-0.21961 -0.116417,-0.44186 -0.166688,-0.66411 v 0 c 0,-0.003 -0.0026,-0.005 -0.0026,-0.0106 v 0 c -0.03731,-0.14552 -0.07144,-0.29104 -0.100541,-0.43656 v 0 c -0.02381,-0.10319 -0.04498,-0.20902 -0.06879,-0.31486 v 0 c -0.185208,-0.88106 -0.328083,-1.77271 -0.428625,-2.68023 v 0 c -0.04762,-0.45508 -0.08731,-0.91281 -0.116417,-1.37583 v 0 c 0.896938,-14.91721 13.337646,-26.72027 28.506212,-26.59089 v 0 c 5.96635,0.0505 11.50937,1.9767 16.06549,5.21018 v 0 l 0.003,0.002 c 2.47121,1.75154 4.64899,3.88646 6.44499,6.32089 v 0 c 3.16203,4.26773 5.15434,9.44563 5.49566,15.04421 v 0 c 0.003,0.0132 0.003,0.0238 -0.003,0.0344 v 0 c -0.0132,0.22225 -0.0291,0.44185 -0.0476,0.66145 v 0 c -0.0185,0.23019 -0.0397,0.46038 -0.0664,0.68766 v 0 c -0.0212,0.21457 -0.0476,0.42862 -0.0762,0.6432 v 0 c -0.008,0.0661 -0.0164,0.13494 -0.0267,0.19844 v 0 c -0.0212,0.1561 -0.045,0.30956 -0.0688,0.46302 v 0 c -0.0106,0.0847 -0.0236,0.16668 -0.0397,0.24606 v 0 c -0.0265,0.1614 -0.0556,0.32544 -0.0847,0.48683 v 0 c -0.0397,0.21961 -0.0823,0.43921 -0.127,0.65617 v 0 c -0.33867,1.63274 -0.81757,3.21204 -1.42611,4.72546 v 0 c -0.0661,0.1696 -0.13494,0.33602 -0.20637,0.50271 v 0 c -0.0873,0.21166 -0.17992,0.42068 -0.27517,0.6297 v 0 c -0.0955,0.20903 -0.1905,0.41566 -0.2884,0.62151 v 0 c -0.003,0.003 -0.005,0.008 -0.005,0.0108 v 0 c -0.0976,0.20373 -0.1987,0.40481 -0.30427,0.60563 v 0 c -0.10292,0.20399 -0.20902,0.40508 -0.32014,0.60616 v 0 c -0.1061,0.20108 -0.21696,0.40217 -0.33311,0.59796 v 0 c -0.11139,0.19844 -0.22781,0.39423 -0.34687,0.58737 v 0 c -0.34952,0.57415 -0.71702,1.13507 -1.10596,1.67984 v 0 c -0.0106,0.0188 -0.0238,0.0376 -0.037,0.0532 v 0 c -0.0526,0.0823 -0.11139,0.1614 -0.16934,0.24078 v 0 c 7.62794,-7.39775 13.09423,-17.018 15.35907,-27.813 v 0 c -1.25704,-0.0662 -2.3548,-0.87286 -2.79956,-2.05582 v 0 c -0.34872,-0.93636 -0.73528,-1.85208 -1.1557,-2.75166 v 0 c 0,0 0,-0.003 0.003,-0.003 v 0 c 0.10821,-0.17462 0.23521,-0.33867 0.38073,-0.49477 v 0 l 4.72281,-4.96649 c 0.008,-0.31989 0.0109,-0.6403 0.0109,-0.96282 v 0 c 0,-0.81756 -0.0188,-1.62984 -0.0561,-2.43681 v 0 c -0.127,-2.9263 -0.48657,-5.78909 -1.06071,-8.57515 v 0 l -7.37923,-7.37923 c -1.52136,-1.524 -3.97934,-1.5531 -5.54064,-0.0714 v 0 l -2.48153,2.36009 -3.67771,3.49514 c -0.1905,0.18256 -0.39925,0.33602 -0.6215,0.46302 v 0 c -0.61146,0.34396 -1.32292,0.47916 -2.01639,0.37571 v 0 c -0.29634,-0.0397 -0.59003,-0.127 -0.87048,-0.254 v 0 c -1.02421,-0.46831 -2.07434,-0.89429 -3.14616,-1.27264 v 0 c -0.41222,-0.14553 -0.78291,-0.37042 -1.09511,-0.65882 v 0 c -0.10293,-0.0953 -0.20109,-0.19579 -0.29105,-0.30427 v 0 -0.003 c -0.0738,-0.0847 -0.14022,-0.17463 -0.20108,-0.26723 v 0 c -0.12435,-0.18521 -0.22754,-0.38629 -0.31221,-0.59532 v 0 c -0.0767,-0.19314 -0.13467,-0.39422 -0.17224,-0.60325 v 0 c -0.0288,-0.15875 -0.0447,-0.32279 -0.05,-0.48683 v 0 l -0.11906,-4.77044 -0.0873,-3.463388 c -0.0106,-0.402167 -0.0794,-0.788194 -0.20109,-1.150938 v 0 c -0.0161,-0.05027 -0.0344,-0.0979 -0.0529,-0.148166 v 0 c -0.0741,-0.193146 -0.1614,-0.378355 -0.26194,-0.558271 v 0 c -0.0423,-0.07408 -0.0876,-0.148167 -0.13494,-0.22225 v 0 c -0.0955,-0.142875 -0.19579,-0.280194 -0.30956,-0.407458 v 0 -0.0026 c -0.0926,-0.105834 -0.18785,-0.209021 -0.29078,-0.301625 v 0 c -0.0452,-0.04233 -0.0905,-0.08202 -0.13784,-0.121709 v 0 c -0.0873,-0.07408 -0.17728,-0.14552 -0.26988,-0.211666 v 0 c -0.082,-0.05821 -0.16378,-0.114036 -0.25135,-0.166423 v 0 c -0.0741,-0.04498 -0.15082,-0.09022 -0.23019,-0.129911 v 0 c -0.54769,-0.283104 -1.17237,-0.441854 -1.82827,-0.441854 v 0 z"
-         style="fill:url(#linearGradient1191);stroke:none;stroke-width:0.212564"
-         id="Gear-Shadow-object-Shape"
-         inkscape:label="Gear-Shadow-object-Shape">
-        <title
-           id="title1972">Gear Shadow object (Shape)</title>
-      </path>
-      <g
-         id="g1195"
-         transform="matrix(0.26458333,0,0,-0.26458333,35.889552,188.84979)"
-         style="stroke-width:0.803393">
-        <path
-           d="m 432.3496,215.3398 c -1.319,3.53 -2.77,6.99 -4.359,10.38 -0.21,0.471 -0.43,0.95 -0.661,1.42 -2.16,4.5 -1.33,9.85 2.1,13.471 l 17.68,18.599 c -0.48,11.06 -1.84,21.88 -4.01,32.41 v 0.03 l -27.89,27.89 c -5.75,5.75 -15.04,5.87 -20.94,0.26 l -9.39,-8.92 -13.889,-13.21 c -0.721,-0.69 -1.521,-1.27 -2.361,-1.75 -2.319,-1.31 -5,-1.8 -7.62,-1.41 -1.119,0.16 -2.22,0.48 -3.279,0.96 -3.871,1.77 -7.84,3.37 -11.891,4.8 -1.559,0.55 -2.96,1.4 -4.139,2.47 -0.39,0.36 -0.761,0.74 -1.101,1.15 v 0.01 c -0.27,0.32 -0.52,0.66 -0.76,1.01 -0.469,0.7 -0.859,1.46 -1.179,2.25 -0.29,0.73 -0.51,1.49 -0.651,2.28 -0.109,0.6 -0.17,1.22 -0.189,1.84 l -0.45,18.03 -0.331,13.09 c -0.04,1.52 -0.299,2.98 -0.759,4.35 -0.061,0.19 -0.13,0.37 -0.201,0.56 -0.269,0.73 -0.599,1.44 -0.99,2.11 -0.16,0.28 -0.33,0.56 -0.51,0.84 -0.36,0.54 -0.74,1.06 -1.169,1.54 v 0.01 c -0.35,0.4 -0.71,0.79 -1.1,1.14 -0.171,0.16 -0.341,0.31 -0.521,0.46 -0.33,0.28 -0.669,0.55 -1.02,0.8 -0.31,0.22 -0.619,0.43 -0.949,0.63 -0.281,0.17 -0.571,0.34 -0.87,0.49 -2.071,1.09 -4.42,1.69 -6.911,1.69 h -50.08 c -2.49,0 -4.839,-0.6 -6.91,-1.69 -0.3,-0.15 -0.59,-0.32 -0.87,-0.49 -0.33,-0.2 -0.64,-0.41 -0.949,-0.63 -0.351,-0.25 -0.691,-0.52 -1.021,-0.8 -0.179,-0.15 -0.349,-0.3 -0.52,-0.46 -0.39,-0.35 -0.75,-0.74 -1.1,-1.14 v -0.01 c -0.429,-0.48 -0.809,-1 -1.17,-1.54 -0.179,-0.28 -0.349,-0.56 -0.509,-0.84 -0.391,-0.67 -0.721,-1.38 -0.991,-2.11 -0.07,-0.19 -0.139,-0.37 -0.2,-0.56 -0.46,-1.37 -0.72,-2.83 -0.76,-4.35 l -0.809,-32.09 c -0.021,-0.62 -0.08,-1.23 -0.181,-1.83 -0.05,-0.26 -0.099,-0.52 -0.159,-0.77 -0.19,-0.76 -0.461,-1.49 -0.78,-2.18 -0.22,-0.47 -0.47,-0.92 -0.741,-1.36 -0.169,-0.27 -0.36,-0.53 -0.549,-0.79 -0.391,-0.51 -0.811,-0.98 -1.271,-1.43 -1.159,-1.1 -2.55,-1.99 -4.11,-2.57 -4.03,-1.5 -7.96,-3.18 -11.81,-5.03 -4.49,-2.16 -9.849,-1.33 -13.47,2.11 l -22.57,21.46 c -5.9,5.6 -15.189,5.48 -20.939,-0.27 l -35.421,-35.41 c -0.96,-0.97 -1.759,-2.02 -2.4,-3.15 -0.219,-0.38 -0.41,-0.76 -0.589,-1.15 -0.101,-0.22 -0.201,-0.44 -0.29,-0.67 -0.371,-0.88 -0.63,-1.79 -0.811,-2.72 -0.01,-0.02 -0.01,-0.04 -0.01,-0.06 -0.099,-0.47 -0.159,-0.94 -0.2,-1.42 -0.06,-0.63 -0.08,-1.26 -0.06,-1.89 -0.009,-0.14 0,-0.28 0.01,-0.42 -0.01,-0.04 0,-0.08 0,-0.12 0.21,-3.38 1.58,-6.7 4.091,-9.34 l 22.129,-23.28 c 3.38,-3.56 4.25,-8.8 2.21,-13.26 -0.25,-0.55 -0.51,-1.109 -0.739,-1.67 v -0.01 c -0.37,-0.84 -0.731,-1.679 -1.091,-2.52 -1.07,-2.52 -2.06,-5.09 -2.98,-7.69 -1.65,-4.7 -6.029,-7.889 -11.009,-8.02 l -31.121,-0.79 c -0.85,-0.02 -1.68,-0.11 -2.49,-0.27 h -0.01 c -2.75,-0.53 -5.24,-1.82 -7.21,-3.639 -0.29,-0.25 -0.57,-0.531 -0.83,-0.811 -0.15,-0.149 -0.28,-0.3 -0.41,-0.45 -0.13,-0.14 -0.25,-0.279 -0.349,-0.43 -0.341,-0.42 -0.661,-0.86 -0.96,-1.32 -0.401,-0.62 -0.75,-1.27 -1.051,-1.94 -0.3,-0.67 -0.56,-1.37 -0.76,-2.089 -0.099,-0.361 -0.189,-0.731 -0.26,-1.101 -0.19,-0.95 -0.29,-1.93 -0.29,-2.94 v -50.089 -0.021 c 0.01,-8.12 6.491,-14.769 14.62,-14.97 l 16.01,-0.4 h 0.01 l 16.07,-0.41 c 4.901,-0.13 9.22,-3.21 10.93,-7.8 1.5,-4.019 3.181,-7.96 5.03,-11.8 0.42,-0.88 0.731,-1.79 0.93,-2.719 0.641,-3.051 0.08,-6.25 -1.59,-8.901 -0.01,-0.01 -0.01,-0.019 -0.019,-0.03 -0.101,-0.16 -0.21,-0.319 -0.321,-0.48 -0.34,-0.469 -0.71,-0.92 -1.11,-1.339 l -21.159,-22.261 c 0,-0.01 0.009,-0.01 0.019,-0.01 28.551,-15.02 61.071,-23.51 95.571,-23.51 29.21,0 56.99,6.09 82.16,17.071 0.05,0.019 0.09,0.04 0.139,0.059 -8.49,-2.099 -17.399,-3.18 -26.559,-3.099 -11.061,0.089 -21.74,1.889 -31.78,5.139 -0.67,0.22 -1.34,0.441 -2,0.67 -0.661,0.231 -1.321,0.47 -1.981,0.71 -7.899,2.91 -15.359,6.72 -22.28,11.311 -1.719,1.149 -3.42,2.349 -5.07,3.589 -0.5,0.38 -1,0.76 -1.49,1.14 -0.74,0.58 -1.479,1.17 -2.21,1.76 -0.719,0.61 -1.429,1.21 -2.13,1.82 -1.469,1.27 -2.91,2.58 -4.299,3.93 -0.471,0.45 -0.931,0.9 -1.391,1.36 -0.6,0.6 -1.19,1.21 -1.779,1.821 -0.551,0.569 -1.08,1.149 -1.62,1.739 -1.201,1.31 -2.371,2.66 -3.511,4.03 -0.38,0.46 -0.75,0.92 -1.119,1.38 -0.661,0.82 -1.301,1.66 -1.941,2.5 -0.04,0.06 -0.08,0.12 -0.13,0.17 -0.469,0.64 -0.95,1.29 -1.41,1.94 -0.5,0.69 -0.979,1.39 -1.46,2.09 -0.479,0.71 -0.95,1.42 -1.409,2.13 -0.44,0.68 -0.871,1.36 -1.291,2.05 -0.029,0.04 -0.05,0.08 -0.069,0.11 -0.451,0.731 -0.89,1.46 -1.321,2.2 -0.85,1.48 -1.67,2.97 -2.46,4.491 -0.31,0.599 -0.62,1.199 -0.92,1.809 -0.16,0.33 -0.32,0.66 -0.48,0.99 -0.26,0.54 -0.52,1.09 -0.77,1.64 l -0.12,0.24 c -0.339,0.76 -0.679,1.52 -1.009,2.29 -0.341,0.79 -0.67,1.58 -0.991,2.37 v 0.02 c -0.319,0.8 -0.63,1.601 -0.929,2.4 -0.311,0.81 -0.601,1.62 -0.881,2.44 -0.279,0.82 -0.56,1.64 -0.82,2.46 -0.04,0.12 -0.08,0.24 -0.11,0.36 v 0.01 c -0.11,0.34 -0.22,0.681 -0.32,1.011 -0.1,0.339 -0.199,0.679 -0.3,1.019 -0.01,0.04 -0.02,0.08 -0.04,0.12 -0.239,0.83 -0.47,1.66 -0.689,2.491 -0.221,0.83 -0.431,1.669 -0.63,2.509 0,0.01 -0.011,0.02 -0.011,0.04 -0.13,0.55 -0.26,1.1 -0.38,1.65 -0.09,0.39 -0.17,0.79 -0.26,1.19 -0.699,3.33 -1.24,6.7 -1.62,10.13 -0.18,1.72 -0.329,3.45 -0.439,5.2 -0.111,1.85 -0.171,3.71 -0.191,5.59 -0.51,59.83 48.1,108.44 107.93,107.93 15.381,-0.13 30.02,-3.56 43.23,-9.6 19.241,-8.79 35.47,-23.139 46.61,-40.95 10.121,-16.16 16.051,-35.189 16.22,-55.51 0.02,-2.49 -0.04,-4.96 -0.2,-7.41 0.011,-0.05 0.011,-0.09 -0.009,-0.13 -0.041,-0.84 -0.101,-1.67 -0.181,-2.5 -0.069,-0.87 -0.15,-1.74 -0.25,-2.599 -0.08,-0.811 -0.18,-1.621 -0.289,-2.431 -0.03,-0.25 -0.061,-0.51 -0.101,-0.75 -0.08,-0.59 -0.17,-1.17 -0.26,-1.75 -0.04,-0.319 -0.089,-0.63 -0.149,-0.93 -0.101,-0.62 -0.201,-1.23 -0.32,-1.84 -0.151,-0.83 -0.311,-1.66 -0.481,-2.48 -1.279,-6.17 -3.09,-12.14 -5.389,-17.859 -0.25,-0.641 -0.511,-1.271 -0.781,-1.901 -0.34,-0.8 -0.689,-1.59 -1.04,-2.38 -0.36,-0.79 -0.719,-1.57 -1.09,-2.349 -0.009,-0.011 -0.02,-0.031 -0.02,-0.04 -0.379,-0.771 -0.76,-1.531 -1.149,-2.29 -0.39,-0.771 -0.791,-1.531 -1.21,-2.29 -0.411,-0.761 -0.831,-1.511 -1.26,-2.261 -0.42,-0.75 -0.861,-1.489 -1.311,-2.22 -1.32,-2.17 -2.71,-4.29 -4.179,-6.35 -0.04,-0.07 -0.09,-0.14 -0.141,-0.2 -0.239,-0.34 -0.48,-0.679 -0.73,-1.01 -0.24,-0.33 -0.479,-0.65 -0.719,-0.98 0.269,0.351 0.529,0.7 0.789,1.05 0.011,0 0.011,0.011 0.02,0.03 28.83,27.96 49.491,64.32 58.05,105.12 0,0.01 0.01,0.01 0,0.02 -4.75,0.25 -8.899,3.301 -10.58,7.78"
-           style="fill:#aaa8a8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.803393"
-           id="Gear-object-Shape"
-           inkscape:label="Gear-object-Shape">
-          <title
-             id="title2012">Gear object (Shape)</title>
-        </path>
-      </g>
-    </g>
-    <g
-       id="Arrow_1-object-Group"
-       inkscape:label="Arrow 1-object-Group"
-       transform="matrix(1.2447326,0,0,1.244711,-11.113788,-16.7108)"
-       style="stroke-width:0.803393">
-      <title
-         id="title1865">Arrow 1 object (Group)</title>
-      <path
-         d="M 76.007529,86.855562 C 69.342674,91.551916 64.296806,98.036854 61.405175,105.61717 v 0 5.82083 h 5.728229 C 72.790195,98.875583 85.484903,90.57825 99.38082,90.57825 v 0 c 14.94605,0 27.91407,9.313068 33.02582,22.70945 v 0 l -6.09865,-0.0421 v 5.82084 l 10.43332,13.78002 10.68758,-13.63371 v -5.8211 l -7.97269,-0.055 C 136.20659,93.889245 119.32141,79.466014 99.38082,79.466014 v 0 c -8.424333,0 -16.507619,2.555611 -23.373291,7.389548"
-         style="fill:url(#linearGradient1223);stroke:none;stroke-width:0.212564"
-         id="Arrow-1-Shadow-object-Shape"
-         inkscape:label="Arrow-1-Shadow-object-Shape">
-        <title
-           id="title1930">Arrow 1 Shadow object (Shape)</title>
-      </path>
-      <path
-         d="m 139.45636,113.33657 c -3.24961,-19.447139 -20.13506,-33.8709 -40.075643,-33.8709 -8.424333,0 -16.507354,2.55614 -23.373292,7.389813 -6.664854,4.696354 -11.710458,11.181291 -14.602354,18.761607 H 67.1333 c 5.656792,-12.56242 18.3515,-20.859753 32.247417,-20.859753 17.031753,0 31.496533,12.092781 34.691903,28.541923 l -7.76446,-0.0537 10.43305,13.78003 10.6881,-13.63398 z"
-         style="fill:#7f7f7f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.212564"
-         id="Arrow-1-object-Shape"
-         inkscape:label="Arrow-1-object-Shape">
-        <title
-           id="title1888">Arrow 1 object (Shape)</title>
-      </path>
-    </g>
-    <g
-       id="Arrow_2-object-Group"
-       inkscape:label="Arrow 2-object-Group"
-       transform="matrix(1.2447326,0,0,1.244711,-11.113788,-16.7108)"
-       style="stroke-width:0.803393">
-      <title
-         id="title2458">Arrow 2 object (Group)</title>
-      <path
-         d="m 51.400221,126.8685 v 5.82083 l 7.972689,0.055 c 3.249612,19.4474 20.135056,33.87116 40.075643,33.87116 v 0 c 8.424597,0 16.507357,-2.55588 23.373557,-7.38981 v 0 c 6.66459,-4.69662 11.71019,-11.18156 14.60209,-18.76187 v 0 l -5.3e-4,-5.81925 c 2.6e-4,-5.3e-4 2.6e-4,-0.001 5.3e-4,-0.002 v 0 h -5.3e-4 v -2.7e-4 h -5.72797 v 0.002 c -5.65705,12.56162 -18.35176,20.85843 -32.247147,20.85843 v 0 c -14.946047,0 -27.914335,-9.31281 -33.02582,-22.70946 v 0 l 6.098646,0.0423 v -5.8211 L 62.088064,113.23452 Z"
-         style="fill:url(#linearGradient1255);stroke:none;stroke-width:0.212564"
-         id="Arrow-2-Shadow-object-Shape"
-         inkscape:label="Arrow-2-Shadow-object-Shape">
-        <title
-           id="title1932">Arrow 2 Shadow object (Shape)</title>
-      </path>
-      <path
-         d="m 131.6961,134.64302 c -5.65679,12.56242 -18.3515,20.85975 -32.247416,20.85975 -17.031758,0 -31.496794,-12.09278 -34.692166,-28.54193 l 7.764726,0.0537 -10.433049,-13.78003 -10.687844,13.63398 7.972689,0.055 c 3.249613,19.4474 20.134792,33.8709 40.075644,33.8709 8.424336,0 16.507356,-2.55561 23.373296,-7.38982 6.66458,-4.69635 11.71045,-11.18129 14.60208,-18.7616 z"
-         style="fill:#7f7f7f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.212564"
-         id="Arrow-2-object-Shape"
-         inkscape:label="Arrow-2-object-Shape">
-        <title
-           id="title1890">Arrow 2 object (Shape)</title>
-      </path>
-    </g>
-  </g>
-  <metadata
-     id="metadata391">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:title>logo (dark)</dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-</svg>
diff --git a/docs/_static/img/libvcs.svg b/docs/_static/img/libvcs.svg
deleted file mode 100644
index cb071e705..000000000
--- a/docs/_static/img/libvcs.svg
+++ /dev/null
@@ -1,186 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   width="512"
-   height="512"
-   viewBox="0 0 135.46667 135.46667"
-   version="1.1"
-   id="svg5"
-   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
-   sodipodi:docname="libvcs.svg"
-   inkscape:export-filename="libvcs.png"
-   inkscape:export-xdpi="96"
-   inkscape:export-ydpi="96"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:dc="http://purl.org/dc/elements/1.1/">
-  <title
-     id="title215">libvcs</title>
-  <sodipodi:namedview
-     id="namedview7"
-     pagecolor="#505050"
-     bordercolor="#000000"
-     borderopacity="1"
-     inkscape:pageshadow="0"
-     inkscape:pageopacity="0"
-     inkscape:pagecheckerboard="true"
-     inkscape:document-units="mm"
-     showgrid="false"
-     inkscape:showpageshadow="false"
-     showborder="true"
-     borderlayer="true"
-     inkscape:zoom="0.94867184"
-     inkscape:cx="168.12979"
-     inkscape:cy="174.98148"
-     inkscape:window-width="1428"
-     inkscape:window-height="931"
-     inkscape:window-x="941"
-     inkscape:window-y="224"
-     inkscape:window-maximized="0"
-     inkscape:current-layer="layer1"
-     inkscape:deskcolor="#505050" />
-  <defs
-     id="defs2">
-    <linearGradient
-       x1="-0.29159656"
-       y1="3.7747583e-15"
-       x2="1"
-       y2="0"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0,67.63151,-67.63151,0,104.41712,78.165762)"
-       spreadMethod="pad"
-       id="linearGradient1223">
-      <stop
-         style="stop-opacity:1;stop-color:#adadad"
-         offset="0"
-         id="stop1219" />
-      <stop
-         style="stop-opacity:1;stop-color:#2f2e2e"
-         offset="1"
-         id="stop1221" />
-    </linearGradient>
-    <linearGradient
-       x1="-1.0933492"
-       y1="2.1316282e-14"
-       x2="1"
-       y2="0"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0,41.305517,-41.305517,0,94.412207,128.26021)"
-       spreadMethod="pad"
-       id="linearGradient1255">
-      <stop
-         style="stop-opacity:1;stop-color:#acacac"
-         offset="0"
-         id="stop1251" />
-      <stop
-         style="stop-opacity:1;stop-color:#706e6f"
-         offset="1"
-         id="stop1253" />
-    </linearGradient>
-  </defs>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-45.411955,-68.2879)">
-    <path
-       d="m 180.87851,136.02017 c 0,37.40758 -30.3252,67.73227 -67.73344,67.73227 -37.407905,0 -67.733117,-30.32469 -67.733117,-67.73227 0,-37.407254 30.325212,-67.73227 67.733117,-67.73227 37.40824,0 67.73344,30.325016 67.73344,67.73227"
-       style="fill:#231f1e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.264582"
-       id="Circle-object-shape"
-       inkscape:label="Circle-object-shape">
-      <title
-         id="title2462">Circle object (shape)</title>
-    </path>
-    <g
-       id="Gear-object-Group"
-       inkscape:label="Gear-object-Group"
-       transform="matrix(1.2447326,0,0,1.244711,-11.113788,-16.7108)"
-       style="stroke-width:0.803393">
-      <title
-         id="title1863">Gear object (Group)</title>
-      <path
-         d="m 107.84563,94.393541 c -0.6559,0 -1.28058,0.15875 -1.82827,0.441854 v 0 c -0.0794,0.03969 -0.1561,0.08493 -0.23018,0.129911 v 0 c -0.0876,0.05239 -0.16934,0.108214 -0.25136,0.166423 v 0 c -0.0926,0.06615 -0.18256,0.137583 -0.26987,0.211666 v 0 c -0.0476,0.03969 -0.0926,0.07937 -0.13785,0.121709 v 0 c -0.10292,0.0926 -0.19817,0.195791 -0.29078,0.301625 v 0 0.0026 c -0.11377,0.127264 -0.21431,0.264583 -0.30956,0.407458 v 0 c -0.0476,0.07408 -0.0926,0.148166 -0.13494,0.22225 v 0 c -0.10054,0.179916 -0.18785,0.365125 -0.26194,0.558271 v 0 c -0.0185,0.05027 -0.0368,0.0979 -0.0532,0.148166 v 0 c -0.12144,0.362744 -0.19023,0.748771 -0.20082,1.150938 v 0 l -0.21404,8.490478 c -0.006,0.16404 -0.0212,0.32543 -0.0479,0.48418 v 0 c -0.0135,0.0688 -0.0265,0.13759 -0.0421,0.20373 v 0 c -0.0505,0.20109 -0.12197,0.39423 -0.20664,0.5768 v 0 c -0.058,0.12435 -0.12409,0.24368 -0.19579,0.35983 v 0 c -0.045,0.0714 -0.0953,0.14023 -0.14526,0.20902 v 0 c -0.10081,0.13494 -0.21193,0.25929 -0.33628,0.37835 v 0 c -0.30163,0.29634 -0.67205,0.53182 -1.08771,0.68792 v 0 c -1.066,0.39688 -2.105815,0.84138 -3.124461,1.32821 v 0 c -1.187715,0.5715 -2.606146,0.35189 -3.563938,-0.55563 v 0 l -5.971646,-5.67795 c -1.561041,-1.48432 -4.01902,-1.45257 -5.54011,0.0688 v 0 l -9.371806,9.37154 c -0.251354,0.25135 -0.463021,0.52917 -0.635,0.8255 v 0 c -0.05821,0.10054 -0.108479,0.20108 -0.156104,0.30427 v 0 c -0.02646,0.0582 -0.05292,0.11642 -0.07673,0.17727 v 0 c -0.0926,0.23283 -0.164042,0.4736 -0.214313,0.71993 v 0 c -0.0026,0.005 -0.0026,0.0103 -0.0026,0.0156 v 0 c -0.02646,0.12436 -0.04233,0.24871 -0.05292,0.37571 v 0 c -0.01587,0.16669 -0.02117,0.33338 -0.01587,0.50006 v 0 c -0.0026,0.037 0,0.0741 0.0026,0.11113 v 0 c -0.0026,0.0106 0,0.0212 0,0.0318 v 0 c -0.0079,0.13229 -0.0079,0.26458 0,0.39661 v 0 c -0.0079,0.14314 -0.0079,0.28601 0,0.43153 v 0 c -0.0079,0.14261 -0.0079,0.28549 0,0.42863 v 0 c -0.0079,0.14287 -0.0079,0.28575 0,0.43127 v 0 c -0.0079,0.14287 -0.0079,0.28575 0,0.42862 v 0 c -0.0079,0.14288 -0.0079,0.28575 0,0.43128 v 0 c -0.0079,0.14287 -0.0079,0.28575 0,0.42862 v 0 c -0.05556,1.0504 0.301625,2.12196 1.082145,2.94217 v 0 l 5.855229,6.1595 c 0.148167,0.15584 0.278078,0.32279 0.388938,0.5027 v 0 0.003 c -0.0979,0.22199 -0.193146,0.4445 -0.288396,0.66702 v 0 c -0.280458,0.67177 -0.545042,1.35175 -0.788458,2.04231 v 0 c -0.436563,1.24381 -1.595438,2.08757 -2.913063,2.12196 v 0 l -8.233833,0.20638 c -0.224896,0.006 -0.4445,0.0291 -0.656167,0.0714 v 0 h -0.0026 c -0.727605,0.14023 -1.383771,0.4789 -1.910292,0.9578 v 0 c -0.07673,0.0659 -0.150813,0.14023 -0.219604,0.21431 v 0 c -0.03969,0.0394 -0.07408,0.0794 -0.108479,0.11933 v 0 c -0.0344,0.0368 -0.06615,0.0738 -0.0926,0.1135 v 0 c -0.08996,0.11113 -0.174625,0.22754 -0.253735,0.34925 v 0 c -0.106098,0.16404 -0.198702,0.33602 -0.278077,0.51329 v 0 c -0.07937,0.17701 -0.145785,0.36248 -0.201083,0.55298 v 0 c -0.02646,0.0952 -0.05001,0.19315 -0.06879,0.29104 v 0 c -0.05027,0.25162 -0.07673,0.51065 -0.07673,0.77788 v 0 13.25271 0.006 3.43958 c 0,2.15371 1.7145,3.91319 3.868208,3.96875 v 0 l 8.490479,0.21432 c 0.116417,0.003 0.227542,0.0132 0.341048,0.0291 v 0 c 0,0 0,0.003 0.0026,0 v 0 c 0.913077,0.11933 1.722702,0.635 2.222764,1.39144 v 0 c 0,0.003 0.0026,0.003 0.0026,0.003 v 0 c 0.129646,0.1958 0.238125,0.41011 0.322792,0.63739 v 0 c 0.34925,0.93689 0.738187,1.85234 1.156229,2.75193 v 0 c -0.0026,0.003 -0.0026,0.005 -0.0053,0.008 v 0 c -0.02646,0.0426 -0.05556,0.0847 -0.08467,0.127 v 0 c -0.08731,0.12727 -0.185209,0.24898 -0.293688,0.36248 v 0 l -5.593291,5.88434 c 7.554118,3.97404 16.158104,6.22035 25.286229,6.22035 v 0 c 7.728483,0 15.078873,-1.61131 21.738173,-4.5167 v 0 c -2.23838,0.5506 -4.58021,0.83106 -6.9903,0.80989 v 0 c -2.92655,-0.0238 -5.75204,-0.50033 -8.40845,-1.36525 v 0 c -0.17727,-0.0582 -0.35455,-0.11668 -0.52917,-0.17727 v 0 c -0.17463,-0.0609 -0.34925,-0.12436 -0.52388,-0.18786 v 0 c -2.08994,-0.76438 -4.06373,-1.77535 -5.89518,-2.99243 v 0 c -0.454554,-0.30427 -0.904875,-0.62177 -1.341173,-0.95012 v 0 c -0.132291,-0.10028 -0.264583,-0.20082 -0.394493,-0.30136 v 0 c -0.195263,-0.15346 -0.391055,-0.30957 -0.584465,-0.46541 v 0 c -0.1905,-0.15927 -0.381,-0.31776 -0.568854,-0.4818 v 0 c -0.388938,-0.33338 -0.764646,-0.67998 -1.132417,-1.03981 v 0 c -0.124354,-0.11907 -0.246062,-0.23813 -0.367771,-0.35984 v 0 c -0.161395,-0.15875 -0.3175,-0.3175 -0.470958,-0.48154 v 0 c -0.145521,-0.15081 -0.28575,-0.30401 -0.428625,-0.46037 v 0 c -0.320146,-0.34661 -0.629708,-0.70115 -0.928687,-1.06627 v 0 c -0.100542,-0.12171 -0.198438,-0.24342 -0.296334,-0.36513 v 0 c -0.174625,-0.21722 -0.344223,-0.43921 -0.513291,-0.66146 v 0 c -0.01058,-0.0159 -0.02143,-0.0317 -0.0344,-0.045 v 0 c -0.127,-0.16933 -0.254,-0.34131 -0.373063,-0.51329 v 0 c -0.132291,-0.18256 -0.259027,-0.36777 -0.386291,-0.55298 v 0 c -0.129646,-0.18521 -0.254,-0.37306 -0.372798,-0.56356 v 0 c -0.119327,-0.17965 -0.233363,-0.35983 -0.344223,-0.5424 v 0 c -0.0079,-0.0103 -0.01323,-0.0185 -0.01561,-0.0291 v 0 c -0.121708,-0.19315 -0.238389,-0.38629 -0.349514,-0.58208 v 0 c -0.227542,-0.38894 -0.4445,-0.78582 -0.650875,-1.18798 v 0 c -0.08493,-0.15875 -0.164042,-0.3175 -0.243417,-0.4789 v 0 c -0.04498,-0.0847 -0.08731,-0.17462 -0.127,-0.26194 v 0 c -0.07144,-0.14287 -0.140229,-0.28839 -0.203729,-0.43391 v 0 l -0.03175,-0.0635 c -0.0926,-0.20109 -0.182563,-0.40191 -0.267229,-0.6059 v 0 c -0.0926,-0.20637 -0.177006,-0.41539 -0.261938,-0.62706 v 0 -0.005 c -0.08731,-0.2114 -0.169333,-0.42334 -0.245798,-0.63527 v 0 c -0.08228,-0.21405 -0.159279,-0.42836 -0.233362,-0.64505 v 0 c -0.07382,-0.21722 -0.147902,-0.43418 -0.216694,-0.65088 v 0 c -0.01058,-0.032 -0.02117,-0.0661 -0.03175,-0.0982 v 0 c -0.0291,-0.087 -0.05556,-0.17727 -0.08202,-0.26749 v 0 c -0.02672,-0.0897 -0.05265,-0.17965 -0.07937,-0.26961 v 0 c -0.0026,-0.0106 -0.0053,-0.0212 -0.01058,-0.0317 v 0 c -0.06323,-0.21961 -0.124619,-0.43947 -0.182562,-0.65881 v 0 c -0.06085,-0.21961 -0.116417,-0.44186 -0.166688,-0.66411 v 0 c 0,-0.003 -0.0026,-0.005 -0.0026,-0.0106 v 0 c -0.03731,-0.14552 -0.07144,-0.29104 -0.100541,-0.43656 v 0 c -0.02381,-0.10319 -0.04498,-0.20902 -0.06879,-0.31486 v 0 c -0.185208,-0.88106 -0.328083,-1.77271 -0.428625,-2.68023 v 0 c -0.04762,-0.45508 -0.08731,-0.91281 -0.116417,-1.37583 v 0 c 0.896938,-14.91721 13.337646,-26.72027 28.506212,-26.59089 v 0 c 5.96635,0.0505 11.50937,1.9767 16.06549,5.21018 v 0 l 0.003,0.002 c 2.47121,1.75154 4.64899,3.88646 6.44499,6.32089 v 0 c 3.16203,4.26773 5.15434,9.44563 5.49566,15.04421 v 0 c 0.003,0.0132 0.003,0.0238 -0.003,0.0344 v 0 c -0.0132,0.22225 -0.0291,0.44185 -0.0476,0.66145 v 0 c -0.0185,0.23019 -0.0397,0.46038 -0.0664,0.68766 v 0 c -0.0212,0.21457 -0.0476,0.42862 -0.0762,0.6432 v 0 c -0.008,0.0661 -0.0164,0.13494 -0.0267,0.19844 v 0 c -0.0212,0.1561 -0.045,0.30956 -0.0688,0.46302 v 0 c -0.0106,0.0847 -0.0236,0.16668 -0.0397,0.24606 v 0 c -0.0265,0.1614 -0.0556,0.32544 -0.0847,0.48683 v 0 c -0.0397,0.21961 -0.0823,0.43921 -0.127,0.65617 v 0 c -0.33867,1.63274 -0.81757,3.21204 -1.42611,4.72546 v 0 c -0.0661,0.1696 -0.13494,0.33602 -0.20637,0.50271 v 0 c -0.0873,0.21166 -0.17992,0.42068 -0.27517,0.6297 v 0 c -0.0955,0.20903 -0.1905,0.41566 -0.2884,0.62151 v 0 c -0.003,0.003 -0.005,0.008 -0.005,0.0108 v 0 c -0.0976,0.20373 -0.1987,0.40481 -0.30427,0.60563 v 0 c -0.10292,0.20399 -0.20902,0.40508 -0.32014,0.60616 v 0 c -0.1061,0.20108 -0.21696,0.40217 -0.33311,0.59796 v 0 c -0.11139,0.19844 -0.22781,0.39423 -0.34687,0.58737 v 0 c -0.34952,0.57415 -0.71702,1.13507 -1.10596,1.67984 v 0 c -0.0106,0.0188 -0.0238,0.0376 -0.037,0.0532 v 0 c -0.0526,0.0823 -0.11139,0.1614 -0.16934,0.24078 v 0 c 7.62794,-7.39775 13.09423,-17.018 15.35907,-27.813 v 0 c -1.25704,-0.0662 -2.3548,-0.87286 -2.79956,-2.05582 v 0 c -0.34872,-0.93636 -0.73528,-1.85208 -1.1557,-2.75166 v 0 c 0,0 0,-0.003 0.003,-0.003 v 0 c 0.10821,-0.17462 0.23521,-0.33867 0.38073,-0.49477 v 0 l 4.72281,-4.96649 c 0.008,-0.31989 0.0109,-0.6403 0.0109,-0.96282 v 0 c 0,-0.81756 -0.0188,-1.62984 -0.0561,-2.43681 v 0 c -0.127,-2.9263 -0.48657,-5.78909 -1.06071,-8.57515 v 0 l -7.37923,-7.37923 c -1.52136,-1.524 -3.97934,-1.5531 -5.54064,-0.0714 v 0 l -2.48153,2.36009 -3.67771,3.49514 c -0.1905,0.18256 -0.39925,0.33602 -0.6215,0.46302 v 0 c -0.61146,0.34396 -1.32292,0.47916 -2.01639,0.37571 v 0 c -0.29634,-0.0397 -0.59003,-0.127 -0.87048,-0.254 v 0 c -1.02421,-0.46831 -2.07434,-0.89429 -3.14616,-1.27264 v 0 c -0.41222,-0.14553 -0.78291,-0.37042 -1.09511,-0.65882 v 0 c -0.10293,-0.0953 -0.20109,-0.19579 -0.29105,-0.30427 v 0 -0.003 c -0.0738,-0.0847 -0.14022,-0.17463 -0.20108,-0.26723 v 0 c -0.12435,-0.18521 -0.22754,-0.38629 -0.31221,-0.59532 v 0 c -0.0767,-0.19314 -0.13467,-0.39422 -0.17224,-0.60325 v 0 c -0.0288,-0.15875 -0.0447,-0.32279 -0.05,-0.48683 v 0 l -0.11906,-4.77044 -0.0873,-3.463388 c -0.0106,-0.402167 -0.0794,-0.788194 -0.20109,-1.150938 v 0 c -0.0161,-0.05027 -0.0344,-0.0979 -0.0529,-0.148166 v 0 c -0.0741,-0.193146 -0.1614,-0.378355 -0.26194,-0.558271 v 0 c -0.0423,-0.07408 -0.0876,-0.148167 -0.13494,-0.22225 v 0 c -0.0955,-0.142875 -0.19579,-0.280194 -0.30956,-0.407458 v 0 -0.0026 c -0.0926,-0.105834 -0.18785,-0.209021 -0.29078,-0.301625 v 0 c -0.0452,-0.04233 -0.0905,-0.08202 -0.13784,-0.121709 v 0 c -0.0873,-0.07408 -0.17728,-0.14552 -0.26988,-0.211666 v 0 c -0.082,-0.05821 -0.16378,-0.114036 -0.25135,-0.166423 v 0 c -0.0741,-0.04498 -0.15082,-0.09022 -0.23019,-0.129911 v 0 c -0.54769,-0.283104 -1.17237,-0.441854 -1.82827,-0.441854 v 0 z"
-         style="fill:#313131;fill-opacity:1;stroke:none;stroke-width:0.212564"
-         id="Gear-Shadow-object-Shape"
-         inkscape:label="Gear-Shadow-object-Shape">
-        <title
-           id="title1972">Gear Shadow object (Shape)</title>
-      </path>
-      <g
-         id="g1195"
-         transform="matrix(0.26458333,0,0,-0.26458333,35.889552,188.84979)"
-         style="stroke-width:0.803393">
-        <path
-           d="m 432.3496,215.3398 c -1.319,3.53 -2.77,6.99 -4.359,10.38 -0.21,0.471 -0.43,0.95 -0.661,1.42 -2.16,4.5 -1.33,9.85 2.1,13.471 l 17.68,18.599 c -0.48,11.06 -1.84,21.88 -4.01,32.41 v 0.03 l -27.89,27.89 c -5.75,5.75 -15.04,5.87 -20.94,0.26 l -9.39,-8.92 -13.889,-13.21 c -0.721,-0.69 -1.521,-1.27 -2.361,-1.75 -2.319,-1.31 -5,-1.8 -7.62,-1.41 -1.119,0.16 -2.22,0.48 -3.279,0.96 -3.871,1.77 -7.84,3.37 -11.891,4.8 -1.559,0.55 -2.96,1.4 -4.139,2.47 -0.39,0.36 -0.761,0.74 -1.101,1.15 v 0.01 c -0.27,0.32 -0.52,0.66 -0.76,1.01 -0.469,0.7 -0.859,1.46 -1.179,2.25 -0.29,0.73 -0.51,1.49 -0.651,2.28 -0.109,0.6 -0.17,1.22 -0.189,1.84 l -0.45,18.03 -0.331,13.09 c -0.04,1.52 -0.299,2.98 -0.759,4.35 -0.061,0.19 -0.13,0.37 -0.201,0.56 -0.269,0.73 -0.599,1.44 -0.99,2.11 -0.16,0.28 -0.33,0.56 -0.51,0.84 -0.36,0.54 -0.74,1.06 -1.169,1.54 v 0.01 c -0.35,0.4 -0.71,0.79 -1.1,1.14 -0.171,0.16 -0.341,0.31 -0.521,0.46 -0.33,0.28 -0.669,0.55 -1.02,0.8 -0.31,0.22 -0.619,0.43 -0.949,0.63 -0.281,0.17 -0.571,0.34 -0.87,0.49 -2.071,1.09 -4.42,1.69 -6.911,1.69 h -50.08 c -2.49,0 -4.839,-0.6 -6.91,-1.69 -0.3,-0.15 -0.59,-0.32 -0.87,-0.49 -0.33,-0.2 -0.64,-0.41 -0.949,-0.63 -0.351,-0.25 -0.691,-0.52 -1.021,-0.8 -0.179,-0.15 -0.349,-0.3 -0.52,-0.46 -0.39,-0.35 -0.75,-0.74 -1.1,-1.14 v -0.01 c -0.429,-0.48 -0.809,-1 -1.17,-1.54 -0.179,-0.28 -0.349,-0.56 -0.509,-0.84 -0.391,-0.67 -0.721,-1.38 -0.991,-2.11 -0.07,-0.19 -0.139,-0.37 -0.2,-0.56 -0.46,-1.37 -0.72,-2.83 -0.76,-4.35 l -0.809,-32.09 c -0.021,-0.62 -0.08,-1.23 -0.181,-1.83 -0.05,-0.26 -0.099,-0.52 -0.159,-0.77 -0.19,-0.76 -0.461,-1.49 -0.78,-2.18 -0.22,-0.47 -0.47,-0.92 -0.741,-1.36 -0.169,-0.27 -0.36,-0.53 -0.549,-0.79 -0.391,-0.51 -0.811,-0.98 -1.271,-1.43 -1.159,-1.1 -2.55,-1.99 -4.11,-2.57 -4.03,-1.5 -7.96,-3.18 -11.81,-5.03 -4.49,-2.16 -9.849,-1.33 -13.47,2.11 l -22.57,21.46 c -5.9,5.6 -15.189,5.48 -20.939,-0.27 l -35.421,-35.41 c -0.96,-0.97 -1.759,-2.02 -2.4,-3.15 -0.219,-0.38 -0.41,-0.76 -0.589,-1.15 -0.101,-0.22 -0.201,-0.44 -0.29,-0.67 -0.371,-0.88 -0.63,-1.79 -0.811,-2.72 -0.01,-0.02 -0.01,-0.04 -0.01,-0.06 -0.099,-0.47 -0.159,-0.94 -0.2,-1.42 -0.06,-0.63 -0.08,-1.26 -0.06,-1.89 -0.009,-0.14 0,-0.28 0.01,-0.42 -0.01,-0.04 0,-0.08 0,-0.12 0.21,-3.38 1.58,-6.7 4.091,-9.34 l 22.129,-23.28 c 3.38,-3.56 4.25,-8.8 2.21,-13.26 -0.25,-0.55 -0.51,-1.109 -0.739,-1.67 v -0.01 c -0.37,-0.84 -0.731,-1.679 -1.091,-2.52 -1.07,-2.52 -2.06,-5.09 -2.98,-7.69 -1.65,-4.7 -6.029,-7.889 -11.009,-8.02 l -31.121,-0.79 c -0.85,-0.02 -1.68,-0.11 -2.49,-0.27 h -0.01 c -2.75,-0.53 -5.24,-1.82 -7.21,-3.639 -0.29,-0.25 -0.57,-0.531 -0.83,-0.811 -0.15,-0.149 -0.28,-0.3 -0.41,-0.45 -0.13,-0.14 -0.25,-0.279 -0.349,-0.43 -0.341,-0.42 -0.661,-0.86 -0.96,-1.32 -0.401,-0.62 -0.75,-1.27 -1.051,-1.94 -0.3,-0.67 -0.56,-1.37 -0.76,-2.089 -0.099,-0.361 -0.189,-0.731 -0.26,-1.101 -0.19,-0.95 -0.29,-1.93 -0.29,-2.94 v -50.089 -0.021 c 0.01,-8.12 6.491,-14.769 14.62,-14.97 l 16.01,-0.4 h 0.01 l 16.07,-0.41 c 4.901,-0.13 9.22,-3.21 10.93,-7.8 1.5,-4.019 3.181,-7.96 5.03,-11.8 0.42,-0.88 0.731,-1.79 0.93,-2.719 0.641,-3.051 0.08,-6.25 -1.59,-8.901 -0.01,-0.01 -0.01,-0.019 -0.019,-0.03 -0.101,-0.16 -0.21,-0.319 -0.321,-0.48 -0.34,-0.469 -0.71,-0.92 -1.11,-1.339 l -21.159,-22.261 c 0,-0.01 0.009,-0.01 0.019,-0.01 28.551,-15.02 61.071,-23.51 95.571,-23.51 29.21,0 56.99,6.09 82.16,17.071 0.05,0.019 0.09,0.04 0.139,0.059 -8.49,-2.099 -17.399,-3.18 -26.559,-3.099 -11.061,0.089 -21.74,1.889 -31.78,5.139 -0.67,0.22 -1.34,0.441 -2,0.67 -0.661,0.231 -1.321,0.47 -1.981,0.71 -7.899,2.91 -15.359,6.72 -22.28,11.311 -1.719,1.149 -3.42,2.349 -5.07,3.589 -0.5,0.38 -1,0.76 -1.49,1.14 -0.74,0.58 -1.479,1.17 -2.21,1.76 -0.719,0.61 -1.429,1.21 -2.13,1.82 -1.469,1.27 -2.91,2.58 -4.299,3.93 -0.471,0.45 -0.931,0.9 -1.391,1.36 -0.6,0.6 -1.19,1.21 -1.779,1.821 -0.551,0.569 -1.08,1.149 -1.62,1.739 -1.201,1.31 -2.371,2.66 -3.511,4.03 -0.38,0.46 -0.75,0.92 -1.119,1.38 -0.661,0.82 -1.301,1.66 -1.941,2.5 -0.04,0.06 -0.08,0.12 -0.13,0.17 -0.469,0.64 -0.95,1.29 -1.41,1.94 -0.5,0.69 -0.979,1.39 -1.46,2.09 -0.479,0.71 -0.95,1.42 -1.409,2.13 -0.44,0.68 -0.871,1.36 -1.291,2.05 -0.029,0.04 -0.05,0.08 -0.069,0.11 -0.451,0.731 -0.89,1.46 -1.321,2.2 -0.85,1.48 -1.67,2.97 -2.46,4.491 -0.31,0.599 -0.62,1.199 -0.92,1.809 -0.16,0.33 -0.32,0.66 -0.48,0.99 -0.26,0.54 -0.52,1.09 -0.77,1.64 l -0.12,0.24 c -0.339,0.76 -0.679,1.52 -1.009,2.29 -0.341,0.79 -0.67,1.58 -0.991,2.37 v 0.02 c -0.319,0.8 -0.63,1.601 -0.929,2.4 -0.311,0.81 -0.601,1.62 -0.881,2.44 -0.279,0.82 -0.56,1.64 -0.82,2.46 -0.04,0.12 -0.08,0.24 -0.11,0.36 v 0.01 c -0.11,0.34 -0.22,0.681 -0.32,1.011 -0.1,0.339 -0.199,0.679 -0.3,1.019 -0.01,0.04 -0.02,0.08 -0.04,0.12 -0.239,0.83 -0.47,1.66 -0.689,2.491 -0.221,0.83 -0.431,1.669 -0.63,2.509 0,0.01 -0.011,0.02 -0.011,0.04 -0.13,0.55 -0.26,1.1 -0.38,1.65 -0.09,0.39 -0.17,0.79 -0.26,1.19 -0.699,3.33 -1.24,6.7 -1.62,10.13 -0.18,1.72 -0.329,3.45 -0.439,5.2 -0.111,1.85 -0.171,3.71 -0.191,5.59 -0.51,59.83 48.1,108.44 107.93,107.93 15.381,-0.13 30.02,-3.56 43.23,-9.6 19.241,-8.79 35.47,-23.139 46.61,-40.95 10.121,-16.16 16.051,-35.189 16.22,-55.51 0.02,-2.49 -0.04,-4.96 -0.2,-7.41 0.011,-0.05 0.011,-0.09 -0.009,-0.13 -0.041,-0.84 -0.101,-1.67 -0.181,-2.5 -0.069,-0.87 -0.15,-1.74 -0.25,-2.599 -0.08,-0.811 -0.18,-1.621 -0.289,-2.431 -0.03,-0.25 -0.061,-0.51 -0.101,-0.75 -0.08,-0.59 -0.17,-1.17 -0.26,-1.75 -0.04,-0.319 -0.089,-0.63 -0.149,-0.93 -0.101,-0.62 -0.201,-1.23 -0.32,-1.84 -0.151,-0.83 -0.311,-1.66 -0.481,-2.48 -1.279,-6.17 -3.09,-12.14 -5.389,-17.859 -0.25,-0.641 -0.511,-1.271 -0.781,-1.901 -0.34,-0.8 -0.689,-1.59 -1.04,-2.38 -0.36,-0.79 -0.719,-1.57 -1.09,-2.349 -0.009,-0.011 -0.02,-0.031 -0.02,-0.04 -0.379,-0.771 -0.76,-1.531 -1.149,-2.29 -0.39,-0.771 -0.791,-1.531 -1.21,-2.29 -0.411,-0.761 -0.831,-1.511 -1.26,-2.261 -0.42,-0.75 -0.861,-1.489 -1.311,-2.22 -1.32,-2.17 -2.71,-4.29 -4.179,-6.35 -0.04,-0.07 -0.09,-0.14 -0.141,-0.2 -0.239,-0.34 -0.48,-0.679 -0.73,-1.01 -0.24,-0.33 -0.479,-0.65 -0.719,-0.98 0.269,0.351 0.529,0.7 0.789,1.05 0.011,0 0.011,0.011 0.02,0.03 28.83,27.96 49.491,64.32 58.05,105.12 0,0.01 0.01,0.01 0,0.02 -4.75,0.25 -8.899,3.301 -10.58,7.78"
-           style="fill:#4f4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.803393"
-           id="Gear-object-Shape"
-           inkscape:label="Gear-object-Shape">
-          <title
-             id="title2012">Gear object (Shape)</title>
-        </path>
-      </g>
-    </g>
-    <g
-       id="Arrow_1-object-Group"
-       inkscape:label="Arrow 1-object-Group"
-       transform="matrix(1.2447326,0,0,1.244711,-11.113788,-16.7108)"
-       style="stroke-width:0.803393">
-      <title
-         id="title1865">Arrow 1 object (Group)</title>
-      <path
-         d="M 76.007529,86.855562 C 69.342674,91.551916 64.296806,98.036854 61.405175,105.61717 v 0 5.82083 h 5.728229 C 72.790195,98.875583 85.484903,90.57825 99.38082,90.57825 v 0 c 14.94605,0 27.91407,9.313068 33.02582,22.70945 v 0 l -6.09865,-0.0421 v 5.82084 l 10.43332,13.78002 10.68758,-13.63371 v -5.8211 l -7.97269,-0.055 C 136.20659,93.889245 119.32141,79.466014 99.38082,79.466014 v 0 c -8.424333,0 -16.507619,2.555611 -23.373291,7.389548"
-         style="fill:url(#linearGradient1223);stroke:none;stroke-width:0.212564"
-         id="Arrow-1-Shadow-object-Shape"
-         inkscape:label="Arrow-1-Shadow-object-Shape">
-        <title
-           id="title1930">Arrow 1 Shadow object (Shape)</title>
-      </path>
-      <path
-         d="m 139.45636,113.33657 c -3.24961,-19.447139 -20.13506,-33.8709 -40.075643,-33.8709 -8.424333,0 -16.507354,2.55614 -23.373292,7.389813 -6.664854,4.696354 -11.710458,11.181291 -14.602354,18.761607 H 67.1333 c 5.656792,-12.56242 18.3515,-20.859753 32.247417,-20.859753 17.031753,0 31.496533,12.092781 34.691903,28.541923 l -7.76446,-0.0537 10.43305,13.78003 10.6881,-13.63398 z"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.212564"
-         id="Arrow-1-object-Shape"
-         inkscape:label="Arrow-1-object-Shape">
-        <title
-           id="title1888">Arrow 1 object (Shape)</title>
-      </path>
-    </g>
-    <g
-       id="Arrow_2-object-Group"
-       inkscape:label="Arrow 2-object-Group"
-       transform="matrix(1.2447326,0,0,1.244711,-11.113788,-16.7108)"
-       style="stroke-width:0.803393">
-      <title
-         id="title2458">Arrow 2 object (Group)</title>
-      <path
-         d="m 51.400221,126.8685 v 5.82083 l 7.972689,0.055 c 3.249612,19.4474 20.135056,33.87116 40.075643,33.87116 v 0 c 8.424597,0 16.507357,-2.55588 23.373557,-7.38981 v 0 c 6.66459,-4.69662 11.71019,-11.18156 14.60209,-18.76187 v 0 l -5.3e-4,-5.81925 c 2.6e-4,-5.3e-4 2.6e-4,-0.001 5.3e-4,-0.002 v 0 h -5.3e-4 v -2.7e-4 h -5.72797 v 0.002 c -5.65705,12.56162 -18.35176,20.85843 -32.247147,20.85843 v 0 c -14.946047,0 -27.914335,-9.31281 -33.02582,-22.70946 v 0 l 6.098646,0.0423 v -5.8211 L 62.088064,113.23452 Z"
-         style="fill:url(#linearGradient1255);stroke:none;stroke-width:0.212564"
-         id="Arrow-2-Shadow-object-Shape"
-         inkscape:label="Arrow-2-Shadow-object-Shape">
-        <title
-           id="title1932">Arrow 2 Shadow object (Shape)</title>
-      </path>
-      <path
-         d="m 131.6961,134.64302 c -5.65679,12.56242 -18.3515,20.85975 -32.247416,20.85975 -17.031758,0 -31.496794,-12.09278 -34.692166,-28.54193 l 7.764726,0.0537 -10.433049,-13.78003 -10.687844,13.63398 7.972689,0.055 c 3.249613,19.4474 20.134792,33.8709 40.075644,33.8709 8.424336,0 16.507356,-2.55561 23.373296,-7.38982 6.66458,-4.69635 11.71045,-11.18129 14.60208,-18.7616 z"
-         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.212564"
-         id="Arrow-2-object-Shape"
-         inkscape:label="Arrow-2-object-Shape">
-        <title
-           id="title1890">Arrow 2 object (Shape)</title>
-      </path>
-    </g>
-  </g>
-  <metadata
-     id="metadata213">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:title>libvcs</dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-</svg>
diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html
deleted file mode 100644
index 19a94fe47..000000000
--- a/docs/_templates/layout.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% extends "!layout.html" %}
-{%- block extrahead %}
-  {{ super() }}
-  {%- if theme_show_meta_manifest_tag == true %}
-  <link rel="manifest" href="/manifest.json">
-  {% endif -%}
-  {%- if theme_show_meta_og_tags == true %}
-  <meta name="description" content="{{ theme_project_description }}">
-
-  <!-- Open Graph / Facebook -->
-  <meta property="og:type" content="website">
-  <meta property="og:url" content="{{ theme_project_url }}/">
-  <meta property="og:title" content="{{ theme_project_title }}">
-  <meta property="og:description" content="{{ theme_project_description }}">
-  <meta property="og:image" itemprop="image" content="{{ theme_project_url }}/_static/img/icons/icon-192x192.png">
-
-  <!-- Twitter -->
-  <meta property="twitter:card" content="summary_large_image">
-  <meta property="twitter:url" content="{{ theme_project_url }} ">
-  <meta property="twitter:title" content="{{ theme_project_title }}">
-  <meta property="twitter:description" content="{{ theme_project_description }}">
-  <meta property="twitter:image" content="{{ theme_project_url }}/_static/img/icons/icon-512x512.png">
-  {% endif -%}
-  {%- if theme_show_meta_app_icon_tags == true %}
-  <meta name="theme-color" content="#ffffff">
-  <meta name="application-name" content="{{ theme_project_name }}">
- 
-  <link rel="shortcut icon" href="/_static/favicon.ico">
-  <link rel="icon" type="image/png" sizes="512x512" href="/_static/img/icons/icon-512x512.png">
-  <link rel="icon" type="image/png" sizes="192x192" href="/_static/img/icons/icon-192x192.png">
-  <link rel="icon" type="image/png" sizes="32x32" href="/_static/img/icons/icon-32x32.png">
-  <link rel="icon" type="image/png" sizes="96x96" href="/_static/img/icons/icon-96x96.png">
-  <link rel="icon" type="image/png" sizes="16x16" href="/_static/img/icons/icon-16x16.png">
-  
-  <!-- Apple -->
-  <meta name="apple-mobile-web-app-title" content="libvcs">
-  
-  <link rel="apple-touch-icon" sizes="192x192" href="/_static/img/icons/icon-192x192.png">
-  <link rel="mask-icon" href="/_static/img/libvcs.svg" color="grey">
-
-  <!-- Microsoft -->
-  <meta name="msapplication-TileColor" content="#ffffff">
-  <meta name="msapplication-TileImage" content="/_static/img/icons/ms-icon-144x144.png">
-  {% endif -%}
-{% endblock %}
diff --git a/docs/_templates/sidebar/projects.html b/docs/_templates/sidebar/projects.html
deleted file mode 100644
index 330d15930..000000000
--- a/docs/_templates/sidebar/projects.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<div class="sidebar-tree projects" id="sidebar-projects">
-  <p class="caption" role="heading">
-    <span class="caption-text"
-      >team git-pull / <a href="https://www.git-pull.com/">Tony Narlock</a></span
-    >:
-  </p>
-
-  <p class="indented-block">
-    <span class="project-name">vcs-python</span>
-    <a class="internal" href="https://vcspull.git-pull.com" class="current">vcspull</a>
-    (<a class="internal" href="https://libvcs.git-pull.com">libvcs</a>),
-    <a class="internal" href="https://g.git-pull.com">g</a>
-  </p>
-  <p class="indented-block">
-    <span class="project-name">tmux-python</span>
-    <a class="internal" href="https://tmuxp.git-pull.com" class="current">tmuxp</a>
-    (<a class="internal" href="https://libtmux.git-pull.com">libtmux</a>)
-  </p>
-
-  <p class="indented-block">
-    <span class="project-name">cihai</span>
-    <span class="indent">
-      <a class="internal" href="https://unihan-etl.git-pull.com" class="current">unihan-etl</a>
-      (<a class="internal" href="https://unihan-db.git-pull.com">db</a>)
-    </span>
-    <span class="indent">
-      <a class="internal" href="https://cihai.git-pull.com" class="current">cihai</a>
-      (<a class="internal" href="https://cihai-cli.git-pull.com">cli</a>)
-    </span>
-  </p>
-</div>
-<script type="text/javascript">
-(() => {
-  const sidebar = document.getElementById("sidebar-projects")
-  sidebar.querySelectorAll(`a[href*="${window.location.hostname}"]`)
-    .forEach((link) => {
-      if (!link.classList.contains("active")) {
-        const d = document.createElement('span');
-        d.innerHTML = link.innerHTML;
-        d.classList.add("active");
-        link.parentNode.replaceChild(d, link);
-      }
-    });
-})()
-</script>
diff --git a/docs/cmd/git.md b/docs/cmd/git.md
index 978c2a098..a9eaeffdc 100644
--- a/docs/cmd/git.md
+++ b/docs/cmd/git.md
@@ -11,5 +11,4 @@ Compare to: [`fabtools.git`](https://fabtools.readthedocs.io/en/0.19.0/api/git.h
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: StrOrBytesPath, StrPath, run
 ```
diff --git a/docs/cmd/hg.md b/docs/cmd/hg.md
index da3346e76..0d13ad53f 100644
--- a/docs/cmd/hg.md
+++ b/docs/cmd/hg.md
@@ -7,5 +7,4 @@ For mercurial, aka `hg(1)`.
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: StrOrBytesPath, StrPath, run
 ```
diff --git a/docs/cmd/svn.md b/docs/cmd/svn.md
index 2cae80e01..3919935af 100644
--- a/docs/cmd/svn.md
+++ b/docs/cmd/svn.md
@@ -7,5 +7,4 @@ For subversion, aka `svn(1)`
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: StrOrBytesPath, StrPath, run
 ```
diff --git a/docs/conf.py b/docs/conf.py
index 2b553684f..bab0c89db 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -23,18 +23,10 @@
     "sphinx.ext.napoleon",  # Should go first
     "autoapi.extension",
     "sphinx.ext.autodoc",
-    "sphinx_autodoc_typehints",
-    "sphinx.ext.intersphinx",
     "sphinx.ext.todo",
-    "sphinx.ext.linkcode",
-    "sphinx_inline_tabs",
-    "sphinx_issues",
-    "sphinx_copybutton",
-    "sphinxext.opengraph",
-    "sphinxext.rediraffe",
+    "sphinx.ext.intersphinx",
     "myst_parser",
 ]
-myst_enable_extensions = ["colon_fence", "substitution", "replacements"]
 
 templates_path = ["_templates"]
 
@@ -50,50 +42,12 @@
 
 exclude_patterns = ["_build"]
 
-pygments_style = "monokai"
-pygments_dark_style = "monokai"
-
-html_css_files = ["css/custom.css"]
-html_static_path = ["_static"]
-html_extra_path = ["manifest.json"]
-html_favicon = "_static/favicon.ico"
-html_theme = "furo"
 html_theme_path: list = []
-html_theme_options: dict = {
-    "light_logo": "img/libvcs.svg",
-    "dark_logo": "img/libvcs-dark.svg",
-    "footer_icons": [
-        {
-            "name": "GitHub",
-            "url": about["__github__"],
-            "html": """
-                <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
-                    <path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
-                </svg>
-            """,
-            "class": "",
-        },
-    ],
-}
-html_sidebars = {
-    "**": [
-        "sidebar/scroll-start.html",
-        "sidebar/brand.html",
-        "sidebar/search.html",
-        "sidebar/navigation.html",
-        "sidebar/projects.html",
-        "sidebar/scroll-end.html",
-    ]
-}
 
 # sphinx.ext.autodoc
 autoclass_content = "both"
 autodoc_member_order = "bysource"
 
-# sphinx-autodoc-typehints
-autodoc_typehints = "description"  # show type hints in doc body instead of signature
-simplify_optional_unions = True
-
 # sphinx-autoapi
 autoapi_type = "python"
 autoapi_dirs = [project_root / "libvcs"]
@@ -103,133 +57,11 @@
 napoleon_google_docstring = True
 napoleon_include_init_with_doc = True
 
-# sphinxext.opengraph
-ogp_site_url = about["__docs__"]
-ogp_image = "_static/img/icons/icon-192x192.png"
-ogp_desscription_length = about["__description__"]
-ogp_site_name = about["__title__"]
-
-# sphinx-copybutton
-copybutton_prompt_text = (
-    r">>> |\.\.\. |> |\$ |\# | In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
-)
-copybutton_prompt_is_regexp = True
-copybutton_remove_prompts = True
-
 # sphinx-issues
 issues_github_path = "vcs-python/libvcs"
 
-# sphinxext-rediraffe
-rediraffe_redirects = "redirects.txt"
-rediraffe_branch = "master~1"
-
-htmlhelp_basename = "%sdoc" % about["__title__"]
-
-latex_documents = [
-    (
-        "index",
-        "{}.tex".format(about["__package_name__"]),
-        "{} Documentation".format(about["__title__"]),
-        about["__author__"],
-        "manual",
-    )
-]
-
-man_pages = [
-    (
-        "index",
-        about["__package_name__"],
-        "{} Documentation".format(about["__title__"]),
-        about["__author__"],
-        1,
-    )
-]
-
-texinfo_documents = [
-    (
-        "index",
-        "{}".format(about["__package_name__"]),
-        "{} Documentation".format(about["__title__"]),
-        about["__author__"],
-        about["__package_name__"],
-        about["__description__"],
-        "Miscellaneous",
-    )
-]
-
 intersphinx_mapping = {
     "py": ("https://docs.python.org/3", None),
     "pip": ("https://pip.pypa.io/en/latest/", None),
     "vcspull": ("https://vcspull.git-pull.com/", None),
 }
-
-
-def linkcode_resolve(domain, info):  # NOQA: C901
-    """
-    Determine the URL corresponding to Python object
-
-    Notes
-    -----
-    From https://github.com/numpy/numpy/blob/v1.15.1/doc/source/conf.py, 7c49cfa
-    on Jul 31. License BSD-3. https://github.com/numpy/numpy/blob/v1.15.1/LICENSE.txt
-    """
-    if domain != "py":
-        return None
-
-    modname = info["module"]
-    fullname = info["fullname"]
-
-    submod = sys.modules.get(modname)
-    if submod is None:
-        return None
-
-    obj = submod
-    for part in fullname.split("."):
-        try:
-            obj = getattr(obj, part)
-        except Exception:
-            return None
-
-    # strip decorators, which would resolve to the source of the decorator
-    # possibly an upstream bug in getsourcefile, bpo-1764286
-    try:
-        unwrap = inspect.unwrap
-    except AttributeError:
-        pass
-    else:
-        obj = unwrap(obj)
-
-    try:
-        fn = inspect.getsourcefile(obj)
-    except Exception:
-        fn = None
-    if not fn:
-        return None
-
-    try:
-        source, lineno = inspect.getsourcelines(obj)
-    except Exception:
-        lineno = None
-
-    if lineno:
-        linespec = "#L%d-L%d" % (lineno, lineno + len(source) - 1)
-    else:
-        linespec = ""
-
-    fn = relpath(fn, start=dirname(libvcs.__file__))
-
-    if "dev" in about["__version__"]:
-        return "{}/blob/master/{}/{}{}".format(
-            about["__github__"],
-            about["__package_name__"],
-            fn,
-            linespec,
-        )
-    else:
-        return "{}/blob/v{}/{}/{}{}".format(
-            about["__github__"],
-            about["__version__"],
-            about["__package_name__"],
-            fn,
-            linespec,
-        )
diff --git a/docs/contributing/index.md b/docs/contributing/index.md
deleted file mode 100644
index 0bf04d5ea..000000000
--- a/docs/contributing/index.md
+++ /dev/null
@@ -1,12 +0,0 @@
-(contributing)=
-
-(developing)=
-
-# Contributing
-
-As an open source project, libvcs accepts contributions through GitHub. Below you will find
-resources on the internals of the project.
-
-```{toctree}
-workflow
-```
diff --git a/docs/contributing/workflow.md b/docs/contributing/workflow.md
deleted file mode 100644
index 744ba8308..000000000
--- a/docs/contributing/workflow.md
+++ /dev/null
@@ -1,208 +0,0 @@
-(workflow)=
-
-# Workflow
-
-## Development environment
-
-[poetry] is a required package to develop.
-
-```console
-$ git clone https://github.com/vcs-python/libvcs.git
-```
-
-```console
-$ cd libvcs
-```
-
-```console
-$ poetry install -E "docs test coverage lint format"
-```
-
-Makefile commands prefixed with `watch_` will watch files and rerun.
-
-## Tests
-
-```console
-$ poetry run py.test
-```
-
-Helpers: `make test` Rerun tests on file change: `make watch_test` (requires [entr(1)])
-
-## Documentation
-
-Default preview server: http://localhost:8068
-
-[sphinx-autobuild] will automatically build the docs, watch for file changes and launch a server.
-
-From home directory: `make start_docs` From inside `docs/`: `make start`
-
-[sphinx-autobuild]: https://github.com/executablebooks/sphinx-autobuild
-
-### Manual documentation (the hard way)
-
-`cd docs/` and `make html` to build. `make serve` to start http server.
-
-Helpers: `make build_docs`, `make serve_docs`
-
-Rebuild docs on file change: `make watch_docs` (requires [entr(1)])
-
-Rebuild docs and run server via one terminal: `make dev_docs` (requires above, and a `make(1)` with
-`-J` support, e.g. GNU Make)
-
-## Formatting
-
-The project uses [black] and [isort] (one after the other). Configurations are in `pyproject.toml`
-and `setup.cfg`:
-
-- `make black isort`: Run `black` first, then `isort` to handle import nuances
-
-## Linting
-
-[flake8] and [mypy] run via CI in our GitHub Actions. See the configuration in `pyproject.toml` and
-`setup.cfg`.
-
-### flake8
-
-[flake8] provides fast, reliable, barebones styling and linting.
-
-````{tab} Command
-
-poetry:
-
-```console
-$ poetry run flake8
-```
-
-If you setup manually:
-
-```console
-$ flake8
-```
-
-````
-
-````{tab} make
-
-```console
-$ make flake8
-```
-
-````
-
-````{tab} Watch
-
-```console
-$ make watch_flake8
-```
-
-requires [`entr(1)`].
-
-````
-
-````{tab} Configuration
-
-See `[flake8]` in setup.cfg.
-
-```{literalinclude} ../../setup.cfg
-:language: ini
-:start-at: "[flake8]"
-:end-before: "[isort]"
-
-```
-
-````
-
-### mypy
-
-[mypy] is used for static type checking.
-
-````{tab} Command
-
-poetry:
-
-```console
-$ poetry run mypy .
-```
-
-If you setup manually:
-
-```console
-$ mypy .
-```
-
-````
-
-````{tab} make
-
-```console
-$ make mypy
-```
-
-````
-
-````{tab} Watch
-
-```console
-$ make watch_mypy
-```
-
-requires [`entr(1)`].
-````
-
-## Releasing
-
-Since this software used in production projects, we don't want to release breaking changes.
-
-Choose what the next version is. Assuming it's version 0.9.0, it could be:
-
-- 0.9.0post0: postrelease, if there was a packaging issue
-- 0.9.1: bugfix / security / tweak
-- 0.10.0: breaking changes, new features
-
-Let's assume we pick 0.9.1
-
-`CHANGES`: Assure any PRs merged since last release are mentioned. Give a thank you to the
-contributor. Set the header with the new version and the date. Leave the "current" header and
-_Insert changes/features/fixes for next release here_ at the top::
-
-    current
-    -------
-    - *Insert changes/features/fixes for next release here*
-
-    libvcs 0.9.1 (2020-10-12)
-    -------------------------
-    - :issue:`1`: Fix bug
-
-`libvcs/__init__.py` and `__about__.py` - Set version
-
-```console
-$ git commit -m 'Tag v0.9.1'
-```
-
-```console
-$ git tag v0.9.1
-```
-
-After `git push` and `git push --tags`, CI will automatically build and deploy to PyPI.
-
-### Releasing (manual)
-
-As of 0.10, [poetry] handles virtualenv creation, package requirements, versioning, building, and
-publishing. Therefore there is no setup.py or requirements files.
-
-Update `__version__` in `__about__.py` and `pyproject.toml`::
-
-    git commit -m 'build(libvcs): Tag v0.1.1'
-    git tag v0.1.1
-    git push
-    git push --tags
-    poetry build
-    poetry publish
-
-[poetry]: https://python-poetry.org/
-[entr(1)]: http://eradman.com/entrproject/
-[`entr(1)`]: http://eradman.com/entrproject/
-[black]: https://github.com/psf/black
-[isort]: https://pypi.org/project/isort/
-[flake8]: https://flake8.pycqa.org/
-[mypy]: http://mypy-lang.org/
diff --git a/docs/history.md b/docs/history.md
deleted file mode 120000
index 3e8bc8c0c..000000000
--- a/docs/history.md
+++ /dev/null
@@ -1 +0,0 @@
-../CHANGES
\ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
index 621e378d2..c2d19720f 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -8,8 +8,6 @@
 :maxdepth: 2
 :hidden:
 
-quickstart
-parse/index
 cmd/index
 projects/index
 ```
@@ -18,9 +16,7 @@ projects/index
 :caption: Project
 :hidden:
 
-contributing/index
 internals/index
-history
 GitHub <https://github.com/vcs-python/libvcs>
 
 ```
diff --git a/docs/internals/run.md b/docs/internals/run.md
index 5473d8bcd..d4c8bc58b 100644
--- a/docs/internals/run.md
+++ b/docs/internals/run.md
@@ -5,5 +5,4 @@
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: StrOrBytesPath, StrPath, logger
 ```
diff --git a/docs/internals/shortcuts.md b/docs/internals/shortcuts.md
index b30314da3..2ce1d934f 100644
--- a/docs/internals/shortcuts.md
+++ b/docs/internals/shortcuts.md
@@ -5,6 +5,4 @@
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: GitProject, MercurialProject, SubversionProject,
-     InvalidVCS, VCSLiteral, ProgressCallbackProtocol
 ```
diff --git a/docs/internals/subprocess.md b/docs/internals/subprocess.md
index 80a9d5f7f..646b0fd0a 100644
--- a/docs/internals/subprocess.md
+++ b/docs/internals/subprocess.md
@@ -3,12 +3,4 @@
 ```{eval-rst}
 .. autoapimodule:: libvcs._internal.subprocess
    :members:
-   :exclude-members:
-     StrOrBytesPath, F, args, bufsize,
-     executable, stdin, stdout, stderr, preexec_fn, cwd,
-     close_fds, shell, cmd, env, text, universal_newlines,
-     startupinfo, creationflags, restore_signals, start_new_session,
-     group, extra_groups, user, umask, pass_fds, encoding, errors,
-     SkipDefaultFieldsReprMixin
-
 ```
diff --git a/docs/manifest.json b/docs/manifest.json
deleted file mode 100644
index 7f34c012a..000000000
--- a/docs/manifest.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-  "name": "libvcs",
-  "short_name": "libvcs",
-  "description": "vcs abstraction layer",
-  "theme_color": "#2196f3",
-  "background_color": "#fff",
-  "display": "browser",
-  "Scope": "https://libvcs.git-pull.com/",
-  "start_url": "https://libvcs.git-pull.com/",
-  "icons": [
-    {
-      "src": "_static/img/icons/icon-72x72.png",
-      "sizes": "72x72",
-      "type": "image/png"
-    },
-    {
-      "src": "_static/img/icons/icon-96x96.png",
-      "sizes": "96x96",
-      "type": "image/png"
-    },
-    {
-      "src": "_static/img/icons/icon-128x128.png",
-      "sizes": "128x128",
-      "type": "image/png"
-    },
-    {
-      "src": "_static/img/icons/icon-144x144.png",
-      "sizes": "144x144",
-      "type": "image/png"
-    },
-    {
-      "src": "_static/img/icons/icon-152x152.png",
-      "sizes": "152x152",
-      "type": "image/png"
-    },
-    {
-      "src": "_static/img/icons/icon-192x192.png",
-      "sizes": "192x192",
-      "type": "image/png"
-    },
-    {
-      "src": "_static/img/icons/icon-384x384.png",
-      "sizes": "384x384",
-      "type": "image/png"
-    },
-    {
-      "src": "_static/img/icons/icon-512x512.png",
-      "sizes": "512x512",
-      "type": "image/png"
-    }
-  ],
-  "splash_pages": null
-}
diff --git a/docs/projects/base.md b/docs/projects/base.md
index aa4527843..adc2e8b49 100644
--- a/docs/projects/base.md
+++ b/docs/projects/base.md
@@ -8,5 +8,4 @@ Adding your own VCS / Extending libvcs can be done through subclassing `BaseProj
 .. autoapimodule:: libvcs.projects.base
    :members:
    :show-inheritance:
-   :exclude-members: run, CmdLoggingAdapter, mkdir_p, StrPath, logger
 ```
diff --git a/docs/projects/git.md b/docs/projects/git.md
index 0ce216c2f..7b97816da 100644
--- a/docs/projects/git.md
+++ b/docs/projects/git.md
@@ -12,5 +12,4 @@ Compare to:
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: BaseProject, StrOrBytesPath, StrPath
 ```
diff --git a/docs/projects/hg.md b/docs/projects/hg.md
index a7615e803..3c3464245 100644
--- a/docs/projects/hg.md
+++ b/docs/projects/hg.md
@@ -7,5 +7,4 @@ For mercurial, aka `hg(1)`.
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: BaseProject, StrOrBytesPath, StrPath
 ```
diff --git a/docs/projects/index.md b/docs/projects/index.md
index f45fa7ea2..19539af81 100644
--- a/docs/projects/index.md
+++ b/docs/projects/index.md
@@ -28,5 +28,4 @@ base
 ```{eval-rst}
 .. autoapimodule:: libvcs.projects.constants
    :members:
-   :exclude-members: GitProject, MercurialProject, SubversionProject
 ```
diff --git a/docs/projects/svn.md b/docs/projects/svn.md
index 1d37e8433..fd7c242d2 100644
--- a/docs/projects/svn.md
+++ b/docs/projects/svn.md
@@ -7,5 +7,4 @@ For subversion, aka `svn(1)`
    :members:
    :show-inheritance:
    :undoc-members:
-   :exclude-members: BaseProject, StrOrBytesPath, StrPath
 ```
diff --git a/docs/quickstart.md b/docs/quickstart.md
deleted file mode 100644
index e9508b34f..000000000
--- a/docs/quickstart.md
+++ /dev/null
@@ -1,41 +0,0 @@
-(quickstart)=
-
-# Quickstart
-
-## Installation
-
-For latest official version:
-
-```console
-$ pip install --user libvcs
-```
-
-Upgrading:
-
-```console
-$ pip install --user --upgrade libvcs
-```
-
-(developmental-releases)=
-
-### Developmental releases
-
-New versions of libvcs are published to PyPI as alpha, beta, or release candidates. In their
-versions you will see notification like `a1`, `b1`, and `rc1`, respectively. `1.10.0b4` would mean
-the 4th beta release of `1.10.0` before general availability.
-
-- [pip]\:
-
-  ```console
-  $ pip install --user --upgrade --pre libvcs
-  ```
-
-via trunk (can break easily):
-
-- [pip]\:
-
-  ```console
-  $ pip install --user -e git+https://github.com/vcs-python/libvcs.git#egg=libvcs
-  ```
-
-[pip]: https://pip.pypa.io/en/stable/
diff --git a/docs/redirects.txt b/docs/redirects.txt
deleted file mode 100644
index e023dc93f..000000000
--- a/docs/redirects.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-"api.md" "projects/index.md"
-"api/base.md" "projects/base.md"
-"api/git.md" "projects/git.md"
-"api/hg.md" "projects/hg.md"
-"api/svn.md" "projects/svn.md"
-"developing.md" "contributing/index.md"
-"contributing/internals.md" "contributing/internals/index.md"
-"contributing/internals/exc.md" "internals/exc.md"
-"contributing/internals/index.md" "internals/index.md"
-"contributing/internals/query_list.md" "internals/query_list.md"
-"contributing/internals/subprocess.md" "internals/subprocess.md"
-"contributing/internals/types.md" "internals/types.md"
diff --git a/libvcs/__init__.py b/libvcs/__init__.py
index 24a263a0b..8b1378917 100644
--- a/libvcs/__init__.py
+++ b/libvcs/__init__.py
@@ -1,18 +1 @@
-"""Project package for libvcs."""
-import logging
 
-from ._internal.run import CmdLoggingAdapter
-from .projects.base import BaseProject
-from .projects.git import GitProject
-from .projects.hg import MercurialProject
-from .projects.svn import SubversionProject
-
-__all__ = [
-    "GitProject",
-    "MercurialProject",
-    "SubversionProject",
-    "BaseProject",
-    "CmdLoggingAdapter",
-]
-
-logger = logging.getLogger(__name__)
diff --git a/libvcs/projects/hg.py b/libvcs/projects/hg.py
index 9ea6ee751..f524f2a91 100644
--- a/libvcs/projects/hg.py
+++ b/libvcs/projects/hg.py
@@ -16,6 +16,9 @@
 logger = logging.getLogger(__name__)
 
 
+__all__ = ["MercurialProject"]
+
+
 class MercurialProject(BaseProject):
     bin_name = "hg"
     schemes = ("hg", "hg+http", "hg+https", "hg+file")
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/tests/_internal/subprocess/conftest.py b/tests/_internal/subprocess/conftest.py
deleted file mode 100644
index fb301f7be..000000000
--- a/tests/_internal/subprocess/conftest.py
+++ /dev/null
@@ -1,8 +0,0 @@
-import pathlib
-
-import pytest
-
-
-@pytest.fixture(autouse=True)
-def cwd_default(monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path):
-    monkeypatch.chdir(tmp_path)
diff --git a/tests/_internal/subprocess/test_SubprocessCommand.py b/tests/_internal/subprocess/test_SubprocessCommand.py
deleted file mode 100644
index 493f67efa..000000000
--- a/tests/_internal/subprocess/test_SubprocessCommand.py
+++ /dev/null
@@ -1,139 +0,0 @@
-import pathlib
-import subprocess
-from typing import Any
-
-import pytest
-
-from libvcs._internal.subprocess import SubprocessCommand
-
-
-def idfn(val: Any) -> str:
-    if isinstance(val, list):
-        if len(val):
-            return str(val[0])
-        return "[]]"
-
-    return str(val)
-
-
-@pytest.mark.parametrize(
-    "args,kwargs,expected_result",
-    [
-        [["ls"], {}, SubprocessCommand("ls")],
-        [[["ls", "-l"]], {}, SubprocessCommand(["ls", "-l"])],
-        [[], {"args": ["ls", "-l"]}, SubprocessCommand(["ls", "-l"])],
-        [["ls -l"], {"shell": True}, SubprocessCommand("ls -l", shell=True)],
-        [[], {"args": "ls -l", "shell": True}, SubprocessCommand("ls -l", shell=True)],
-        [
-            [],
-            {"args": ["ls", "-l"], "shell": True},
-            SubprocessCommand(["ls", "-l"], shell=True),
-        ],
-    ],
-    ids=idfn,
-)
-def test_init(args: list, kwargs: dict, expected_result: Any):
-    """Test SubprocessCommand via list + kwargs, assert attributes"""
-    cmd = SubprocessCommand(*args, **kwargs)
-    assert cmd == expected_result
-
-    # Attributes in cmd should match what's passed in
-    for k, v in kwargs.items():
-        assert getattr(cmd, k) == v
-
-    proc = cmd.Popen()
-    proc.communicate()
-    assert proc.returncode == 0
-
-
-FIXTURES = [
-    [["ls"], {}, SubprocessCommand("ls")],
-    [[["ls", "-l"]], {}, SubprocessCommand(["ls", "-l"])],
-]
-
-
-@pytest.mark.parametrize(
-    "args,kwargs,expected_result",
-    FIXTURES,
-    ids=idfn,
-)
-def test_init_and_Popen(args: list, kwargs: dict, expected_result: Any):
-    """Test SubprocessCommand with Popen"""
-    cmd = SubprocessCommand(*args, **kwargs)
-    assert cmd == expected_result
-
-    cmd_proc = cmd.Popen()
-    cmd_proc.communicate()
-    assert cmd_proc.returncode == 0
-
-    proc = subprocess.Popen(*args, **kwargs)
-    proc.communicate()
-    assert proc.returncode == 0
-
-
-@pytest.mark.parametrize(
-    "args,kwargs,expected_result",
-    FIXTURES,
-    ids=idfn,
-)
-def test_init_and_Popen_run(args: list, kwargs: dict, expected_result: Any):
-    """Test SubprocessCommand with run"""
-    cmd = SubprocessCommand(*args, **kwargs)
-    assert cmd == expected_result
-
-    cmd_proc = cmd.Popen()
-    cmd_proc.communicate()
-    assert cmd_proc.returncode == 0
-
-    proc = subprocess.run(*args, **kwargs)
-    assert proc.returncode == 0
-
-
-@pytest.mark.parametrize(
-    "args,kwargs,expected_result",
-    FIXTURES,
-    ids=idfn,
-)
-def test_init_and_check_call(args: list, kwargs: dict, expected_result: Any):
-    """Test SubprocessCommand with Popen.check_call"""
-    cmd = SubprocessCommand(*args, **kwargs)
-    assert cmd == expected_result
-
-    return_code = cmd.check_call()
-    assert return_code == 0
-
-    proc = subprocess.check_call(*args, **kwargs)
-    assert proc == return_code
-
-
-@pytest.mark.parametrize(
-    "args,kwargs,expected_result",
-    FIXTURES,
-)
-def test_init_and_check_output(args: list, kwargs: dict, expected_result: Any):
-    """Test SubprocessCommand with Popen.check_output"""
-    cmd = SubprocessCommand(*args, **kwargs)
-    assert cmd == expected_result
-
-    return_output = cmd.check_output()
-    assert isinstance(return_output, bytes)
-
-    proc = subprocess.check_output(*args, **kwargs)
-    assert proc == return_output
-
-
-@pytest.mark.parametrize(
-    "args,kwargs,run_kwargs",
-    [
-        [["ls"], {}, {}],
-        [[["ls", "-l"]], {}, {}],
-        [[["ls", "-al"]], {}, {"stdout": subprocess.DEVNULL}],
-    ],
-    ids=idfn,
-)
-def test_run(tmp_path: pathlib.Path, args: list, kwargs: dict, run_kwargs: dict):
-    kwargs["cwd"] = tmp_path
-    cmd = SubprocessCommand(*args, **kwargs)
-    response = cmd.run(**run_kwargs)
-
-    assert response.returncode == 0
diff --git a/tests/_internal/test_query_list.py b/tests/_internal/test_query_list.py
deleted file mode 100644
index 3af208fd9..000000000
--- a/tests/_internal/test_query_list.py
+++ /dev/null
@@ -1,240 +0,0 @@
-from typing import Optional
-
-import pytest
-
-from libvcs._internal.query_list import QueryList
-
-
-@pytest.mark.parametrize(
-    "items,filter_expr,expected_result",
-    [
-        [[{"test": 1}], None, [{"test": 1}]],
-        [[{"test": 1}], None, QueryList([{"test": 1}])],
-        [[{"fruit": "apple"}], None, QueryList([{"fruit": "apple"}])],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            None,
-            QueryList([{"fruit": "apple", "banana": object()}]),
-        ],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            dict(fruit__eq="apple"),
-            QueryList([{"fruit": "apple", "banana": object()}]),
-        ],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            dict(fruit__eq="notmatch"),
-            QueryList([]),
-        ],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            dict(fruit__exact="apple"),
-            QueryList([{"fruit": "apple", "banana": object()}]),
-        ],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            dict(fruit__exact="notmatch"),
-            QueryList([]),
-        ],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            dict(fruit__iexact="Apple"),
-            QueryList([{"fruit": "apple", "banana": object()}]),
-        ],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            dict(fruit__iexact="Notmatch"),
-            QueryList([]),
-        ],
-        [
-            [{"fruit": "apple", "banana": object()}],
-            dict(fruit="notmatch"),
-            QueryList([]),
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit="apple"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__in="app"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__icontains="App"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__contains="app"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__regex=r"app.*"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__iregex=r"App.*"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__startswith="a"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__istartswith="AP"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__startswith="z"),
-            [],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__endswith="le"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__iendswith="LE"),
-            [{"fruit": "apple"}],
-        ],
-        [
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-            dict(fruit__endswith="z"),
-            [],
-        ],
-        [
-            [
-                {"fruit": "apple"},
-                {"fruit": "mango"},
-                {"fruit": "banana"},
-                {"fruit": "kiwi"},
-            ],
-            dict(fruit__in=["apple", "mango"]),
-            [{"fruit": "apple"}, {"fruit": "mango"}],
-        ],
-        [
-            [
-                {"fruit": "apple"},
-                {"fruit": "mango"},
-                {"fruit": "banana"},
-                {"fruit": "kiwi"},
-            ],
-            dict(fruit__nin=["apple", "mango"]),
-            [{"fruit": "banana"}, {"fruit": "kiwi"}],
-        ],
-        [
-            [
-                {"place": "book store", "city": "Tampa", "state": "Florida"},
-                {"place": "coffee shop", "city": "Tampa", "state": "Florida"},
-                {
-                    "place": "chinese restaurant",
-                    "city": "ybor city",
-                    "state": "Florida",
-                },
-                {
-                    "place": "walt disney world",
-                    "city": "Lake Buena Vista",
-                    "state": "Florida",
-                },
-            ],
-            dict(city="Tampa", state="Florida"),
-            [
-                {"place": "book store", "city": "Tampa", "state": "Florida"},
-                {"place": "coffee shop", "city": "Tampa", "state": "Florida"},
-            ],
-        ],
-        [
-            [
-                {"place": "book store", "city": "Tampa", "state": "Florida"},
-                {"place": "coffee shop", "city": "Tampa", "state": "Florida"},
-                {
-                    "place": "chinese restaurant",
-                    "city": "ybor city",
-                    "state": "Florida",
-                },
-                {
-                    "place": "walt disney world",
-                    "city": "Lake Buena Vista",
-                    "state": "Florida",
-                },
-            ],
-            dict(place__contains="coffee", state="Florida"),
-            [
-                {"place": "coffee shop", "city": "Tampa", "state": "Florida"},
-            ],
-        ],
-        [
-            [
-                {
-                    "place": "Largo",
-                    "city": "Tampa",
-                    "state": "Florida",
-                    "foods": {"fruit": ["banana", "orange"], "breakfast": "cereal"},
-                },
-                {
-                    "place": "Chicago suburbs",
-                    "city": "Elmhurst",
-                    "state": "Illinois",
-                    "foods": {"fruit": ["apple", "cantelope"], "breakfast": "waffles"},
-                },
-            ],
-            dict(foods__fruit__contains="banana"),
-            [
-                {
-                    "place": "Largo",
-                    "city": "Tampa",
-                    "state": "Florida",
-                    "foods": {"fruit": ["banana", "orange"], "breakfast": "cereal"},
-                },
-            ],
-        ],
-        [
-            [
-                {
-                    "place": "Largo",
-                    "city": "Tampa",
-                    "state": "Florida",
-                    "foods": {"fruit": ["banana", "orange"], "breakfast": "cereal"},
-                },
-                {
-                    "place": "Chicago suburbs",
-                    "city": "Elmhurst",
-                    "state": "Illinois",
-                    "foods": {"fruit": ["apple", "cantelope"], "breakfast": "waffles"},
-                },
-            ],
-            dict(foods__breakfast="cereal"),
-            [
-                {
-                    "place": "Largo",
-                    "city": "Tampa",
-                    "state": "Florida",
-                    "foods": {"fruit": ["banana", "orange"], "breakfast": "cereal"},
-                },
-            ],
-        ],
-        [[1, 2, 3, 4, 5], None, QueryList([1, 2, 3, 4, 5])],
-        [[1, 2, 3, 4, 5], [1], QueryList([1])],
-        [[1, 2, 3, 4, 5], [1, 4], QueryList([1, 4])],
-        [[1, 2, 3, 4, 5], lambda val: 1 == val, QueryList([1])],
-        [[1, 2, 3, 4, 5], lambda val: 2 == val, QueryList([2])],
-    ],
-)
-def test_filter(items: list, filter_expr: Optional[dict], expected_result: list):
-    qs = QueryList(items)
-    if filter_expr is not None:
-        if isinstance(filter_expr, dict):
-            assert qs.filter(**filter_expr) == expected_result
-        else:
-            assert qs.filter(filter_expr) == expected_result
-    else:
-        assert qs.filter() == expected_result
diff --git a/tests/cmd/__init__.py b/tests/cmd/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/tests/cmd/test_core.py b/tests/cmd/test_core.py
deleted file mode 100644
index 5664a9f7a..000000000
--- a/tests/cmd/test_core.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import pathlib
-
-import pytest
-
-from libvcs._internal.run import mkdir_p, which
-
-
-def test_mkdir_p(tmp_path: pathlib.Path):
-    path = tmp_path / "file"
-    path.touch()
-
-    with pytest.raises(Exception) as excinfo:
-        mkdir_p(path)
-    excinfo.match(r"Could not create directory %s" % path)
-
-    # already exists is a noop
-    mkdir_p(tmp_path)
-
-
-def test_which_no_hg_found(monkeypatch):
-    monkeypatch.setenv("PATH", "/")
-    which("hg")
-    which("hg", "/")
diff --git a/tests/cmd/test_git.py b/tests/cmd/test_git.py
deleted file mode 100644
index 5eb271399..000000000
--- a/tests/cmd/test_git.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import pathlib
-from typing import Callable
-
-import pytest
-
-from libvcs.cmd import git
-
-
-@pytest.mark.parametrize("dir_type", [str, pathlib.Path])
-def test_run(dir_type: Callable, tmp_path: pathlib.Path):
-    repo = git.Git(dir=dir_type(tmp_path))
-
-    assert repo.dir == tmp_path
diff --git a/tests/conftest.py b/tests/conftest.py
deleted file mode 100644
index 47abacbc3..000000000
--- a/tests/conftest.py
+++ /dev/null
@@ -1 +0,0 @@
-from libvcs.conftest import *  # noqa F40
diff --git a/tests/projects/test_base.py b/tests/projects/test_base.py
deleted file mode 100644
index 957f28d96..000000000
--- a/tests/projects/test_base.py
+++ /dev/null
@@ -1,68 +0,0 @@
-"""tests for libvcs repo abstract base class."""
-import pathlib
-import sys
-
-import pytest
-
-from libvcs._internal.shortcuts import create_project
-from libvcs.projects.base import BaseProject, convert_pip_url
-
-
-def test_repr():
-    repo = create_project(url="file://path/to/myrepo", dir="/hello/", vcs="git")
-
-    str_repo = str(repo)
-    assert "GitProject" in str_repo
-    assert "hello" in str_repo
-    assert "<GitProject hello>" == str_repo
-
-
-def test_repr_base():
-    repo = BaseProject(url="file://path/to/myrepo", dir="/hello/")
-
-    str_repo = str(repo)
-    assert "Project" in str_repo
-    assert "hello" in str_repo
-    assert "<BaseProject hello>" == str_repo
-
-
-def test_ensure_dir_creates_parent_if_not_exist(tmp_path: pathlib.Path):
-    projects_path = tmp_path / "projects_path"  # doesn't exist yet
-    dir = projects_path / "myrepo"
-    repo = BaseProject(url="file://path/to/myrepo", dir=dir)
-
-    repo.ensure_dir()
-    assert projects_path.is_dir()
-
-
-def test_convert_pip_url():
-    url, rev = convert_pip_url(pip_url="git+file://path/to/myrepo@therev")
-
-    assert url, rev == "therev"
-    assert url, rev == "file://path/to/myrepo"
-
-
-def test_progress_callback(
-    capsys: pytest.CaptureFixture[str],
-    tmp_path: pathlib.Path,
-    git_remote_repo: pathlib.Path,
-):
-    def progress_cb(output, timestamp):
-        sys.stdout.write(output)
-        sys.stdout.flush()
-
-    class Project(BaseProject):
-        bin_name = "git"
-
-        def obtain(self, *args, **kwargs):
-            self.ensure_dir()
-            self.run(["clone", "--progress", self.url, self.dir], log_in_real_time=True)
-
-    r = Project(
-        url=f"file://{str(git_remote_repo)}",
-        dir=str(tmp_path),
-        progress_callback=progress_cb,
-    )
-    r.obtain()
-    captured = capsys.readouterr()
-    assert "Cloning into" in captured.out
diff --git a/tests/projects/test_conftest.py b/tests/projects/test_conftest.py
deleted file mode 100644
index 38a495991..000000000
--- a/tests/projects/test_conftest.py
+++ /dev/null
@@ -1,30 +0,0 @@
-import pathlib
-
-import pytest
-
-from libvcs._internal.run import which
-from libvcs.conftest import CreateProjectCallbackFixtureProtocol
-
-
-@pytest.mark.skipif(not which("git"), reason="git is not available")
-def test_create_git_remote_repo(
-    create_git_remote_repo: CreateProjectCallbackFixtureProtocol,
-    tmp_path: pathlib.Path,
-    projects_path: pathlib.Path,
-):
-    git_remote_1 = create_git_remote_repo()
-    git_remote_2 = create_git_remote_repo()
-
-    assert git_remote_1 != git_remote_2
-
-
-@pytest.mark.skipif(not which("svn"), reason="svn is not available")
-def test_create_svn_remote_repo(
-    create_svn_remote_repo: CreateProjectCallbackFixtureProtocol,
-    tmp_path: pathlib.Path,
-    projects_path: pathlib.Path,
-):
-    svn_remote_1 = create_svn_remote_repo()
-    svn_remote_2 = create_svn_remote_repo()
-
-    assert svn_remote_1 != svn_remote_2
diff --git a/tests/projects/test_git.py b/tests/projects/test_git.py
deleted file mode 100644
index 9d598257e..000000000
--- a/tests/projects/test_git.py
+++ /dev/null
@@ -1,777 +0,0 @@
-"""Tests for libvcs git repos."""
-import datetime
-import os
-import pathlib
-import textwrap
-from typing import Callable
-
-import pytest
-
-from pytest_mock import MockerFixture
-
-from libvcs import exc
-from libvcs._internal.run import run, which
-from libvcs._internal.shortcuts import create_project
-from libvcs.conftest import CreateProjectCallbackFixtureProtocol
-from libvcs.projects.git import (
-    GitFullRemoteDict,
-    GitProject,
-    GitRemote,
-    GitStatus,
-    convert_pip_url as git_convert_pip_url,
-)
-
-if not which("git"):
-    pytestmark = pytest.mark.skip(reason="git is not available")
-
-
-ProjectTestFactory = Callable[..., GitProject]
-ProjectTestFactoryLazyKwargs = Callable[..., dict]
-ProjectTestFactoryRemotesLazyExpected = Callable[..., GitFullRemoteDict]
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options",
-    [
-        [
-            GitProject,
-            lambda bare_dir, tmp_path, **kwargs: {
-                "url": f"file://{bare_dir}",
-                "dir": tmp_path / "obtaining a bare repo",
-                "vcs": "git",
-            },
-        ],
-        [
-            create_project,
-            lambda bare_dir, tmp_path, **kwargs: {
-                "url": f"git+file://{bare_dir}",
-                "dir": tmp_path / "obtaining a bare repo",
-                "vcs": "git",
-            },
-        ],
-    ],
-)
-def test_repo_git_obtain_initial_commit_repo(
-    tmp_path: pathlib.Path,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-):
-    """initial commit repos return 'initial'.
-
-    note: this behaviors differently from git(1)'s use of the word "bare".
-    running `git rev-parse --is-bare-repository` would return false.
-    """
-    repo_name = "my_git_project"
-
-    run(["git", "init", repo_name], cwd=tmp_path)
-
-    bare_dir = tmp_path / repo_name
-    git_repo: GitProject = constructor(**lazy_constructor_options(**locals()))
-
-    git_repo.obtain()
-    assert git_repo.get_revision() == "initial"
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options",
-    [
-        [
-            GitProject,
-            lambda git_remote_repo, tmp_path, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": tmp_path / "myrepo",
-                "vcs": "git",
-            },
-        ],
-        [
-            create_project,
-            lambda git_remote_repo, tmp_path, **kwargs: {
-                "url": f"git+file://{git_remote_repo}",
-                "dir": tmp_path / "myrepo",
-                "vcs": "git",
-            },
-        ],
-    ],
-)
-def test_repo_git_obtain_full(
-    tmp_path: pathlib.Path,
-    git_remote_repo,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-):
-    git_repo: GitProject = constructor(**lazy_constructor_options(**locals()))
-    git_repo.obtain()
-
-    test_repo_revision = run(["git", "rev-parse", "HEAD"], cwd=git_remote_repo)
-
-    assert git_repo.get_revision() == test_repo_revision
-    assert os.path.exists(tmp_path / "myrepo")
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options",
-    [
-        [
-            GitProject,
-            lambda git_remote_repo, tmp_path, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": tmp_path / "myrepo",
-                "vcs": "git",
-            },
-        ],
-        [
-            create_project,
-            lambda git_remote_repo, tmp_path, **kwargs: {
-                "url": f"git+file://{git_remote_repo}",
-                "dir": tmp_path / "myrepo",
-                "vcs": "git",
-            },
-        ],
-    ],
-)
-def test_repo_update_handle_cases(
-    tmp_path: pathlib.Path,
-    git_remote_repo: pathlib.Path,
-    mocker: MockerFixture,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-):
-    git_repo: GitProject = constructor(**lazy_constructor_options(**locals()))
-    git_repo.obtain()  # clone initial repo
-    mocka = mocker.spy(git_repo, "run")
-    git_repo.update_repo()
-
-    mocka.assert_any_call(["symbolic-ref", "--short", "HEAD"])
-
-    mocka.reset_mock()
-
-    # will only look up symbolic-ref if no rev specified for object
-    git_repo.rev = "HEAD"
-    git_repo.update_repo()
-    assert mocker.call(["symbolic-ref", "--short", "HEAD"]) not in mocka.mock_calls
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options",
-    [
-        [
-            GitProject,
-            lambda git_remote_repo, tmp_path, progress_callback, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": tmp_path / "myrepo",
-                "progress_callback": progress_callback,
-                "vcs": "git",
-            },
-        ],
-        [
-            create_project,
-            lambda git_remote_repo, tmp_path, progress_callback, **kwargs: {
-                "url": f"git+file://{git_remote_repo}",
-                "dir": tmp_path / "myrepo",
-                "progress_callback": progress_callback,
-                "vcs": "git",
-            },
-        ],
-    ],
-)
-def test_progress_callback(
-    tmp_path: pathlib.Path,
-    git_remote_repo: pathlib.Path,
-    mocker: MockerFixture,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-):
-    def progress_callback_spy(output, timestamp):
-        assert isinstance(output, str)
-        assert isinstance(timestamp, datetime.datetime)
-
-    progress_callback = mocker.Mock(
-        name="progress_callback_stub", side_effect=progress_callback_spy
-    )
-
-    run(["git", "rev-parse", "HEAD"], cwd=git_remote_repo)
-
-    # create a new repo with the repo as a remote
-    git_repo: GitProject = constructor(**lazy_constructor_options(**locals()))
-    git_repo.obtain()
-
-    assert progress_callback.called
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options,lazy_remote_expected",
-    [
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-            },
-            lambda git_remote_repo, **kwargs: {"origin": f"file://{git_remote_repo}"},
-        ],
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "remotes": {"origin": f"file://{git_remote_repo}"},
-            },
-            lambda git_remote_repo, **kwargs: {"origin": f"file://{git_remote_repo}"},
-        ],
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "remotes": {
-                    "origin": f"file://{git_remote_repo}",
-                    "second_remote": f"file://{git_remote_repo}",
-                },
-            },
-            lambda git_remote_repo, **kwargs: {
-                "origin": f"file://{git_remote_repo}",
-                "second_remote": f"file://{git_remote_repo}",
-            },
-        ],
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "remotes": {
-                    "second_remote": f"file://{git_remote_repo}",
-                },
-            },
-            lambda git_remote_repo, **kwargs: {
-                "origin": f"file://{git_remote_repo}",
-                "second_remote": f"file://{git_remote_repo}",
-            },
-        ],
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "remotes": {
-                    "origin": GitRemote(
-                        name="origin",
-                        fetch_url=f"file://{git_remote_repo}",
-                        push_url=f"file://{git_remote_repo}",
-                    ),
-                    "second_remote": GitRemote(
-                        name="second_remote",
-                        fetch_url=f"file://{git_remote_repo}",
-                        push_url=f"file://{git_remote_repo}",
-                    ),
-                },
-            },
-            lambda git_remote_repo, **kwargs: {
-                "origin": f"file://{git_remote_repo}",
-                "second_remote": f"file://{git_remote_repo}",
-            },
-        ],
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "vcs": "git",
-                "remotes": {
-                    "second_remote": GitRemote(
-                        name="second_remote",
-                        fetch_url=f"file://{git_remote_repo}",
-                        push_url=f"file://{git_remote_repo}",
-                    ),
-                },
-            },
-            lambda git_remote_repo, **kwargs: {
-                "second_remote": f"file://{git_remote_repo}",
-            },
-        ],
-        [
-            create_project,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"git+file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "vcs": "git",
-            },
-            lambda git_remote_repo, **kwargs: {"origin": f"file://{git_remote_repo}"},
-        ],
-    ],
-)
-def test_remotes(
-    projects_path: pathlib.Path,
-    git_remote_repo: pathlib.Path,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-    lazy_remote_expected: ProjectTestFactoryRemotesLazyExpected,
-):
-    repo_name = "myrepo"
-    remote_name = "myremote"
-    remote_url = "https://localhost/my/git/repo.git"
-
-    git_repo: GitProject = constructor(**lazy_constructor_options(**locals()))
-    git_repo.obtain()
-
-    expected = lazy_remote_expected(**locals())
-    assert len(expected.keys()) > 0
-    for expected_remote_name, expected_remote_url in expected.items():
-        remote = git_repo.remote(expected_remote_name)
-        assert remote is not None
-
-        if remote is not None:
-            assert (
-                expected_remote_name,
-                expected_remote_url,
-                expected_remote_url,
-            ) == remote.to_tuple()
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options,lazy_remote_dict,lazy_remote_expected",
-    [
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "remotes": {
-                    "origin": f"file://{git_remote_repo}",
-                },
-            },
-            lambda git_remote_repo, **kwargs: {
-                "second_remote": GitRemote(
-                    **{
-                        "name": "second_remote",
-                        "fetch_url": f"file://{git_remote_repo}",
-                        "push_url": f"file://{git_remote_repo}",
-                    }
-                )
-            },
-            lambda git_remote_repo, **kwargs: {
-                "origin": GitRemote(
-                    name="origin",
-                    push_url=f"file://{git_remote_repo}",
-                    fetch_url=f"file://{git_remote_repo}",
-                ),
-                "second_remote": GitRemote(
-                    name="second_remote",
-                    push_url=f"file://{git_remote_repo}",
-                    fetch_url=f"file://{git_remote_repo}",
-                ),
-            },
-        ],
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "remotes": {
-                    "origin": f"file://{git_remote_repo}",
-                    # accepts short-hand form since it's inputted in the constructor
-                    "second_remote": f"file://{git_remote_repo}",
-                },
-            },
-            lambda git_remote_repo, **kwargs: {},
-            lambda git_remote_repo, **kwargs: {
-                "origin": GitRemote(
-                    name="origin",
-                    push_url=f"file://{git_remote_repo}",
-                    fetch_url=f"file://{git_remote_repo}",
-                ),
-                "second_remote": GitRemote(
-                    name="second_remote",
-                    push_url=f"file://{git_remote_repo}",
-                    fetch_url=f"file://{git_remote_repo}",
-                ),
-            },
-        ],
-        [
-            GitProject,
-            lambda git_remote_repo, projects_path, repo_name, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": projects_path / repo_name,
-                "remotes": {
-                    "origin": f"file://{git_remote_repo}",
-                },
-            },
-            lambda git_remote_repo, second_git_remote_repo, **kwargs: {
-                "origin": GitRemote(
-                    **{
-                        "name": "second_remote",
-                        "fetch_url": f"{second_git_remote_repo!s}",
-                        "push_url": f"{second_git_remote_repo!s}",
-                    }
-                )
-            },
-            lambda git_remote_repo, second_git_remote_repo, **kwargs: {
-                "origin": GitRemote(
-                    name="origin",
-                    fetch_url=f"{second_git_remote_repo!s}",
-                    push_url=f"{second_git_remote_repo!s}",
-                ),
-            },
-        ],
-    ],
-)
-def test_remotes_update_repo(
-    projects_path: pathlib.Path,
-    git_remote_repo: pathlib.Path,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-    lazy_remote_dict: ProjectTestFactoryRemotesLazyExpected,
-    lazy_remote_expected: ProjectTestFactoryRemotesLazyExpected,
-    create_git_remote_repo: CreateProjectCallbackFixtureProtocol,
-):
-    repo_name = "myrepo"
-    remote_name = "myremote"
-    remote_url = "https://localhost/my/git/repo.git"
-
-    second_git_remote_repo = create_git_remote_repo()
-
-    git_repo: GitProject = constructor(**lazy_constructor_options(**locals()))
-    git_repo.obtain()
-
-    git_repo._remotes |= {
-        k: GitRemote(*v) if isinstance(v, dict) else v
-        for k, v in lazy_remote_dict(**locals()).items()
-    }
-    git_repo.update_repo(set_remotes=True)
-
-    expected = lazy_remote_expected(**locals())
-    assert len(expected.keys()) > 0
-    for expected_remote_name, expected_remote_url in expected.items():
-        assert expected_remote_url == git_repo.remote(expected_remote_name)
-
-
-def test_git_get_url_and_rev_from_pip_url():
-    pip_url = "git+ssh://git@bitbucket.example.com:7999/PROJ/repo.git"
-
-    url, rev = git_convert_pip_url(pip_url)
-    assert "ssh://git@bitbucket.example.com:7999/PROJ/repo.git" == url
-    assert rev is None
-
-    pip_url = "{}@{}".format(
-        "git+ssh://git@bitbucket.example.com:7999/PROJ/repo.git",
-        "eucalyptus",
-    )
-    url, rev = git_convert_pip_url(pip_url)
-    assert "ssh://git@bitbucket.example.com:7999/PROJ/repo.git" == url
-    assert rev == "eucalyptus"
-
-    # the git manual refers to this as "scp-like syntax"
-    # https://git-scm.com/docs/git-clone
-    pip_url = "{}@{}".format("git+user@hostname:user/repo.git", "eucalyptus")
-    url, rev = git_convert_pip_url(pip_url)
-    assert "user@hostname:user/repo.git" == url
-    assert rev == "eucalyptus"
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options",
-    [
-        [
-            GitProject,
-            lambda git_remote_repo, dir, **kwargs: {
-                "url": f"file://{git_remote_repo}",
-                "dir": str(dir),
-                "vcs": "git",
-            },
-        ],
-        [
-            create_project,
-            lambda git_remote_repo, dir, **kwargs: {
-                "url": f"git+file://{git_remote_repo}",
-                "dir": dir,
-                "vcs": "git",
-            },
-        ],
-    ],
-)
-def test_remotes_preserves_git_ssh(
-    projects_path: pathlib.Path,
-    git_remote_repo: pathlib.Path,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-):
-    # Regression test for #14
-    repo_name = "myexamplegit"
-    dir = projects_path / repo_name
-    remote_name = "myremote"
-    remote_url = "git+ssh://git@github.com/tony/AlgoXY.git"
-    git_repo: GitProject = constructor(**lazy_constructor_options(**locals()))
-
-    git_repo.obtain()
-    git_repo.set_remote(name=remote_name, url=remote_url)
-
-    assert (
-        GitRemote(remote_name, remote_url, remote_url).to_dict()
-        in git_repo.remotes().values()
-    )
-
-
-@pytest.mark.parametrize(
-    # Postpone evaluation of options so fixture variables can interpolate
-    "constructor,lazy_constructor_options",
-    [
-        [
-            GitProject,
-            lambda bare_dir, tmp_path, **kwargs: {
-                "url": f"file://{bare_dir}",
-                "dir": tmp_path / "obtaining a bare repo",
-                "vcs": "git",
-            },
-        ],
-        [
-            create_project,
-            lambda bare_dir, tmp_path, **kwargs: {
-                "url": f"git+file://{bare_dir}",
-                "dir": tmp_path / "obtaining a bare repo",
-                "vcs": "git",
-            },
-        ],
-    ],
-)
-def test_private_ssh_format(
-    tmpdir: pathlib.Path,
-    constructor: ProjectTestFactory,
-    lazy_constructor_options: ProjectTestFactoryLazyKwargs,
-):
-    with pytest.raises(exc.LibVCSException) as excinfo:
-        create_project(
-            url=git_convert_pip_url(
-                "git+ssh://github.com:/tmp/omg/private_ssh_repo"
-            ).url,
-            dir=tmpdir,
-            vcs="git",
-        )
-        excinfo.match(r".*is a malformed.*")
-
-
-def test_ls_remotes(git_repo: GitProject):
-    remotes = git_repo.remotes()
-
-    assert "origin" in remotes
-    assert "origin" in git_repo.remotes(flat=True)
-
-
-def test_get_remotes(git_repo: GitProject):
-    assert "origin" in git_repo.remotes()
-
-
-@pytest.mark.parametrize(
-    "repo_name,new_repo_url",
-    [
-        ["myrepo", "file:///apples"],
-    ],
-)
-def test_set_remote(git_repo: GitProject, repo_name: str, new_repo_url: str):
-    mynewremote = git_repo.set_remote(name=repo_name, url="file:///")
-
-    assert "file:///" in mynewremote.fetch_url, "set_remote returns remote"
-
-    assert isinstance(
-        git_repo.remote(name=repo_name), GitRemote
-    ), "remote() returns GitRemote"
-    remote = git_repo.remote(name=repo_name)
-    assert remote is not None, "Remote should exist"
-    if remote is not None:
-        assert "file:///" in remote.fetch_url, "new value set"
-
-    assert "myrepo" in git_repo.remotes(), ".remotes() returns new remote"
-
-    with pytest.raises(
-        exc.CommandError,
-        match=f".*remote {repo_name} already exists.*",
-    ):
-        mynewremote = git_repo.set_remote(name="myrepo", url=new_repo_url)
-
-    mynewremote = git_repo.set_remote(name="myrepo", url=new_repo_url, overwrite=True)
-
-    remote = git_repo.remote(name="myrepo")
-    assert remote is not None
-    if remote is not None:
-        assert (
-            new_repo_url in remote.fetch_url
-        ), "Running remove_set should overwrite previous remote"
-
-
-def test_get_git_version(git_repo: GitProject):
-    expected_version = git_repo.run(["--version"]).replace("git version ", "")
-    assert git_repo.get_git_version()
-    assert expected_version == git_repo.get_git_version()
-
-
-def test_get_current_remote_name(git_repo: GitProject):
-    assert git_repo.get_current_remote_name() == "origin"
-
-    new_branch = "another-branch-with-no-upstream"
-    git_repo.run(["checkout", "-B", new_branch])
-    assert (
-        git_repo.get_current_remote_name() == new_branch
-    ), "branch w/o upstream should return branch only"
-
-    new_remote_name = "new_remote_name"
-    git_repo.set_remote(
-        name=new_remote_name, url=f"file://{git_repo.dir}", overwrite=True
-    )
-    git_repo.run(["fetch", new_remote_name])
-    git_repo.run(["branch", "--set-upstream-to", f"{new_remote_name}/{new_branch}"])
-    assert (
-        git_repo.get_current_remote_name() == new_remote_name
-    ), "Should reflect new upstream branch (different remote)"
-
-    upstream = "{}/{}".format(new_remote_name, "master")
-
-    git_repo.run(["branch", "--set-upstream-to", upstream])
-    assert (
-        git_repo.get_current_remote_name() == upstream
-    ), "Should reflect upstream branch (differente remote+branch)"
-
-    git_repo.run(["checkout", "master"])
-
-    # Different remote, different branch
-    remote = f"{new_remote_name}/{new_branch}"
-    git_repo.run(["branch", "--set-upstream-to", remote])
-    assert (
-        git_repo.get_current_remote_name() == remote
-    ), "Should reflect new upstream branch (different branch)"
-
-
-def test_GitRemote_from_stdout():
-    FIXTURE_A = textwrap.dedent(
-        """
-        # branch.oid d4ccd4d6af04b53949f89fbf0cdae13719dc5a08
-        # branch.head fix-current-remote-name
-        1 .M N... 100644 100644 100644 91082f119279b6f105ee9a5ce7795b3bdbe2b0de 91082f119279b6f105ee9a5ce7795b3bdbe2b0de CHANGES
-    """  # NOQA: E501
-    )
-    assert {
-        "branch_oid": "d4ccd4d6af04b53949f89fbf0cdae13719dc5a08",
-        "branch_head": "fix-current-remote-name",
-    }.items() <= GitStatus.from_stdout(FIXTURE_A).to_dict().items()
-
-
-@pytest.mark.parametrize(
-    "fixture,expected_result",
-    [
-        [
-            """
-        # branch.oid de6185fde0806e5c7754ca05676325a1ea4d6348
-        # branch.head fix-current-remote-name
-        # branch.upstream origin/fix-current-remote-name
-        # branch.ab +0 -0
-        1 .M N... 100644 100644 100644 91082f119279b6f105ee9a5ce7795b3bdbe2b0de 91082f119279b6f105ee9a5ce7795b3bdbe2b0de CHANGES
-        1 .M N... 100644 100644 100644 302ca2c18d4c295ce217bff5f93e1ba342dc6665 302ca2c18d4c295ce217bff5f93e1ba342dc6665 tests/test_git.py
-    """,  # NOQA: E501
-            {
-                "branch_oid": "de6185fde0806e5c7754ca05676325a1ea4d6348",
-                "branch_head": "fix-current-remote-name",
-                "branch_upstream": "origin/fix-current-remote-name",
-                "branch_ab": "+0 -0",
-                "branch_ahead": "0",
-                "branch_behind": "0",
-            },
-        ],
-        [
-            "# branch.upstream moo/origin/myslash/remote",
-            {"branch_upstream": "moo/origin/myslash/remote"},
-        ],
-        [
-            """
-            # branch.oid c3c5323abc5dca78d9bdeba6c163c2a37b452e69
-            # branch.head libvcs-0.4.0
-            # branch.upstream origin/libvcs-0.4.0
-            # branch.ab +0 -0
-            """,
-            {
-                "branch_oid": "c3c5323abc5dca78d9bdeba6c163c2a37b452e69",
-                "branch_head": "libvcs-0.4.0",
-                "branch_upstream": "origin/libvcs-0.4.0",
-                "branch_ab": "+0 -0",
-                "branch_ahead": "0",
-                "branch_behind": "0",
-            },
-        ],
-    ],
-)
-def test_GitRemote__from_stdout_b(fixture: str, expected_result: dict):
-    assert (
-        GitStatus.from_stdout(textwrap.dedent(fixture)).to_dict().items()
-        >= expected_result.items()
-    )
-
-
-@pytest.mark.parametrize(
-    "fixture,expected_result",
-    [
-        [
-            "# branch.ab +1 -83",
-            {
-                "branch_ab": "+1 -83",
-                "branch_ahead": "1",
-                "branch_behind": "83",
-            },
-        ],
-        [
-            """
-            # branch.ab +0 -0
-            """,
-            {
-                "branch_ab": "+0 -0",
-                "branch_ahead": "0",
-                "branch_behind": "0",
-            },
-        ],
-        [
-            """
-            # branch.ab +1 -83
-            """,
-            {
-                "branch_ab": "+1 -83",
-                "branch_ahead": "1",
-                "branch_behind": "83",
-            },
-        ],
-        [
-            """
-            # branch.ab +9999999 -9999999
-            """,
-            {
-                "branch_ab": "+9999999 -9999999",
-                "branch_ahead": "9999999",
-                "branch_behind": "9999999",
-            },
-        ],
-    ],
-)
-def test_GitRemote__from_stdout_c(fixture: str, expected_result: dict):
-    assert (
-        expected_result.items()
-        <= GitStatus.from_stdout(textwrap.dedent(fixture)).to_dict().items()
-    )
-
-
-def test_repo_git_remote_checkout(
-    create_git_remote_repo: CreateProjectCallbackFixtureProtocol,
-    tmp_path: pathlib.Path,
-    projects_path: pathlib.Path,
-):
-    git_server = create_git_remote_repo()
-    git_repo_checkout_dir = projects_path / "my_git_checkout"
-    git_repo = GitProject(dir=str(git_repo_checkout_dir), url=f"file://{git_server!s}")
-
-    git_repo.obtain()
-    git_repo.update_repo()
-
-    assert git_repo.get_revision() == "initial"
-
-    assert git_repo_checkout_dir.exists()
-    assert pathlib.Path(git_repo_checkout_dir / ".git").exists()
diff --git a/tests/projects/test_hg.py b/tests/projects/test_hg.py
deleted file mode 100644
index fa845758d..000000000
--- a/tests/projects/test_hg.py
+++ /dev/null
@@ -1,55 +0,0 @@
-"""Tests for libvcs hg repos."""
-import pathlib
-
-import pytest
-
-from libvcs._internal.run import run, which
-from libvcs._internal.shortcuts import create_project
-
-if not which("hg"):
-    pytestmark = pytest.mark.skip(reason="hg is not available")
-
-
-def test_repo_mercurial(tmp_path: pathlib.Path, projects_path, hg_remote_repo):
-    repo_name = "my_mercurial_project"
-
-    mercurial_repo = create_project(
-        url=f"file://{hg_remote_repo}",
-        dir=projects_path / repo_name,
-        vcs="hg",
-    )
-
-    run(["hg", "init", mercurial_repo.repo_name], cwd=tmp_path)
-
-    mercurial_repo.update_repo()
-
-    test_repo_revision = run(
-        ["hg", "parents", "--template={rev}"], cwd=projects_path / repo_name
-    )
-
-    assert mercurial_repo.get_revision() == test_repo_revision
-
-
-def test_vulnerability_2022_03_12_command_injection(
-    monkeypatch: pytest.MonkeyPatch,
-    user_path: pathlib.Path,
-    tmp_path: pathlib.Path,
-    hg_remote_repo,
-):
-    """Prevent hg aliases from executed arbitrary commands via URLs.
-
-    As of 0.11 this code path is/was only executed via .obtain(), so this only would
-    effect explicit invocation of .object() or update_repo() of uncloned destination.
-    """
-    random_dir = tmp_path / "random"
-    random_dir.mkdir()
-    monkeypatch.chdir(str(random_dir))
-    mercurial_repo = create_project(
-        url="--config=alias.clone=!touch ./HELLO", vcs="hg", dir="./"
-    )
-    with pytest.raises(Exception):
-        mercurial_repo.update_repo()
-
-    assert not pathlib.Path(
-        random_dir / "HELLO"
-    ).exists(), "Prevent command injection in hg aliases"
diff --git a/tests/projects/test_svn.py b/tests/projects/test_svn.py
deleted file mode 100644
index 3f67e3846..000000000
--- a/tests/projects/test_svn.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""tests for libvcs svn repos."""
-import os
-import pathlib
-
-import pytest
-
-from libvcs._internal.run import which
-from libvcs.conftest import CreateProjectCallbackFixtureProtocol
-from libvcs.projects.svn import SubversionProject
-
-if not which("svn"):
-    pytestmark = pytest.mark.skip(reason="svn is not available")
-
-
-def test_repo_svn(tmp_path: pathlib.Path, svn_remote_repo):
-    repo_name = "my_svn_project"
-
-    svn_repo = SubversionProject(
-        url=f"file://{svn_remote_repo}",
-        dir=str(tmp_path / repo_name),
-    )
-
-    svn_repo.obtain()
-    svn_repo.update_repo()
-
-    assert svn_repo.get_revision() == 0
-    assert svn_repo.get_revision_file("./") == 0
-
-    assert os.path.exists(tmp_path / repo_name)
-
-
-def test_repo_svn_remote_checkout(
-    create_svn_remote_repo: CreateProjectCallbackFixtureProtocol,
-    tmp_path: pathlib.Path,
-    projects_path: pathlib.Path,
-):
-    svn_server = create_svn_remote_repo()
-    svn_repo_checkout_dir = projects_path / "my_svn_checkout"
-    svn_repo = SubversionProject(
-        dir=svn_repo_checkout_dir, url=f"file://{svn_server!s}"
-    )
-
-    svn_repo.obtain()
-    svn_repo.update_repo()
-
-    assert svn_repo.get_revision() == 0
-    assert svn_repo.get_revision_file("./") == 0
-
-    assert svn_repo_checkout_dir.exists()
diff --git a/tests/test_exc.py b/tests/test_exc.py
deleted file mode 100644
index ef95517b2..000000000
--- a/tests/test_exc.py
+++ /dev/null
@@ -1,33 +0,0 @@
-"""tests for libvcs exceptions."""
-import pytest
-
-from libvcs import exc
-
-
-def test_command_error():
-    with pytest.raises(exc.CommandError) as e:
-        returncode = 0
-        command = ["command", "arg"]
-        raise exc.CommandError("this is output", returncode, command)
-    assert e.value.cmd == " ".join(command)
-    assert (
-        str(e.value)
-        == exc.CommandError.message.format(
-            returncode=e.value.returncode, cmd=e.value.cmd
-        )
-        + "\n%s" % e.value.output
-    )
-
-    with pytest.raises(exc.CommandError) as e:
-        returncode = 0
-        command = ["command", "arg"]
-        raise exc.CommandError("", returncode, command)
-    assert e.value.cmd == " ".join(command)
-    assert str(e.value) == exc.CommandError.message.format(
-        returncode=e.value.returncode, cmd=e.value.cmd
-    )
-
-    with pytest.raises(exc.CommandError) as e:
-        command = "command arg"
-        raise exc.CommandError("this is output", 0, command)
-    assert e.value.cmd == command
diff --git a/tests/test_shortcuts.py b/tests/test_shortcuts.py
deleted file mode 100644
index 832693a0c..000000000
--- a/tests/test_shortcuts.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import pathlib
-
-import pytest
-
-from libvcs import GitProject, MercurialProject, SubversionProject
-from libvcs._internal.shortcuts import create_project
-from libvcs.exc import InvalidVCS
-
-
-@pytest.mark.parametrize(
-    "repo_dict,repo_class,raises_exception",
-    [
-        (
-            {"url": "https://github.com/freebsd/freebsd.git", "vcs": "git"},
-            GitProject,
-            False,
-        ),
-        (
-            {"url": "https://bitbucket.org/birkenfeld/sphinx", "vcs": "hg"},
-            MercurialProject,
-            False,
-        ),
-        (
-            {"url": "http://svn.code.sf.net/p/docutils/code/trunk", "vcs": "svn"},
-            SubversionProject,
-            False,
-        ),
-        (
-            {"url": "http://svn.code.sf.net/p/docutils/code/trunk", "vcs": "svna"},
-            None,
-            InvalidVCS,
-        ),
-    ],
-)
-def test_create_project(
-    tmp_path: pathlib.Path, repo_dict, repo_class, raises_exception
-):
-    # add parent_dir via fixture
-    repo_dict["dir"] = tmp_path / "repo_name"
-
-    if raises_exception:
-        with pytest.raises(raises_exception):
-            create_project(**repo_dict)
-    else:
-        repo = create_project(**repo_dict)
-        assert isinstance(repo, repo_class)
