Source code for sphinx_versioned.versions

import os

os.environ["GIT_PYTHON_REFRESH"] = "quiet"

import git
import pathlib
from abc import ABC
from loguru import logger as log


[docs] class PseudoBranch: """Class to generate a branch/pseudo-branch for git detached head/commit. Parameters ---------- name : :class:`str` Branch/pseudo-branch name. """ def __init__(self, name: str) -> None: self.name = name return def __repr__(self) -> str: return self.name pass
[docs] class _BranchTag(ABC): """Abstract base class for getting relative paths of branches and tags as properties.""" @property def branches(self) -> dict: """Get the branches and its ``index.html`` location. Returns ------- :class:`dict` """ return { x: "../" + str(y.relative_to(self.build_directory) / "index.html") for x, y in self._branches.items() } @property def tags(self) -> dict: """Get the tags and its ``index.html`` location. Returns ------- :class:`dict` """ return { x: "../" + str(y.relative_to(self.build_directory) / "index.html") for x, y in self._tags.items() } pass
[docs] class GitVersions(_BranchTag): """Handles git branches and tags. Builds upon the abstract base class :class:`sphinx_versioned.versions._BranchTag`. Initlizes and latches into the git repo. Parameters ---------- git_root : :class:`str` Git repository root directory. build_directory : :class:`str` Path of build directory. force_branches : :class:`bool` This option allows `GitVersions` to treat the detached commits as normal branches. Use this option to build docs for detached head/commits. """ def __init__(self, git_root: str, build_directory: str, force_branches: bool) -> None: self.git_root = git_root self.build_directory = pathlib.Path(build_directory) self.force_branches = force_branches # for detached head self._active_branch = None if not self.build_directory.exists(): self.build_directory.mkdir(parents=True, exist_ok=True) self.repo = git.Repo(git_root) if self.repo.bare: self.repo = git.Repo(os.getcwd()) if self.repo.bare: log.error("The git repository is bare. Add some commits then try again!") exit(-1) log.success("latched into the git repo") self._parse_branches() return
[docs] def _parse_branches(self) -> bool: """Parse branches and tags into separate variables. Collect all branches and tags in `GitVersions.all_versions`. Additionally, if the head is detached and `--force` is supplied, then append a PseudoBranch representing the detached commit sha. Returns ------- :class:`bool` """ self._raw_branches = self.repo.branches self._raw_tags = self.repo.tags self._branches = {x.name: self.build_directory / x.name for x in self._raw_branches} self._tags = {x.name: self.build_directory / x.name for x in self._raw_tags} self.all_versions = [*self._raw_tags, *self._raw_branches] # check if if the current git status is detached, if yes, and if `--force` is supplied -> append: if self.repo.head.is_detached: log.warning(f"git head detached {self.repo.head.is_detached}") if self.force_branches: log.debug("Forcing detached commit into PseudoBranch") self.all_versions.append(PseudoBranch(self.repo.head.object.hexsha)) log.debug(f"Found versions: {[x.name for x in self.all_versions]}") return True
[docs] def checkout(self, name, *args, **kwargs) -> bool: """git checkout the branch/tag with its ``name``. Parameters ---------- name : :class:`str` Name of the branch/tag. """ self._active_branch = name log.debug(f"git checkout branch/tag: `{name}`") return self.repo.git.checkout(name, *args, **kwargs)
@property def active_branch(self, *args, **kwargs): """Property to get the currently active branch.""" if self._active_branch: return self._active_branch if self.repo.head.is_detached: log.warning(f"git head detached: {self.repo.head.is_detached}") return PseudoBranch(self.repo.head.object.hexsha) return self.repo.active_branch pass
[docs] class BuiltVersions(_BranchTag): """Handles versions to build. Builds upon the abstract base class :class:`sphinx_versioned.versions._BranchTag`. Parameters ---------- versions : :class:`list` Versions to be build. build_directory : :class:`str` Path of the build directory. """ def __init__(self, versions: list, build_directory: str) -> None: self._versions = versions self.build_directory = pathlib.Path(build_directory) if not self.build_directory.exists(): self.build_directory.mkdir(parents=True, exist_ok=True) self._parse() return
[docs] def _parse(self) -> bool: """Parse raw branches/tags in :class:`~sphinx_versioned.versions.GitVersions` instance into separate variables.""" self._raw_tags = [] self._raw_branches = [] for tag in self._versions: if isinstance(tag, git.TagReference): self._raw_tags.append(tag) else: self._raw_branches.append(tag) self._branches = {x.name: self.build_directory / x.name for x in self._raw_branches} self._tags = {x.name: self.build_directory / x.name for x in self._raw_tags} return True
pass