
    .h              
      Z   d dl mZ d dlmZ d dlmZ  G d d      Zedk(  rd dlZ e       Z	e	j                  rr ej                         Z ede	j                   d	e	j                   d
e	j                    de	j"                           ej                         ez
  dz  Z ededd       yyy)    )annotations)cached_property)Pathc                      e Zd ZdZ ee      j                         fddZedd       Z	edd       Z
ddZedd       ZddZedd       Zedd	       Zedd
       Zedd       Zy)GitRepoa  
    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                    | j                  |      | _        | j                  r!| j                  | j                        | _        yd| _        y)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     S/var/www/html/ai-service/venv/lib/python3.12/site-packages/ultralytics/utils/git.py__init__zGitRepo.__init__)   s4     OOD)	15dll499-    c                V    t        d | gt        | j                        z   D        d      S )zReturn repo root or None.c              3  H   K   | ]  }|d z  j                         s|  yw).gitN)exists).0ds     r   	<genexpr>z%GitRepo._find_root.<locals>.<genexpr>6   s     O1!f*9L9L9NQOs   ""N)nextlistparents)ps    r   r	   zGitRepo._find_root3   s'     Od199o 5OQUVVr   c                   | dz  }|j                         r|S |j                         re|j                  d      j                         }|j	                  d      r4| |j                  dd      d   j                         z  j                         S y)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   zGitRepo._gitdir8   sx     6M88:H99;8,224A||I&qwwsAq17799BBDDr   c                j    |r0|j                         r |j                  d      j                         S dS )zRead and strip file if exists.r   r   N)r   r%   r&   )r   r   s     r   _readzGitRepo._readD   s+    78QXXZq{{({+113QTQr   c                b    | j                  | j                  r| j                  dz        S d      S )zHEAD file contents.HEADN)r-   r   r   s    r   headzGitRepo.headH   s*     zz$++$++.HH4HHr   c                   | j                   |z  }| j                  |      }|r|S | j                   dz  }|j                         r|j                         j	                         ng }|j                         }|D ]H  }|dd dv sd|vr|j                  dd      \  }}	|	j                         |k(  s8|j                         c S  y)z%Commit for ref (handles packed-refs).zpacked-refsNr"   )   #   ^    )	r   r-   r   
read_bytes
splitlinesencoder(   r&   decode)
r   refrfspfbtgtlineshanames
             r   _ref_commitzGitRepo._ref_commitM   s    [[3JJrNH[[=(,.IIKBMMO&&(Rjjl 	$DBQx<'4t+;

4+ICzz|s"zz|#	$ r   c                    | j                   duS )zTrue if inside a git repo.N)r   r0   s    r   is_repozGitRepo.is_repo^   s     {{$&&r   c                    | j                   r'| j                  r| j                  j                  d      sy| j                  dd j                         }|j                  d      r|t	        d      d S |S )zCurrent branch or None.ref: N   zrefs/heads/)rE   r1   r'   r&   len)r   r:   s     r   branchzGitRepo.branchc   s`     ||499DII4H4H4Qiim!!#,/NN=,Is3}%'(RsRr   c                    | j                   r| j                  sy| j                  j                  d      r,| j                  | j                  dd j	                               S | j                  S )zCurrent commit SHA or None.NrG   rH   )rE   r1   r'   rC   r&   r0   s    r   commitzGitRepo.commitk   sU     ||499:>)):N:Nw:Wt		!" 3 3 56f]a]f]ffr   c                   | j                   sy| j                  dz  }d\  }}| j                  |      xs dj                         D ]  }|j	                         }|j                  d      r"|j                  d      r|j                         }F|j                         j                  d      sf|dk(  sl|j                  d	d
      d
   j	                         } |S  |S )zOrigin URL or None.Nconfig)NN []zurl =z[remote "origin"]=r"   )	rE   r   r-   r7   r&   r'   endswithlowerr(   )r   cfgremoteurlr<   r+   s         r   originzGitRepo.originr   s     ||kkH$ **S/'R335 	A	A||C QZZ_%%g.6=P3Pggc1oa(..0
	 
r   N)r   r   )r   r   returnPath | None)r
   r   rY   rZ   )r   rZ   rY   
str | None)rY   r[   )r:   strrY   r[   )rY   bool)__name__
__module____qualname____doc__r   __file__r)   r   staticmethodr	   r   r-   r   r1   rC   propertyrE   rJ   rL   rX    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   r^   timer*   rE   perf_countert0printr
   rJ   rL   rX   dtre   r   r   <module>ro      s    # % w wt z	AyyT affXYqxxj	!((9QXXJWXd!B&$.*2c(#67	 	 r   