o
    Uh.                    @   s  d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZ ddlmZmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZmZmZmZ ddlmZm Z m!Z!m"Z"m#Z#m$Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, ddl-m.Z.m/Z/m0Z0m1Z1m2Z2 ddl3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z; ddl<m=Z=m>Z>m?Z?m@Z@mAZAmBZB ddlCmDZDmEZE ddlFmGZG ddlHmIZImJZJ ddlKmLZLmMZMmNZNmOZOmPZP ddlQmRZRmSZSmTZT ddlUmVZVmWZWmXZXmYZY ddlUmZZ[ ddl\m]Z]m^Z^m_Z_ e	ddZ`G dd  d eZaebejcd!dpea Zdebejed!dp"ea Zfd"ZgG d#d$ d$ehZiG d%d& d&eiZjG d'd( d(eiZkG d)d* d*eiZld+d, Zmd-d. Znd/d0 Zoed1d2 Zpd3d4 Zqegfd5d6ZrG d7d8 d8eiZsdd:d;Ztdedeff	dd<d=Zddd?d@ZZdddBdCZudddDdEZv	>							A	AddFdGZwddHdIZxddAddJdKeey fdLdMZzddAdefddNdddddfdNee{ dOee| dPeee{e}f  dQee dRee| f
dSdTZ~ddUdVZdWdX ZdddYdZZddd[d\ZeZegfd]d^Zegfd_d`ZejcfddadbZejcfddcddZejcfddedfZejcfddgdhZejcfddidjZejcfddkdlZdmdn Zdodp Zd>dejcddAdAf	ddqdrZd>dejcegf	ddsdtZedfddudvZejcfddwdxZdye{d9e{fdzd{Zddd|d}Zdd~dZdd ZdddAddddAegfdee{e}f deee{e}f  deee{e}f  dee{e}f deyde{d9dfddZejcfddZdddZd dddZ	ddeSdeee{e}f  d9eee{ e{f fddZddedefdAf	dddZddedefddAddf	dddZdddZdddZ	dddZdd ZddddZddddZdd9e|fddZdd9e|fddZdee{e}f d9eOfddZdee{e}f d9eOfddZdddZddddZdd Zdd Zdd ZdejcefdddAdAdAfddZ	>	ddeeSe{f deee{e}f  d9eee}e}e}f  fddZddQee fddZdddZ			d	dddĄZdejcdAdAf	dddǄZdee}e{f dyee}e{f d9dfddɄZdeSdee}e{f d9dfdd˄Zddd̈́ZddddτZdde{de}d9dfddӄZddՄ Zddee}e{f deyd9dfdd؄Z	d	deydeeydf fddۄZdd݄ Zddd߄ZdddZdd Zdd Zdd ZdddZdddZdddZdd Zdd ZŐdddZƐdddZdd ZdS (
  a  Simple wrapper that provides porcelain-like functions on top of Dulwich.

Currently implemented:
 * archive
 * add
 * branch{_create,_delete,_list}
 * check-ignore
 * checkout_branch
 * clone
 * cone mode{_init, _set, _add}
 * commit
 * commit-tree
 * daemon
 * describe
 * diff-tree
 * fetch
 * for-each-ref
 * init
 * ls-files
 * ls-remote
 * ls-tree
 * pull
 * push
 * rm
 * remote{_add}
 * receive-pack
 * reset
 * sparse_checkout
 * submodule_add
 * submodule_init
 * submodule_list
 * rev-list
 * tag{_create,_delete,_list}
 * upload-pack
 * update-server-info
 * status
 * symbolic-ref

These functions are meant to behave similarly to the git subcommands.
Differences in behaviour are considered bugs.

Note: one of the consequences of this is that paths tend to be
interpreted relative to the current working directory rather than relative
to the repository root.

Functions should generally accept both unicode strings and bytestrings
    N)
namedtuple)closingcontextmanager)BytesIO	RawIOBase)Path)OptionalUnion   )
tar_stream)get_transport_and_path)Config
ConfigFileStackedConfigread_submodules)
CHANGE_ADDCHANGE_COPYCHANGE_DELETECHANGE_MODIFYCHANGE_RENAMERENAME_CHANGE_TYPES)SendPackError)ensure_dir_exists)can_fast_forward)IgnoreFilterManager)_fs_to_tree_pathblob_from_path_and_statbuild_file_from_blobget_unstaged_changesindex_entry_from_stat)iter_tree_contentstree_lookup_path)CommitTagformat_timezoneparse_timezonepretty_format_tree_entry)parse_commitparse_object	parse_refparse_reftuples
parse_treeto_bytes)write_pack_from_containerwrite_pack_index)write_tree_diff)ZERO_SHAProtocol)LOCAL_BRANCH_PREFIXLOCAL_REMOTE_PREFIXLOCAL_TAG_PREFIXRef_import_remote_refs)BaseRepoRepoget_user_identity)FileSystemBackendReceivePackHandlerTCPGitServerUploadPackHandler)update_server_info)SparseCheckoutConflictErrorapply_included_pathsdetermine_included_paths	GitStatuszstaged unstaged untrackedc                   @   s>   e Zd ZdZddddZdefddZdd	d
ZdddZdS )
NoneStreamz;Fallback if stdout or stderr are unavailable, does nothing.returnNc                 C      d S N )selfsizerH   rH   e/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/dulwich/porcelain.pyread      zNoneStream.readc                 C   s   dS )N    rH   )rI   rH   rH   rK   readall   rM   zNoneStream.readallc                 C   rF   rG   rH   rI   brH   rH   rK   readinto   rM   zNoneStream.readintoc                 C   rF   rG   rH   rP   rH   rH   rK   write   rM   zNoneStream.write)rD   rE   N)	__name__
__module____qualname____doc__rL   bytesrO   rR   rS   rH   rH   rH   rK   rC      s    
rC   bufferzutf-8c                       s"   e Zd ZdZd fddZ  ZS )ErrorzPorcelain-based error.rE   Nc                    s   t  | d S rG   )super__init__)rI   msg	__class__rH   rK   r]      s   zError.__init__rT   )rU   rV   rW   rX   r]   __classcell__rH   rH   r_   rK   r[      s    r[   c                   @      e Zd ZdZdS )RemoteExistsz&Raised when the remote already exists.NrU   rV   rW   rX   rH   rH   rH   rK   rc          rc   c                   @   rb   )TimezoneFormatErrorzBRaised when the timezone cannot be determined from a given string.Nrd   rH   rH   rH   rK   rf      re   rf   c                   @   rb   )CheckoutErrorz.Indicates that a checkout cannot be performed.Nrd   rH   rH   rH   rK   rg      re   rg   c                 C   s   ddl }|d}||| r*zt| dd t}|d W S  ty)   Y nw ddl}|j	
| }|r:|d S |d}||| }d}|ro| \}	}
}|t|
d 7 }|rb|t|d	 7 }|	d
krk| }|S |}|S t| )a  Parse given string and attempt to return a timezone offset.

    Different formats are considered in the following order:

     - Git internal format: <unix timestamp> <timezone offset>
     - RFC 2822: e.g. Mon, 20 Nov 1995 19:12:08 -0500
     - ISO 8601: e.g. 1995-11-20T19:12:08-0500

    Args:
      tz_str: datetime string
    Returns: Timezone offset as integer
    Raises:
      TimezoneFormatError: if timezone information cannot be extracted
    r   Nz^[0-9]+ [+-][0-9]{,4}$ r
   	   z5[0-9] ?([+-])([0-9]{2})(?::(?=[0-9]{2}))?([0-9]{2})?$i  <   -)recompilematchr%   splitencodeDEFAULT_ENCODING
ValueErroremail.utilsutilsparsedate_tzsearchgroupsintrf   )tz_strrl   internal_format_patterntz_internalemailrfc_2822iso_8601_patternrn   
total_secssignhoursminutesrH   rH   rK   parse_timezone_format   s8   

r   c                  C   sX   t  j} tjdrttjd }n| }tjdr&ttjd }||fS | }||fS )zRetrieve local timezone as described in
    https://raw.githubusercontent.com/git/git/v2.3.0/Documentation/date-formats.txt
    Returns: A tuple containing author timezone, committer timezone.
    GIT_AUTHOR_DATEGIT_COMMITTER_DATE)time	localtime	tm_gmtoffosenvirongetr   )local_timezoneauthor_timezonecommit_timezonerH   rH   rK   get_user_timezones   s   
r   c                 C   s   t | tr| S t| S )zEOpen an argument that can be a repository or a path for a repository.)
isinstancer7   r8   path_or_reporH   rH   rK   	open_repo	  s   
r   c                 c   s    | V  dS )zBContext manager that has the same api as closing but does nothing.NrH   )objrH   rH   rK   _noop_context_manager  s   
r   c                 C   s   t | tr	t| S tt| S )zOpen an argument that can be a repository or a path for a repository.
    returns a context manager that will close the repo on exit if the argument
    is a path, else does nothing if the argument is a repo.
    )r   r7   r   r   r8   r   rH   rH   rK   open_repo_closing  s   
r   c                 C   s   t jdkrtj|}t|}| }t jdkrtj| } t|  } z|| }W n tyG   |	 rD|j
 }||j | }n Y nw t jdkrZt|tjjd|S t|S )a  Convert a path to a path usable in an index, e.g. bytes and relative to
    the repository root.

    Args:
      repopath: Repository path, absolute or relative to the cwd
      path: A path, absolute or relative to the cwd
    Returns: A path formatted for use in e.g. an index
    win32/)sysplatformr   pathabspathr   resolverelative_torr   
is_symlinkparentnamestrreplaceseprp   rY   )repopathr   tree_encodingresolved_pathrelpathr   rH   rH   rK   path_to_tree_path   s&   



r   c                   @   s   e Zd ZdZdddZdS )DivergedBranchesz8Branches have diverged and fast-forward is not possible.rE   Nc                 C   s   || _ || _d S rG   )current_shanew_sha)rI   r   r   rH   rH   rK   r]   L  s   
zDivergedBranches.__init__rT   )rU   rV   rW   rX   r]   rH   rH   rH   rK   r   I  s    r   rE   c                 C   s:   zt | ||}W n ty   d}Y nw |st||dS )zCheck if updating to a sha can be done with fast forwarding.

    Args:
      repo: Repository object
      current_sha: Current head sha
      new_sha: New head sha
    FN)r   KeyErrorr   )repor   r   canrH   rH   rK   check_divergedQ  s   
r   c                 C   sl   |du rd}t | "}t||}t|j|j|j |jD ]}|| qW d   dS 1 s/w   Y  dS )zCreate an archive.

    Args:
      repo: Path of repository for which to generate an archive.
      committish: Commit SHA1 or ref to use
      outstream: Output stream (defaults to stdout)
      errstream: Error stream (defaults to stderr)
    NHEAD)r   r'   r   object_storetreecommit_timerS   )r   
committish	outstream	errstreamrepo_objcchunkrH   rH   rK   archivea  s   

"r   .c                 C   s6   t | }t| W d   dS 1 sw   Y  dS )z]Update server info files for a repository.

    Args:
      repo: path to the repository
    N)r   server_update_server_infor   rrH   rH   rK   r>   y  s   

"r>   Fc                 C   sf   t | %}t|}|s||j vrtd| d|jd| W d   dS 1 s,w   Y  dS )zSet git symbolic ref into HEAD.

    Args:
      repo: path to the repository
      ref_name: short name of the new ref
      force: force settings without checking if it exists in refs/heads
    zfatal: ref `z` is not a ref   HEADN)r   _make_branch_refrefskeysr[   set_symbolic_ref)r   ref_nameforcer   ref_pathrH   rH   rK   symbolic_ref  s   
"r   c                    sR   t | }|j fddD }| W d    d S 1 s"w   Y  d S )Nc                    s,   i | ]} s| tr|d kr|| qS r   )
startswithr4   ).0refallr   rH   rK   
<dictcomp>  s    zpack_refs.<locals>.<dictcomp>)r   r   add_packed_refs)r   r   r   packed_refsrH   r   rK   	pack_refs  s   
"r   c	                 C   s   t |ddr||pt}t |ddr||pt}t |ddr'||p%t}t }	|du r2|	d }|du r:|	d }t| }
|
j|||||||t|ttfrQ|nddW  d   S 1 s_w   Y  dS )a-  Create a new commit.

    Args:
      repo: Path to repository
      message: Optional commit message
      author: Optional author name and email
      author_timezone: Author timestamp timezone
      committer: Optional committer name and email
      commit_timezone: Commit timestamp timezone
      no_verify: Skip pre-commit and commit-msg hooks
      signoff: GPG Sign the commit (bool, defaults to False,
        pass True to use default GPG key,
        pass a str containing Key ID to use a specific GPG key)
    Returns: SHA1 of the new commit
    rp   Nr   r
   )messageauthorr   	committerr   encoding	no_verifyr   )	getattrrp   rq   r   r   	do_commitr   r   bool)r   r   r   r   r   r   r   r   signoffr   r   rH   rH   rK   commit  s.   
$r   c                 C   s>   t | }|j||||dW  d   S 1 sw   Y  dS )zCreate a new commit object.

    Args:
      repo: Path to repository
      tree: An existing tree object
      author: Optional author name and email
      committer: Optional committer name and email
    )r   r   r   r   N)r   r   )r   r   r   r   r   r   rH   rH   rK   commit_tree  s
   
	$r   )baresymlinksr   c                C   s2   t j| st |  |rt| S tj| |dS )zCreate a new git repository.

    Args:
      path: Path to repository.
      bare: Whether to create a bare repository.
      symlinks: Whether to create actual symlinks (defaults to autodetect)
    Returns: A Repo instance
    )r   )r   r   existsmkdirr8   	init_bareinit)r   r   r   rH   rH   rK   r     s
   	

r   origindepthbranchconfigprotocol_versionc                 K   s   |durddl }|jdtdd |	du rt }	|du r| }|r'|r'td|du r2| dd }t|tr<|	t
}tj| }t| fd	|	i|\}}|
rV|
	d
}
|j||||||||j||
|dS )aX  Clone a local or remote git repository.

    Args:
      source: Path or URL for source repository
      target: Path to target repository (optional)
      bare: Whether or not to create a bare repository
      checkout: Whether or not to check-out HEAD after cloning
      errstream: Optional stream to write progress to
      outstream: Optional stream to write progress to (deprecated)
      origin: Name of remote from the repository used to clone
      depth: Depth to fetch at
      branch: Optional branch or tag to be used as HEAD in the new repository
        instead of the cloned repository's HEAD.
      config: Configuration to use
      refspecs: refspecs to fetch. Can be a bytestring, a string, or a list of
        bytestring/string.
      filter_spec: A git-rev-list-style object filter spec, as an ASCII string.
        Only used if the server supports the Git protocol-v2 'filter'
        feature, and ignored otherwise.
      protocol_version: desired Git protocol version. By default the highest
        mutually supported protocol version will be used.
    Returns: The new repository
    Nr   z7outstream= has been deprecated in favour of errstream=.   )
stacklevelz"checkout and bare are incompatibler   rD   r   ascii)	r   r   r   checkoutr   progressr   filter_specr   )warningswarnDeprecationWarningr   defaultr[   ro   r   r   rp   rq   r   r   r   r   clonerS   )sourcetargetr   r   r   r   r   r   r   r   r   r   kwargsr   r   clientr   rH   rH   rK   r     sD   &


r   c           
      C   s   t  }t| i}t|j }t|}|s*ttt	tt
  t	|| }g }t|ts4|g}|D ]*}t|}t	| |}	| rPt
j|	d}	||	r[||	 q6||	 q6|| W d   ||fS 1 ssw   Y  ||fS )a  Add files to the staging area.

    Args:
      repo: Repository for the files
      paths: Paths to add.  No value passed stages all modified files.
    Returns: Tuple with set of added files and ignored files

    If the repository contains ignored directories, the returned set will
    contain the path to an ignored directory (with trailing slash). Individual
    files within ignored directories will not be returned.
     N)setr   r   r   r   r   	from_repolistget_untracked_pathsr   r   getcwd
open_indexr   r   is_dirjoin
is_ignoredaddappendstage)
r   pathsignoredr   	repo_pathignore_managerrelpathspr   r   rH   rH   rK   r  F  s:   





r  c                 C   s2   t j|t jj }t j| t jj }||S )zCheck whether subdir is parentdir or a subdir of parentdir.

    If parentdir or subdir is a relative path, it will be disamgibuated
    relative to the pwd.
    )r   r   realpathr   r   )subdir	parentdirparentdir_abs
subdir_absrH   rH   rK   
_is_subdiro  s   
r  c                 C   s  |du rt  }t| k}t||jstd| }|ddd | }t	
|}t||j}tt|D ]7\}}|rNtt |dk}	|	rMt | q7t|j|}
|
|v }t j||j}||}|sn|snt | q7W d   dS 1 szw   Y  dS )a  Remove any untracked files from the target directory recursively.

    Equivalent to running ``git clean -fd`` in target_dir.

    Args:
      repo: Repository where the files may be tracked
      target_dir: Directory to clean - current directory if None
    Nz,target_dir must be in the repo's working dir)s   cleans   requireForceTr   )r   r   r   r  r   r[   get_config_stackget_booleanr   r   r   _walk_working_dir_pathsreversedr   lenlistdirrmdirr   r   r  remove)r   
target_dirr   r   indexr  paths_in_wdapr   is_emptyip
is_trackedrpr  rH   rH   rK   clean{  s2   	




"r!  c                 C   sd  t | }| }|D ]}ttj|}t|j|}z|| j}W n ty7 }	 zt	| d|	d}	~	ww |szt
|}
W n	 tyJ   Y nNw zt||
}W n	 ty[   Y n=w zt|j||  j|d }W n tyw   d}Y nw |j|kr||krt	d| ||krt	d| t| ||= q|  W d   dS 1 sw   Y  dS )zuRemove files from the staging area.

    Args:
      repo: Repository for the files
      paths: Paths to remove
    z did not match any filesNr
   z?file has staged content differing from both the file and head: zfile has staged changes: )r   r   r   fsencoder   r   r   shar   r[   lstatOSErrorr   r!   __getitem__headr   idr  rS   )r   r  cachedr   r  r
  	full_path	tree_path	index_shaexcstblobcommitted_sharH   rH   rK   r    sV   


"r  c                 C   s$   | j r
| j d}n|}||dS )Nr   r   )r   decoder   contentsdefault_encodingr   rH   rH   rK   commit_decode  s   r5  c                 C   s"   | j r
| j d}n|}||S )Nr   )r   r1  rp   r2  rH   rH   rK   commit_encode  s   
r6  c              	   C   s  | d | d| jd d  t| jdkr/| dddd	 | jdd
 D  d  | d|| j d  | j| jkrM| d|| j d  t	| j
| j }td|}t| jd}| d| d | d  | d | || jd  | d d
S )zWrite a human-readable commit log entry.

    Args:
      commit: A `Commit` object
      outstream: A stream file to write to
    z3--------------------------------------------------
zcommit: r   
r
   zmerge: z...c                 S   s   g | ]}| d qS )r   r1  r   r   rH   rH   rK   
<listcomp>      z print_commit.<locals>.<listcomp>NzAuthor: zCommitter: %a %b %d %Y %H:%M:%SDate:   rh   )rS   r(  r1  r  parentsr   r   r   r   gmtimeauthor_timer   strftimer$   r   )r   r1  r   
time_tupletime_strtimezone_strrH   rH   rK   print_commit  s(   

rE  c                 C   s   | d|| j d  t| j| j }td|}t| jd}| d| d | d  | d | || j	 | d dS )zWrite a human-readable tag.

    Args:
      tag: A `Tag` object
      decode: Function for decoding bytes to unicode string
      outstream: A stream to write to
    zTagger: r7  r<  r   r=  rh   N)
rS   taggerr   r?  tag_timetag_timezonerA  r$   r1  r   )tagr1  r   rB  rC  rD  rH   rH   rK   	print_tag  s   
rJ  c                 C   s   | ||j dS )zWrite a blob to a stream.

    Args:
      repo: A `Repo` object
      blob: A `Blob` object
      decode: Function for decoding bytes to unicode string
      outstream: A stream file to write to
    N)rS   data)r   r/  r1  r   rH   rH   rK   	show_blob  s   	rL  c                 C   sh   t |||d |jr| |jd  }|j}nd}t }t|| j||j |d |t||	  dS )zShow a commit to a stream.

    Args:
      repo: A `Repo` object
      commit: A `Commit` object
      decode: Function for decoding bytes to unicode string
      outstream: Stream to write to
    )r1  r   r   N)
rE  r>  r   r   r/   r   seekrS   r5  getvalue)r   r   r1  r   parent_commit	base_tree
diffstreamrH   rH   rK   show_commit&  s   	
rR  c                 C   s    |D ]}| ||d  qdS )zPrint a tree to a stream.

    Args:
      repo: A `Repo` object
      tree: A `Tree` object
      decode: Function for decoding bytes to unicode string
      outstream: Stream to write to
    r7  N)rS   )r   r   r1  r   nrH   rH   rK   	show_tree;  s   	rT  c                 C   s(   t ||| t| | |jd  || dS )zPrint a tag to a stream.

    Args:
      repo: A `Repo` object
      tag: A `Tag` object
      decode: Function for decoding bytes to unicode string
      outstream: Stream to write to
    r
   N)rJ  show_objectobject)r   rI  r1  r   rH   rH   rK   show_tagH  s   	rW  c                 C   s   t tttd|j | |||S )N)s   trees   blobs   commits   tag)rT  rL  rR  rW  	type_name)r   r   r1  r   rH   rH   rK   rU  U  s   rU  c                 c   s    | D ]\}|sqt |tr|d }|jtkr|jj}d}d}n8|jtkr-|jj}d}d}n*|jtkr;|jj}d}d}n|jt	v rW|jj}|jj}|jt
krPd}n|jtkrWd}d|||f V  qd	S )
z5Print a simple status summary, listing changed files.r   r   ADMRCz%-8s%-20s%-20sN)r   r   typer   newr   r   oldr   r   r   r   )changeschangepath1path2kindrH   rH   rK   print_name_status^  s6   






rf  c           	         s   t | 3}|j|||d}|D ]  fdd}t j|| |r.|dd t  D  qW d   dS 1 s:w   Y  dS )aQ  Write commit logs.

    Args:
      repo: Path to repository
      paths: Optional set of specific paths to print entries for
      outstream: Stream to write log output to
      reverse: Reverse order in which entries are printed
      name_status: Print name status
      max_entries: Optional maximum number of entries to display
    )max_entriesr  reversec                    s   t  j| S rG   )r5  r   xentryrH   rK   r1       zlog.<locals>.decodec                 S   s   g | ]}|d  qS )r7  rH   )r   linerH   rH   rK   r:        zlog.<locals>.<listcomp>N)r   
get_walkerrE  r   
writelinesrf  ra  )	r   r  r   rg  rh  name_statusr   walkerr1  rH   rk  rK   log{  s   
"rt  c                    s   |du rdg}t |ts|g}t| -}|D ]!}t||t tr* fdd}n fdd}t||| qW d   dS 1 sCw   Y  dS )zPrint the changes in a commit.

    Args:
      repo: Path to repository
      objects: Objects to show (defaults to [HEAD])
      outstream: Stream to write to
      default_encoding: Default encoding to use if none is set in the
        commit
    Nr   c                    s   t |  S rG   )r5  ri  r4  orH   rK   r1    rm  zshow.<locals>.decodec                    s
   |   S rG   r8  ri  )r4  rH   rK   r1    s   
)r   r   r   r(   r"   rU  )r   objectsr   r4  r   	objectishr1  rH   ru  rK   show  s   



"ry  c                 C   s>   t | }t||j|| W d   dS 1 sw   Y  dS )zCompares the content and mode of blobs found via two tree objects.

    Args:
      repo: Path to repository
      old_tree: Id of old tree
      new_tree: Id of new tree
      outstream: Stream to write to
    N)r   r/   r   )r   old_treenew_treer   r   rH   rH   rK   	diff_tree  s   
	"r|  c                    s`   t | "  j fdd|D dD ]}||jjd  qW d   dS 1 s)w   Y  dS )zLists commit objects in reverse chronological order.

    Args:
      repo: Path to repository
      commits: Commits over which to iterate
      outstream: Stream to write to
    c                    s   g | ]} | j qS rH   )r(  r9  r   rH   rK   r:    r;  zrev_list.<locals>.<listcomp>)include   
