Source code for datalad_next.repo_utils.worktree

from __future__ import annotations

from pathlib import Path

from datalad_next.exceptions import CapturedException
from datalad_next.runners import (
    CommandError,
    call_git_lines,
)


[docs] def get_worktree_head( path: Path, ) -> tuple[str | None, str | None]: """Returns the symbolic name of the worktree `HEAD` at the given path Returns ------- tuple The first item is the symbolic name of the worktree `HEAD`, or `None` if there is no commit. The second item is the symbolic name of the "corresponding branch" in an adjusted-mode git-annex repository, or `None`. """ try: HEAD = call_git_lines( # we add the pathspec disambiguator to get cleaner error messages # (and we only report the first item below, to take it off again) ['rev-parse', '-q', '--symbolic-full-name', 'HEAD', '--'], cwd=path, # we are doing error message parsing below, fix the language # to avoid making it even more fragile force_c_locale=True, )[0] except (NotADirectoryError, FileNotFoundError) as e: raise ValueError('path not found') from e except CommandError as e: CapturedException(e) if 'fatal: not a git repository' in e.stderr: raise ValueError(f'no Git repository at {path!r}') from e elif 'fatal: bad revision' in e.stderr: return (None, None) else: # no idea reraise raise if HEAD.startswith('refs/heads/adjusted/'): # this is a git-annex adjusted branch. do the comparison against # its basis. it is not meaningful to track the managed branch in # a superdataset return ( HEAD, # replace 'refs/heads' with 'refs/basis' f'refs/basis/{HEAD[11:]}', ) else: return (HEAD, None)