
    h              
      f   S SK Jr  S SKJr  S SKJr   " S S5      r\S:X  a  S SKr\" 5       r	\	R                  (       ar  \R                  " 5       r\" S\	R                   S	\	R                   S
\	R                    S\	R"                   35        \R                  " 5       \-
  S-  r\" S\S S35        ggg)    )annotations)cached_property)Pathc                      \ rS rSrSr\" \5      R                  5       4SS jjr\	SS j5       r
\	SS j5       rSS jr\SS j5       rSS jr\SS	 j5       r\SS
 j5       r\SS j5       r\SS j5       rSrg)GitRepo	   a  
Represent a local Git repository and expose branch, commit, and remote metadata.

This class discovers the repository root by searching for a .git entry from the given path upward, resolves the
actual .git directory (including worktrees), and reads Git metadata directly from on-disk files. It does not
invoke the git binary and therefore works in restricted environments. All metadata properties are resolved
lazily and cached; construct a new instance to refresh state.

Attributes:
    root (Path | None): Repository root directory containing the .git entry; None if not in a repository.
    gitdir (Path | None): Resolved .git directory path; handles worktrees; None if unresolved.
    head (str | None): Raw contents of HEAD; a SHA for detached HEAD or "ref: <refname>" for branch heads.
    is_repo (bool): Whether the provided path resides inside a Git repository.
    branch (str | None): Current branch name when HEAD points to a branch; None for detached HEAD or non-repo.
    commit (str | None): Current commit SHA for HEAD; None if not determinable.
    origin (str | None): URL of the "origin" remote as read from gitdir/config; None if unset or unavailable.

Examples:
    Initialize from the current working directory and read metadata
    >>> from pathlib import Path
    >>> repo = GitRepo(Path.cwd())
    >>> repo.is_repo
    True
    >>> repo.branch, repo.commit[:7], repo.origin
    ('main', '1a2b3c4', 'https://example.com/owner/repo.git')

Notes:
    - Resolves metadata by reading files: HEAD, packed-refs, and config; no subprocess calls are used.
    - Caches properties on first access using cached_property; recreate the object to reflect repository changes.
c                    U R                  U5      U l        U R                  (       a!  U R                  U R                  5      U l        gSU l        g)z
Initialize a Git repository context by discovering the repository root from a starting path.

Args:
    path (Path, optional): File or directory path used as the starting point to locate the repository root.
N)
_find_rootroot_gitdirgitdir)selfpaths     O/home/james-whalen/.local/lib/python3.13/site-packages/ultralytics/utils/git.py__init__GitRepo.__init__)   s4     OOD)	15dll499-    c                V    [        S U /[        U R                  5      -    5       S5      $ )zReturn repo root or None.c              3  X   #    U  H   oS -  R                  5       (       d  M  Uv   M"     g7f).gitN)exists).0ds     r   	<genexpr>%GitRepo._find_root.<locals>.<genexpr>6   s!     O 51f*9L9L9NQQ 5s   *	*N)nextlistparents)ps    r   r
   GitRepo._find_root3   s'     Od199o 5OQUVVr   c                2   U S-  nUR                  5       (       a  U$ UR                  5       (       af  UR                  SS9R                  5       nUR	                  S5      (       a3  XR                  SS5      S   R                  5       -  R                  5       $ g)z2Resolve actual .git directory (handles worktrees).r   ignoreerrorszgitdir::   N)is_diris_file	read_textstrip
startswithsplitresolve)r   gts      r   r   GitRepo._gitdir8   s}     6M88::H99;;8,224A||I&&wwsAq17799BBDDr   c                x    U(       a2  UR                  5       (       a  UR                  SS9R                  5       $ S$ )zRead and strip file if exists.r"   r#   N)r   r)   r*   )r   r   s     r   _readGitRepo._readD   s-    78QXXZZq{{({+113QTQr   c                l    U R                  U R                  (       a  U R                  S-  5      $ S5      $ )zHEAD file contents.HEADN)r2   r   r   s    r   headGitRepo.headH   s*     zz$++$++.HH4HHr   c                   U R                   U-  nU R                  U5      nU(       a  U$ U R                   S-  nUR                  5       (       a  UR                  5       R	                  5       O/ nUR                  5       nU HN  nUSS S;   d  SU;  a  M  UR                  SS5      u  pU	R                  5       U:X  d  M>  UR                  5       s  $    g)z%Commit for ref (handles packed-refs).zpacked-refsNr&   )   #   ^    )	r   r2   r   
read_bytes
splitlinesencoder,   r*   decode)
r   refrfspfbtgtlineshanames
             r   _ref_commitGitRepo._ref_commitM   s    [[3JJrNH[[=(,.IIKKBMMO&&(RjjlDBQx<'4t+;

4+ICzz|s"zz|#  r   c                    U R                   SL$ )zTrue if inside a git repo.N)r   r6   s    r   is_repoGitRepo.is_repo^   s     {{$&&r   c                   U R                   (       a1  U R                  (       a   U R                  R                  S5      (       d  gU R                  SS R                  5       nUR                  S5      (       a  U[	        S5      S $ U$ )zCurrent branch or None.ref: N   zrefs/heads/)rM   r7   r+   r*   len)r   rA   s     r   branchGitRepo.branchc   sf     ||499DII4H4H4Q4Qiim!!#,/NN=,I,Is3}%'(RsRr   c                    U R                   (       a  U R                  (       d  gU R                  R                  S5      (       a,  U R                  U R                  SS R	                  5       5      $ U R                  $ )zCurrent commit SHA or None.NrP   rQ   )rM   r7   r+   rJ   r*   r6   s    r   commitGitRepo.commitk   sX     ||499:>)):N:Nw:W:Wt		!" 3 3 56f]a]f]ffr   c                   U R                   (       d  gU R                  S-  nSu  p#U R                  U5      =(       d    SR                  5        H  nUR	                  5       nUR                  S5      (       a(  UR                  S5      (       a  UR                  5       nMQ  UR                  5       R                  S5      (       d  Mw  US:X  d  M  UR                  S	S
5      S
   R	                  5       n  U$    U$ )zOrigin URL or None.Nconfig)NN []zurl =z[remote "origin"]=r&   )	rM   r   r2   r>   r*   r+   endswithlowerr,   )r   cfgremoteurlrC   r/   s         r   originGitRepo.originr   s     ||kkH$ **S/'R335A	A||C  QZZ__%%g..6=P3Pggc1oa(..0
 6 
r   )r   r   N)r   r   )r   r   returnPath | None)r   r   re   rf   )r   rf   re   
str | None)re   rg   )rA   strre   rg   )re   bool)__name__
__module____qualname____firstlineno____doc__r   __file__r-   r   staticmethodr
   r   r2   r   r7   rJ   propertyrM   rS   rV   rc   __static_attributes__ r   r   r   r   	   s    > %)N$:$:$< E W W 	 	R I I" ' ' S S g g  r   r   __main__Nzrepo=z
branch=z
commit=z
origin=i  u   
⏱️ Profiling: total z.3fz ms)
__future__r   	functoolsr   pathlibr   r   rj   timer.   rM   perf_countert0printr   rS   rV   rc   dtrs   r   r   <module>r}      s    # % w wt z	Ayy affXYqxxj	!((9QXXJWX!B&$.*2c(#67	 	 r   