N)r   rp  rS   r   r(  )r   commitsr   rl  rH   r}  rK   rev_list  s
   
"r  urlc                 C   s*   |  ddd }|dr|d d }|S )Nr   r
   rD   .git)rsplitendswith)r  r   rH   rH   rK   _canonical_part  s   
r  c              	   C   s   t | R}|du rtjt||j}|du r|}tj|jd}zt|}W n ty7   t }||_Y nw |	d|fd| |	d|fd| |
  W d   dS 1 sYw   Y  dS )zAdd a new submodule.

    Args:
      repo: Path to repository
      url: URL of repository to add as submodule
      path: Path where submodule should live
    N.gitmodules	submoduler  r   )r   r   r   r   r  r   r   	from_pathFileNotFoundErrorr   write_to_path)r   r  r   r   r   gitmodules_pathr   rH   rH   rK   submodule_add  s    


"r  c                 C   s   t | 5}| }tj|jd}t|D ]\}}}|d|fdd |d|fd| q|  W d   dS 1 s<w   Y  dS )zEInitialize submodules.

    Args:
      repo: Path to repository
    r  s	   submodules   activeT   urlN)r   
get_configr   r   r   r   r   r  )r   r   r   r  r   r  r   rH   rH   rK   submodule_init  s   

"r  c                 c   sl    ddl m} t| !}||j||  jD ]\}}||tfV  qW d   dS 1 s/w   Y  dS )z?List submodules.

    Args:
      repo: Path to repository
    r
   )iter_cached_submodulesN)r  r  r   r   r'  r   r1  rq   )r   r  r   r   r#  rH   rH   rK   submodule_list	  s   
