vcs.py
Utilities related to VCS.
checkout_latest_tag(local_repo, use_prereleases=False)
¶
Checkout latest git tag and check it out, sorted by PEP 440.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
local_repo |
Union[str, pathlib.Path] |
A git repository in the local filesystem. |
required |
use_prereleases |
Optional[bool] |
If |
False |
Source code in copier/vcs.py
def checkout_latest_tag(local_repo: StrOrPath, use_prereleases: OptBool = False) -> str:
"""Checkout latest git tag and check it out, sorted by PEP 440.
Parameters:
local_repo:
A git repository in the local filesystem.
use_prereleases:
If `False`, skip prerelease git tags.
"""
with local.cwd(local_repo):
all_tags = git("tag").split()
if not use_prereleases:
all_tags = filter(
lambda tag: not version.parse(tag).is_prerelease, all_tags
)
sorted_tags = sorted(all_tags, key=version.parse, reverse=True)
try:
latest_tag = str(sorted_tags[0])
except IndexError:
print(
colors.warn | "No git tags found in template; using HEAD as ref",
file=sys.stderr,
)
latest_tag = "HEAD"
git("checkout", "--force", latest_tag)
git("submodule", "update", "--checkout", "--init", "--recursive", "--force")
return latest_tag
clone(url, ref=None)
¶
Clone repo into some temporary destination.
Includes dirty changes for local templates by copying into a temp directory and applying a wip commit there.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
url |
str |
Git-parseable URL of the repo. As returned by get_repo. |
required |
ref |
Optional[str] |
Reference to checkout. For Git repos, defaults to |
None |
Source code in copier/vcs.py
def clone(url: str, ref: OptStr = None) -> str:
"""Clone repo into some temporary destination.
Includes dirty changes for local templates by copying into a temp
directory and applying a wip commit there.
Args:
url:
Git-parseable URL of the repo. As returned by
[get_repo][copier.vcs.get_repo].
ref:
Reference to checkout. For Git repos, defaults to `HEAD`.
"""
location = tempfile.mkdtemp(prefix=f"{__name__}.clone.")
_clone = git["clone", "--no-checkout", url, location]
# Faster clones if possible
if GIT_VERSION >= Version("2.27"):
_clone = _clone["--filter=blob:none"]
_clone()
if not ref and os.path.exists(url) and Path(url).is_dir():
is_dirty = False
with local.cwd(url):
is_dirty = bool(git("status", "--porcelain").strip())
if is_dirty:
url_abspath = Path(url).absolute()
with local.cwd(location):
git("--git-dir=.git", f"--work-tree={url_abspath}", "add", "-A")
git(
"--git-dir=.git",
f"--work-tree={url_abspath}",
"commit",
"-m",
"Copier automated commit for draft changes",
"--no-verify",
)
warn(
"Dirty template changes included automatically.",
DirtyLocalWarning,
)
with local.cwd(location):
git("checkout", ref or "HEAD")
git("submodule", "update", "--checkout", "--init", "--recursive", "--force")
return location
get_repo(url)
¶
Transforms url
into a git-parseable origin URL.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
url |
str |
Valid examples:
|
required |
Source code in copier/vcs.py
def get_repo(url: str) -> OptStr:
"""Transforms `url` into a git-parseable origin URL.
Args:
url:
Valid examples:
- gh:copier-org/copier
- gl:copier-org/copier
- git@github.com:copier-org/copier.git
- git+https://mywebsiteisagitrepo.example.com/
- /local/path/to/git/repo
- /local/path/to/git/bundle/file.bundle
"""
for pattern, replacement in REPLACEMENTS:
url = re.sub(pattern, replacement, url)
url_path = Path(url)
if not (
url.endswith(GIT_POSTFIX)
or url.startswith(GIT_PREFIX)
or is_git_repo_root(url_path)
or is_git_bundle(url_path)
):
return None
if url.startswith("git+"):
url = url[4:]
return url
is_git_bundle(path)
¶
Indicate if a path is a valid git bundle.
Source code in copier/vcs.py
def is_git_bundle(path: Path) -> bool:
"""Indicate if a path is a valid git bundle."""
with TemporaryDirectory(prefix=f"{__name__}.is_git_bundle.") as dirname:
with local.cwd(dirname):
git("init")
return bool(git["bundle", "verify", path] & TF)
is_git_repo_root(path)
¶
Indicate if a given path is a git repo root directory.
Source code in copier/vcs.py
def is_git_repo_root(path: StrOrPath) -> bool:
"""Indicate if a given path is a git repo root directory."""
try:
with local.cwd(Path(path, ".git")):
return bool(git("rev-parse", "--is-inside-git-dir").strip() == "true")
except OSError:
return False
is_in_git_repo(path)
¶
Indicate if a given path is in a git repo directory.
Source code in copier/vcs.py
def is_in_git_repo(path: StrOrPath) -> bool:
"""Indicate if a given path is in a git repo directory."""
try:
git("-C", path, "rev-parse", "--show-toplevel")
return True
except (OSError, ProcessExecutionError):
return False