"""Functionality for working with a git repository"""frompathlibimportPathfromtypingimportOptional,TypeVar,Unionfrom.importshellfrom.exceptionsimportShellCommandExceptionfrom.file_systemimportPathLike,chdirfrom.logimportloggerT=TypeVar("T")
[docs]defgit_tree_add(struct:dict,prefix:PathLike="",**kwargs):"""Adds recursively a directory structure to git Args: struct: directory structure as dictionary of dictionaries prefix: prefix for the given directory structure Additional keyword arguments are passed to the :obj:`git <pyscaffold.shell.ShellCommand>` callable object. """prefix=Path(prefix)forname,contentinstruct.items():ifisinstance(content,dict):git_tree_add(struct[name],prefix=prefix/name,**kwargs)elifcontentisNoneorisinstance(content,str):shell.git("add",str(prefix/name),**kwargs)else:raiseTypeError(f"Don't know what to do with content type {type}.")
[docs]defadd_tag(project:PathLike,tag_name:str,message:Optional[str]=None,**kwargs):"""Add an (annotated) tag to the git repository. Args: project: path to the project tag_name: name of the tag message: optional tag message Additional keyword arguments are passed to the :obj:`git <pyscaffold.shell.ShellCommand>` callable object. """withchdir(project):ifmessageisNone:shell.git("tag",tag_name,**kwargs)else:shell.git("tag","-a",tag_name,"-m",message,**kwargs)
[docs]definit_commit_repo(project:PathLike,struct:dict,**kwargs):"""Initialize a git repository Args: project: path to the project struct: directory structure as dictionary of dictionaries Additional keyword arguments are passed to the :obj:`git <pyscaffold.shell.ShellCommand>` callable object. """logger.report("initialize",f"git repo in {project}...")withchdir(project,pretend=kwargs.get("pretend")):shell.git("init",**kwargs)git_tree_add(struct,**kwargs)shell.git("commit","-m","Initial commit",**kwargs)
[docs]defis_git_repo(path:PathLike):"""Check if path is a git repository"""path=Path(path)logger.report("check",f"is {path} already a git repo...")ifnotpath.is_dir():returnFalsewithchdir(path):try:shell.git("rev-parse","--git-dir")exceptShellCommandException:returnFalsereturnTrue
[docs]defget_git_root(default:Optional[T]=None)->Union[None,T,str]:"""Return the path to the top-level of the git repository or *default*. Args: default: if no git root is found, default is returned Returns: str: top-level path or *default* """try:returnnext(shell.git("rev-parse","--show-toplevel"))exceptShellCommandException:returndefault