"r  r   rI  r   r   rx  r   r   c
                 C   sl  t | }
t|
|}t|tr||	}|rt }|du r$t|
 }nt|tr/||	}nt|ts6J ||_	t|trD||	}nt|trJnd}|d|	 |_
||_t||jf|_|du ritt }||_|du rvt d }n	t|trt|}||_|r|t|tr|nd |
j| |j}n|j}||
jt|< W d   dS 1 sw   Y  dS )aJ  Creates a tag in git via dulwich calls.

    Args:
      repo: Path to repository
      tag: tag string
      author: tag author (optional, if annotated is set)
      message: tag message (optional)
      annotated: whether to create an annotated tag
      objectish: object the tag should point at, defaults to HEAD
      tag_time: Optional time for annotated tag
      tag_timezone: Optional timezone for annotated tag
      sign: GPG Sign the tag (bool, defaults to False,
        pass True to use default GPG key,
        pass a str containing Key ID to use a specific GPG key)
    NrN   r7  r
   )r   r(   r   r   rp   r#   r9   r  rY   rF  r   r   r^  r(  rV  rx   r   rG  r   r%   rH  r   r   
add_objectr   _make_tag_ref)r   rI  r   r   	annotatedrx  rG  rH  r   r   r   rV  tag_objtag_idrH   rH   rK   
tag_create  sF   







