Source code for gitspy._subprocess

"""
gitspy._subprocess
==================
"""
import contextlib as _contextlib
import os as _os
import subprocess as _sp
import typing as _t
from pathlib import Path as _Path

from spall import Subprocess as _Subprocess


[docs]class Git(_Subprocess): """Git commands as class attributes. @DynamicAttrs """ def __init__(self) -> None: self.commands = [ i.lstrip().split()[0] for i in _sp.check_output(["git", "help", "--all"]) .decode() .splitlines() if i.startswith(" ") ] super().__init__("git", positionals=self.commands) def _get_gitdir(self, path: _Path) -> _t.Optional[_Path]: # find and return the path to the repository's .git directory # start with provided path and any parent up to / where None is # returned if working outside a repository gitdir = path / ".git" if gitdir.is_dir(): return gitdir if path == _Path("/"): return None return self._get_gitdir(path.parent)
[docs] def call( self, *args: str, **kwargs: _t.Union[bool, str, _os.PathLike] ) -> int: """Call partial git command instantiated in superclass. :param args: Command's positional arguments. :key file: File path to write the stdout stream to. :key capture: Pipe stream to self. :key devnull: Suppress output. :key suppress: Suppress errors and continue running. :raises CalledProcessError: If error occurs in subprocess. :return: Exit status. """ cwd = _Path.cwd().absolute() gitdir = self._get_gitdir(cwd) or cwd / ".git" try: _os.environ.update( GIT_DIR=str(gitdir), GIT_WORK_TREE=str(gitdir.parent) ) # silence stderr to avoid duplicates if error raised again # and to avoid writing to stderr if second command succeeds with _contextlib.redirect_stderr(None): return super().call(*args, **kwargs) # options such as `--bare` won't allow `GIT_WORK_TREE` to be set except _sp.CalledProcessError: del _os.environ["GIT_WORK_TREE"] return super().call(*args, **kwargs)