"r  c                 C   s@   t | }t|jd}|W  d   S 1 sw   Y  dS )zfList all tags.

    Args:
      repo: Path to repository
      outstream: Stream to write tags to
    s	   refs/tagsN)r   sortedr   as_dict)r   r   r   tagsrH   rH   rK   tag_list]  s   
$r  c                 C   st   t | ,}t|tr|g}nt|tr|}ntd||D ]}|jt|= qW d   dS 1 s3w   Y  dS )z^Remove a tag.

    Args:
      repo: Path to repository
      name: Name of tag to remove
    zUnexpected tag name type N)r   r   rY   r   r[   r   r  r   r   r   namesrH   rH   rK   
tag_deletei  s   


"r  c                 C   sT   |dkrt dt| }t||}||j W d   dS 1 s#w   Y  dS )zReset current HEAD to the specified state.

    Args:
      repo: Path to repository
      mode: Mode ("hard", "soft", "mixed")
      treeish: Treeish to reset to
    hardz)hard is the only mode currently supportedN)r[   r   r+   reset_indexr(  )r   modetreeishr   r   rH   rH   rK   reset{  s   

"r  r   remote_locationc                 C   sl   |   }|d u rt| }t|tr| }n|}d|f}d }||r.| }||d}nd }|| fS )N   remoter  )r  get_branch_remoter   r   rp   has_sectionr1  r   )r   r  r   encoded_locationsectionremote_namerH   rH   rK   get_remote_repo  s   


r  c                    sz  t | du rtgt|\}}t|fd i|\}}	g i  fdd}
t|ddp8t}||	}z|j|	|
j	|j
d}W n tyg } ztd| d |jd	   |d}~ww |
d
|| d  |jpxi  D ]\}}|dur|
d|||f  q{|
d|  q{|durtj| W d   dS W d   dS 1 sw   Y  dS )a2  Remote push with dulwich via dulwich.client.

    Args:
      repo: Path to repository
      remote_location: Location of the remote
      refspecs: Refs to push to remote
      outstream: A stream file to write output
      errstream: A stream file to write errors
      force: Force overwriting refs
    Nr   c                    s    tj|  d i }D ]E\}}}|d u r"t||< d |< qzj| }W n ty> } z	td| d|d }~ww |sM|| v rMt| | | |||< ||< q|S )Nr   zNo valid ref z in local repository)extendr*   r   r0   r   r[   r   )r   new_refslhrh	force_reflocalshar-  r   r   refspecsremote_changed_refsselected_refsrH   rK   update_refs  s"   

zpush.<locals>.update_refsr   )generate_pack_datar   zPush to z failed -> r   s   Push to s    successful.
s   Push of ref %s failed: %s
s   Ref %s updated
)r   active_branchr  r   r  r   rq   get_url	send_packr  rS   r   r[   argsr1  rp   
ref_statusitemsr6   r   )r   r  r  r   r   r   r   r  r   r   r  err_encodingresultr-  r   errorrH   r  rK   push  sZ   




:"r  Tc	                    st  t | t|\}
}g du rdg fdd}t|fd i|	\}}|r3|d}|j||j|||d}D ]:\}}}|ss|jv rsztj	|d |j|  W n t
yr } z|ri td	|d}~ww |j| j|< qAr|jd
 d  d< d j}j|d |
durtj|
|j W d   dS W d   dS 1 sw   Y  dS )a  Pull from remote via dulwich.client.

    Args:
      repo: Path to repository
      remote_location: Location of the remote
      refspecs: refspecs to fetch. Can be a bytestring, a string, or a list of
        bytestring/string.
      outstream: A stream file to write to output
      errstream: A stream file to write to errors
      filter_spec: A git-rev-list-style object filter spec, as an ASCII string.
        Only used if the server supports the Git protocol-v2 'filter'
        feature, and ignored otherwise.
      protocol_version: desired Git protocol version. By default the highest
        mutually supported protocol version will be used
    Nr   c                    s,    t jd  fddD S )Nr  c                    s(   g | ]\}}}|  j vr| qS rH   )r   )r   r  r  r  )r   remote_refsrH   rK   r:    s
    z1pull.<locals>.determine_wants.<locals>.<listcomp>)r  r*   r   )r  r  r   r   r   r  r  )r  rK   determine_wants  s   zpull.<locals>.determine_wantsr   r   )r   r  r   r   r
   zmerge is not yet supportedr   )r   )r   r  r   r  rp   fetchrS   r   r   followr   NotImplementedErrorr   r  r6   )r   r  r  r   r   fast_forwardr   r   r   r   r  r  r   r   fetch_resultr  r  r  r-  r   rH   r  rK   pull  sV   



"

/"r  r   c                 C   s   t | C}t|}| }| }|j}tt||j|}t|j|j|| |d}	t	j
dkr6dd |	D }
nt|	}
t|||
W  d   S 1 sJw   Y  dS )a0  Returns staged, unstaged, and untracked changes relative to the HEAD.

    Args:
      repo: Path to repository or repository object
      ignored: Whether to include ignored files in untracked
      untracked_files: How to handle untracked files, defaults to "all":
          "no": do not return untracked files
          "all": include all files in untracked directories
        Using untracked_files="no" can be faster than "all" when the worktreee
          contains many untracked files/directories.

    Note: untracked_files="normal" (git's default) is not implemented.

    Returns: GitStatus tuple,
        staged -  dict with lists of staged paths (diff index/HEAD)
        unstaged -  list of unstaged paths (diff index/working-tree)
        untracked - list of untracked, un-ignored & non-.git paths
    )exclude_ignoreduntracked_filesr   c                 S   s   g | ]
}| tjjd qS r   )r   r   r   r   )r   r   rH   rH   rK   r:  h  s    zstatus.<locals>.<listcomp>N)r   get_tree_changesr   get_blob_normalizercheckin_normalizer   r   r   r   r   r   rB   )r   r  r  r   tracked_changesr  
normalizerfilter_callbackunstaged_changesuntracked_pathsuntracked_changesrH   rH   rK   statusD  s(   


$r  c                 c   s    t | D ]F\}}}d|v r|d ||krqd|v r'|d ||kr'q|| kr0|dfV  |D ]}t j||}|dfV  q2|rL||||dd< qdS )a#  Get path, is_dir for files in working dir from frompath.

    Args:
      frompath: Path to begin walk
      basepath: Path to compare to
      prune_dirnames: Optional callback to prune dirnames during os.walk
        dirnames will be set to result of prune_dirnames(dirpath, dirnames)
    r  TFN)r   walkr  r   r   )frompathbasepathprune_dirnamesdirpathdirnames	filenamesfilenamefilepathrH   rH   rK   r  q  s&   	


r  c           
      #   s    |dkr	t d|dvrtd|dkrdS t }t|W d   n1 s+w   Y  g  fdd}t |d	D ]#\}}|sft |}	|	|vrfr^tj	
| sftj	
|V  qCE dH  dS )
aV  Get untracked paths.

    Args:
      frompath: Path to walk
      basepath: Path to compare to
      index: Index to check against
      exclude_ignored: Whether to exclude ignored paths
      untracked_files: How to handle untracked files:
        - "no": return an empty list
        - "all": return all files in untracked directories
        - "normal": Not implemented

    Note: ignored directories will never be walked for performance reasons.
      If exclude_ignored is False, only the path to an ignored directory will
      be yielded, no files inside the directory will be returned
    normalznormal is not yet supported)nor   z(untracked_files must be one of (no, all)r  Nc              	      sz   t t|d ddD ]0}tj| || }tjtj| d}|r:s7tjtj|d ||= q
|S )Nr
   rD   r   )ranger  r   r   r   r   r  r  )r  r  ir   r  r  r  r  r  ignored_dirsrH   rK   r    s   
z+get_untracked_paths.<locals>.prune_dirnames)r  )r  rr   r   r   r   r  r   r  r   r   r   )
r  r  r  r  r  r   r  r  r   r  rH   r  rK   r     s0   

r   c              	   C   s   t | p}| }g g g d}z|d j}W n ty!   d}Y nw ||j|D ]A}|d d s=|d |d d  q)|d d sO|d |d d  q)|d d |d d krg|d |d d  q)td	|W  d   S 1 sww   Y  dS )
zReturn add/delete/modify changes to tree by comparing index to HEAD.

    Args:
      repo: repo path or object
    Returns: dict with lists for each type of change
    )r  deletemodifyr   Nr   r  r
   r  r  zgit mv ops not yet supported)r   r   r   r   changes_from_treer   r  r  )r   r   r  r  tree_idrb  rH   rH   rK   r    s*   
$r  c                 C   s    t | }t|||}|  dS )zRun a daemon serving Git requests over TCP/IP.

    Args:
      path: Path to the directory to serve.
      address: Optional address to listen on (defaults to ::)
      port: Optional port to listen on (defaults to TCP_GIT_PORT)
    N)r:   r<   serve_forever)r   addressportbackendserverrH   rH   rK   daemon  s   	r  c           
      C   sF   ddl m}m}m}m} t| }||}||||||d}	|	  dS )zRun a daemon serving Git requests over HTTP.

    Args:
      path: Path to the directory to serve
      address: Optional address to listen on (defaults to ::)
      port: Optional port to listen on (defaults to 80)
    r
   )WSGIRequestHandlerLoggerWSGIServerLoggermake_servermake_wsgi_chain)handler_classserver_classN)webr  r  r  r  r:   r  )
r   r  r  r  r  r  r  r  appr  rH   rH   rK   
web_daemon  s   r  c                    x    du rt tjdtj |du rt tjdtj}tj| } t| }d fdd}t|j	|}t
|| g|}|  dS )zUpload a pack file after negotiating its contents using smart protocol.

    Args:
      path: Path to the repository
      inf: Input stream to communicate with client
      outf: Output stream to communicate with client
    NrZ   rE   c                         |     d S rG   rS   flushrK  outfrH   rK   send_fn'     
zupload_pack.<locals>.send_fnr   rT   )r   r   stdoutstdinr   r   
expanduserr:   r1   rL   r=   handler   infr  r  r  protohandlerrH   r  rK   upload_pack     r  c                    r  )zReceive a pack file after negotiating its contents using smart protocol.

    Args:
      path: Path to the repository
      inf: Input stream to communicate with client
      outf: Output stream to communicate with client
    NrZ   rE   c                    r  rG   r  r  r  rH   rK   r  A  r  zreceive_pack.<locals>.send_fnr   rT   )r   r   r  r  r   r   r  r:   r1   rL   r;   r	  r
  rH   r  rK   receive_pack2  r  r  r   c                 C      t | tr
| t} t|  S rG   )r   r   rp   rq   r2   r   rH   rH   rK   r   L     

r   c                 C   r  rG   )r   r   rp   rq   r4   r  rH   rH   rK   r  R  r  r  c                 C   sZ   t | }t|tr|}n|g}|D ]}|jt|= qW d   dS 1 s&w   Y  dS )zbDelete a branch.

    Args:
      repo: Path to the repository
      name: Name of the branch
    N)r   r   r   r   r   r  rH   rH   rK   branch_deleteX  s   

"r  c                 C   s   t | G}|du rd}t||}t|}d|t }|r)|jj|d|j|d n|jj||j|ds;t	d| dW d   dS W d   dS 1 sNw   Y  dS )zCreate a branch.

    Args:
      repo: Path to the repository
      name: Name of the new branch
      objectish: Target object to point new branch at (defaults to HEAD)
      force: Force creation of branch, even if it already exists
    Nr   s   branch: Created from )r   zBranch with name z already exists.)
r   r(   r   rp   rq   r   set_if_equalsr(  
add_if_newr[   )r   r   rx  r   r   rV  refnameref_messagerH   rH   rK   branch_createh  s   
	
"r  c                 C   s:   t | }|jjtdW  d   S 1 sw   Y  dS )zEList all branches.

    Args:
      repo: Path to the repository
    baseN)r   r   r   r2   r   rH   rH   rK   branch_list~  s   
$r  c                 C   sb   t | #}|jdd d }|tst||ttd W  d   S 1 s*w   Y  dS )zReturn the active branch in the repository, if any.

    Args:
      repo: Repository to open
    Returns:
      branch name
    Raises:
      KeyError: if the repository does not have a working tree
      IndexError: if HEAD is floating
    r   r   r
   N)r   r   r  r   r2   rr   r  )r   r   
active_refrH   rH   rK   r    s   

$r  c              	   C   s|   t | 0}t|j}| }z
|d|fd}W n ty#   d}Y n	w W d   |S W d   |S 1 s7w   Y  |S )zReturn the active branch's remote name, if any.

    Args:
      repo: Repository to open
    Returns:
      remote name
    Raises:
      KeyError: if the repository does not have a working tree
    s   branchr  s   originN)r   r  r   r  r   r   )r   r   branch_namer   r  rH   rH   rK   r    s    




r  c	              	   K   s   t | K}
t|
|\}}|du rd|t }t|fd|
 i|	\}}|j||
|j|d}|durGt|
j	||j	|||d W d   |S W d   |S 1 sRw   Y  |S )a  Fetch objects from a remote server.

    Args:
      repo: Path to the repository
      remote_location: String identifying a remote server
      outstream: Output stream (defaults to stdout)
      errstream: Error stream (defaults to stderr)
      message: Reflog message (defaults to b"fetch: from <remote_name>")
      depth: Depth to fetch at
      prune: Prune remote removed refs
      prune_tags: Prune reomte removed tags
    Returns:
      Dictionary with refs on the remote
    Ns   fetch: from r   )r   r   )prune
prune_tags)
r   r  rp   rq   r   r  r  rS   r6   r   )r   r  r   r   r   r   r  r   r   r   r   r  r   r   r  rH   rH   rK   r    s8   



r  patternc                    s   t |tr
t|}t|    }W d   n1 sw   Y  |r`i }|d}| D ].\}}d}|d}t|t|krCq/t	||D ]\}	}
t
|
|	}|sV nqH|r]|||< q/|} fddt| dd dD }|S )	zIterate over all refs that match the (optional) pattern.

    Args:
      repo: Path to the repository
      pattern: Optional glob (7) patterns to filter the refs with
    Returns:
      List of bytes tuples with: (sha, object_type, ref_name)
    N   /Fc                    s*   g | ]\}}|d kr|  |j|fqS r   )
get_objectrX  )r   r   r#  r}  rH   rK   r:    s
    z for_each_ref.<locals>.<listcomp>c                 S   s   | d S )Nr   rH   )ref_sharH   rH   rK   <lambda>
  s    zfor_each_ref.<locals>.<lambda>)key)r   r   r   r"  r   get_refsro   r  r  zipfnmatchfnmatchcaser  )r   r!  r   matching_refspattern_partsr   r#  matches	ref_partspatref_partretrH   r}  rK   for_each_ref  s:   






	r2  c                 K   s2   |du rt  }t| fd|i|\}}||S )zList the refs in a remote.

    Args:
      remote: Remote repository location
      config: Configuration to use
    Returns:
      Dictionary with remote refs
    Nr   )r   r   r   r'  )remoter   r   r   	host_pathrH   rH   rK   	ls_remote  s   	
r5  c                 C   s8   t | }|j  W d   dS 1 sw   Y  dS )zRepack loose files in a repository.

    Currently this only packs loose objects.

    Args:
      repo: Path to the repository
    N)r   r   pack_loose_objectsr   rH   rH   rK   repack!  s   
"r7  c           
   	   C   s   t | }t|j|jdd |D |||d\}}	W d   n1 s"w   Y  |dur>tdd | D }t|||	 dS dS )a  Pack objects into a file.

    Args:
      repo: Path to the repository
      object_ids: List of object ids to write
      packf: File-like object to write to
      idxf: File-like object to write to (can be None)
      delta_window_size: Sliding window size for searching for deltas;
                         Set to None for default window size.
      deltify: Whether to deltify objects
      reuse_deltas: Allow reuse of existing deltas while deltifying
    c                 S   s   g | ]}|d fqS rG   rH   )r   oidrH   rH   rK   r:  F  ro  z pack_objects.<locals>.<listcomp>)deltifydelta_window_sizereuse_deltasNc                 S   s"   g | ]\}}||d  |d fqS )r   r
   rH   )r   kvrH   rH   rK   r:  L  s   " )r   r-   rS   r   r  r  r.   )
r   
object_idspackfidxfr:  r9  r;  r   entriesdata_sumrH   rH   rK   pack_objects-  s   
	rC  r   c                    s\   d fdd t | }t||} |j|jd W d   dS 1 s'w   Y  dS )zList contents of a tree.

    Args:
      repo: Path to the repository
      treeish: Tree id to list
      outstream: Output stream (defaults to stdout)
      recursive: Whether to recursively list files
      name_only: Only print item name
    rE   Nc                    sl   | |   D ]-\}}}|rt||}r|d  n	t||| t|r3r3 | || qd S )Nr  )	iteritems	posixpathr   rS   r&   statS_ISDIR)storetreeidr  r   r  r#  	list_tree	name_onlyr   	recursiverH   rK   rK  a  s   zls_tree.<locals>.list_treer   rT   )r   r+   r   r(  )r   r  r   rM  rL  r   r   rH   rJ  rK   ls_treeP  s
   

"rN  c                 C   s   t |ts
|t}t |ts|t}t| %}| }d|f}||r*t|||d| |	  W d   dS 1 s@w   Y  dS )znAdd a remote.

    Args:
      repo: Path to the repository
      name: Remote name
      url: Remote URL
    r  r  N)
r   rY   rp   rq   r   r  r  rc   r   r  )r   r   r  r   r   r  rH   rH   rK   
remote_addq  s   






"rO  c                 C   s`   t |ts
|t}t| }| }d|f}||= |  W d   dS 1 s)w   Y  dS )z[Remove a remote.

    Args:
      repo: Path to the repository
      name: Remote name
    r  N)r   rY   rp   rq   r   r  r  )r   r   r   r   r  rH   rH   rK   remote_remove  s   



"rP  c                 c   s    t | 8}| }t|}|D ]#}|st|j||v rqtj|r,tj||j}|	|r4|V  qW d   dS 1 s@w   Y  dS )zDebug gitignore files.

    Args:
      repo: Path to the repository
      paths: List of paths to check for
      no_index: Don't check index
    Returns: List of ignored files
    N)
r   r   r   r   r   r   r   isabsr   r  )r   r  no_indexr   r  r  r   rH   rH   rK   check_ignore  s   
	

"rS  c                 C   s   t | A}|durt|}nd}|r |j|= t||j|j|< n
|j|t|| |dur=|jd| W d   dS W d   dS 1 sHw   Y  dS )a  Update HEAD to point at a new branch/commit.

    Note that this does not actually update the working tree.

    Args:
      repo: Path to the repository
      detached: Create a detached head
      target: Branch or committish to switch to
      new_branch: New branch to create
    Nr   )r   r   r   r'   r(  r   r)   )r   r   detached
new_branchr   to_setrH   rH   rK   update_head  s   

"rW  	file_pathr   c           
      C   sd   t | |d}t|}|| jj|}tjt| j|}| j|d  }|d }	t	||	||d dS )zReset the file to specific commit or branch.

    Args:
      repo: dulwich Repo object
      file_path: file to reset, relative to the repository path
      target: branch or commit or b'HEAD' to reset
    )r  r
   r   )
symlink_fnN)
r+   r   lookup_pathr   r&  r   r   r   r"  r   )
r   rX  r   rY  r   r+  
file_entryr*  r/  r  rH   rH   rK   
reset_file  s   r\  c                 C   s   d }|dkr		 |S || j jtdv rt| | |S |  }|dd }d|f}||rT||d d}zt| |t	| 
  W n	 tyJ   Y nw t| t|  |S t| |dd |S )	Nr   r  r"  r   r  rN   T)rT  )r   r   r2   rW  r  ro   r  r   r  r3   r1  r[   )r   r   checkout_targetr   r   r  rH   rH   rK   #_update_head_during_checkout_branch  s.   

r^  r   c                 C   s  t |}t| |  }t| |}|r| |j t| | nt| }tt|d d |d d  |d d  |d  }d}|t	|k r|| }z(|
| jj| z|
| jj| |d7 }W n tyn   td|  w W n ty~   || Y nw |t	|k sDt| |}	|	durt| |	}t }
|  }t| j|jD ]8}|
|j |j|v rqtjt| j|j}| j|j }ttj| t||j|}t||j||j< q|  t| j|jD ]}|j|
vr| |jg q|  }| | j|jD ]Q}|d }|d du rP|d }tj| j| }tj!|r't"| tj|}|| jkrPt	t#|dk}|rDt$| tj|}|| jks3q dS )a  Switch branches or restore working tree files.

    The implementation of this function will probably not scale well
    for branches with lots of local changes.
    This is due to the analysis of a diff between branches before any
    changes are applied.

    Args:
      repo: dulwich Repo object
      target: branch name or commit sha to checkout
      force: true or not to force checkout
    r   r  r  r  r
   zLYour local changes to the following files would be overwritten by checkout: N)%r,   r+   r'  r  r(  r^  r  r   r   r  rZ  r   r&  r   rg   r1  popr   r    r  r   r   r   r"  r#  r   dirnamer   r  r   rS   unstager  isfiler  r  r  )r   r   r   current_treetarget_treestatus_reportra  r  rb  r]  
dealt_with
repo_indexrl  r*  r/  r.  path_change	file_namedir_pathr  rH   rH   rK   checkout_branch  s   









rk  conec                 C   s   t | K}|du r| }|du r| }|du rtdn|}|| t|||}z	t|||d W n tyF } zt|j	 |d}~ww W d   dS 1 sRw   Y  dS )a  Perform a sparse checkout in the repository (either 'full' or 'cone mode').

    Perform sparse checkout in either 'cone' (directory-based) mode or
    'full pattern' (.gitignore) mode, depending on the ``cone`` parameter.

    If ``cone`` is ``None``, the mode is inferred from the repository's
    ``core.sparseCheckoutCone`` config setting.

    Steps:
      1) If ``patterns`` is provided, write them to ``.git/info/sparse-checkout``.
      2) Determine which paths in the index are included vs. excluded.
         - If ``cone=True``, use "cone-compatible" directory-based logic.
         - If ``cone=False``, use standard .gitignore-style matching.
      3) Update the index's skip-worktree bits and add/remove files in
         the working tree accordingly.
      4) If ``force=False``, refuse to remove files that have local modifications.

    Args:
      repo: Path to the repository or a Repo object.
      patterns: Optional list of sparse-checkout patterns to write.
      force: Whether to force removal of locally modified files (default False).
      cone: Boolean indicating cone mode (True/False). If None, read from config.

    Returns:
      None
    Nz"No sparse checkout patterns found.r  )
r   infer_cone_modeget_sparse_checkout_patternsr[   set_sparse_checkout_patternsrA   r@   r?   rg   r  )r   patternsr   rl  r   linesincluded_pathsr-  rH   rH   rK   sparse_checkoutJ  s&   

"rs  c                 C   sN   t | }|  ddg}t||ddd W d   dS 1 s w   Y  dS )aq  Initialize a repository to use sparse checkout in 'cone' mode.

    Sets ``core.sparseCheckout`` and ``core.sparseCheckoutCone`` in the config.
    Writes an initial ``.git/info/sparse-checkout`` file that includes only
    top-level files (and excludes all subdirectories), e.g. ``["/*", "!/*/"]``.
    Then performs a sparse checkout to update the working tree accordingly.

    If no directories are specified, then only top-level files are included:
    https://git-scm.com/docs/git-sparse-checkout#_internalscone_mode_handling

    Args:
      repo: Path to the repository or a Repo object.

    Returns:
      None
    /*!/*/Tr   rl  N)r   configure_for_cone_moders  )r   r   rp  rH   rH   rK   cone_mode_init  s
   
"rx  c                 C   sZ   t | }|  |j|d | }t|||dd W d   dS 1 s&w   Y  dS )a  Overwrite the existing 'cone-mode' sparse patterns with a new set of directories.

    Ensures ``core.sparseCheckout`` and ``core.sparseCheckoutCone`` are enabled.
    Writes new patterns so that only the specified directories (and top-level files)
    remain in the working tree, and applies the sparse checkout update.

    Args:
      repo: Path to the repository or a Repo object.
      dirs: List of directory names to include.
      force: Whether to forcibly discard local modifications (default False).

    Returns:
      None
    dirsTrv  N)r   rw  set_cone_mode_patternsrn  rs  )r   rz  r   r   new_patternsrH   rH   rK   cone_mode_set  s   
"r}  c                    s   t | 4}|  ddg  fdd| D }||pg  }|j|d | }t|||dd W d   dS 1 s;w   Y  dS )	a	  Add new directories to the existing 'cone-mode' sparse-checkout patterns.

    Reads the current patterns from ``.git/info/sparse-checkout``, adds pattern
    lines to include the specified directories, and then performs a sparse
    checkout to update the working tree accordingly.

    Args:
      repo: Path to the repository or a Repo object.
      dirs: List of directory names to add to the sparse-checkout.
      force: Whether to forcibly discard local modifications (default False).

    Returns:
      None
    rt  ru  c                    s   g | ]}| vr| d qS r  )strip)r   r/  base_patternsrH   rK   r:    s
    z!cone_mode_add.<locals>.<listcomp>ry  T)rp  r   rl  N)r   rw  rn  r{  rs  )r   rz  r   r   existing_dirs
added_dirsr|  rH   r  rK   cone_mode_add  s   

"r  c              	   C   sv   t | -}ddlm} z|tj|jd}W n ty$   | }Y nw ||W  d   S 1 s4w   Y  dS )zCheck canonical name and email of contact.

    Args:
      repo: Path to the repository
      contact: Contact name and/or email
    Returns: Canonical contact data
    r
   )Mailmapz.mailmapN)	r   mailmapr  r  r   r   r   r  lookup)r   contactr   r  r  rH   rH   rK   check_mailmap  s   

$r  c                 c   s    t | 1}|jD ]$}|j| }z|  W q	 ty- } z||fV  W Y d}~q	d}~ww W d   dS 1 s9w   Y  dS )zsCheck a repository.

    Args:
      repo: A path to the repository
    Returns: Iterator over errors/warnings
    N)r   r   check	Exception)r   r   r#  rv  erH   rH   rK   fsck  s   


"r  c                 C   sR   t | }ddlm} ||}tt| W  d   S 1 s"w   Y  dS )z!List all stashes in a repository.r
   StashN)r   stashr  r   	enumerater   stashesr   r   r  r  rH   rH   rK   
stash_list  s
   

$r  c                 C   L   t | }ddlm} ||}|  W d   dS 1 sw   Y  dS )z Push a new stash onto the stack.r
   r  N)r   r  r  r   r  r  rH   rH   rK   
stash_push  
   


"r  c                 C   r  )zPop a stash from the stack.r
   r  N)r   r  r  r   r_  r  rH   rH   rK   	stash_pop	  r  r  c                 C   sN   t | }ddlm} ||}|| W d   dS 1 s w   Y  dS )zDrop a stash from the stack.r
   r  N)r   r  r  r   drop)r   r  r   r  r  rH   rH   rK   
stash_drop	  s
   

"r  c                 C   s8   t | }t| W  d   S 1 sw   Y  dS )zList all files in an index.N)r   r  r   r   rH   rH   rK   ls_files	  s   

$r  c                 C   s   | ddd S )z"For now, just return 7 characters.r   N   r8  )r   	object_idrH   rH   rK   find_unique_abbrev	  s   r  c              
   C   s  t d|dur|nd}t| }| }i }| D ]E\}}| }||}d|vr,q|dd\}	}
z|j}W n	 tyB   Y qw ||d }t	j	t
|jdd  |jdg||
< qt| d	d
 dd}||  }t|dkr|durd|jd| W  d   S dt|j|j W  d   S d}| }|D ]I}|jjd}|D ]9}
|
d }|
d d }||kr|dkr|    W  d   S d|||jd|     W  d   S q|d7 }qd|jd| W  d   S 1 sw   Y  dS )a  Describe the repository version.

    Args:
      repo: git repository
      abbrev: number of characters of commit to take, default is 7
    Returns: a string description of the current git revision

    Examples: "gabcdefh", "v0.1" or "v0.1-5-gabcdefh".
    r   Nr  r  r   r
      r   c                 S   s   | d d S )Nr
   r   rH   )rI  rH   rH   rK   r%  D	  s    zdescribe.<locals>.<lambda>T)r&  rh  zg{}gz	{}-{}-g{})slicer   r'  r  r1  r#  r  rV  AttributeErrordatetimer   r?  r   r(  r  r'  r  formatr  r   rp  r   )r   abbrevabbrev_slicer   r   r  r&  valuer   _rI  r   sorted_tagslatest_commitcommit_countrs  rl  	commit_idtag_name
tag_commitrH   rH   rK   describe!	  s`   





 #
1
-

&r  c                 C   sx   |du rd}t | (}t||}|j}t|tst||}t|jj||\}}|| W  d   S 1 s5w   Y  dS )zGet an object by path.

    Args:
      repo: A path to the repository
      path: Path to look up
      committish: Commit to look up path in
    Returns: A `ShaFile` object
    Nr   )	r   r'   r   r   rY   r6  r!   r   r&  )r   r   r   r   r   rP  r  r#  rH   rH   rK   get_object_by_pathj	  s   	



$r  c                 C   s<   t | }| |jW  d   S 1 sw   Y  dS )zWrite a tree object from the index.

    Args:
      repo: Repository for which to write tree
    Returns: tree id for the tree that was written
    N)r   r   r   r   r   rH   rH   rK   
write_tree	  s   
$r  rT   )r   )F)	r   NNNNNNFF)NNN)r   N)r   NF)NN)r   rG   )r   Fr   )Fr   )r   NN)NF)NNT)FN)r   N)NFN)rX   r  r)  r   rE  rF  r   r   collectionsr   
contextlibr   r   ior   r   pathlibr   typingr   r	   r   r   r   r   r   r   r   r   r   r|  r   r   r   r   r   r   errorsr   filer   graphr   ignorer   r  r   r   r   r   r   r   r    r!   rw  r"   r#   r$   r%   r&   
objectspecr'   r(   r)   r*   r+   r,   packr-   r.   patchr/   protocolr0   r1   r   r2   r3   r4   r5   r6   r   r7   r8   r9   r  r:   r;   r<   r=   r>   r   sparse_patternsr?   r@   rA   rB   rC   r   r  default_bytes_out_streamstderrdefault_bytes_err_streamrq   r  r[   rc   rf   rg   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rx   rY   r   r  r  r!  r  rmr5  r6  rE  rJ  rL  rR  rT  rW  rU  rf  rt  ry  r  r  r  r  r  r  r  r  r  tupler  r  r  r  r  r   r  r  r  r  r  r   r  r  r  r  r  r  r  r   r2  r5  r7  rC  rN  rO  rP  rS  rW  r\  r^  rk  rs  rx  r}  r  r  r  r  r  r  r  r  r  r  r  r  rH   rH   rH   rK   <module>   s  0  
7

)




3	


T).0	
"
#


	

G


T
O-!;#


/

6

%
&!
 X

5


	
	
		I