
                            d Z ddlmZ ddlmZmZ ddlmZmZ ddl	Z	ddl
Z
ddlm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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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+m,Z, ddl-m.Z. ddl/m0Z0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6m7Z7m8Z8m9Z9m:Z: ddl;m<Z<m=Z= ddl>m?Z? ddl@mAZAmBZB ddlCmDZDmEZEmFZFmGZG ddlHmIZImJZJ ddlKmLZLmMZMmNZNmOZOmPZQ  edd      ZR G d de      ZS eTej                  dd      xs  eS       ZV eTej                  dd      xs  eS       ZXdZY G d d eZ      Z[ G d! d"e[      Z\d# Z]ed$        Z^d% Z_eYfd&Z` G d' d(e[      Zad) ZbdeVeXfd*Zcd{d,ZPd|d.Zd	 	 	 	 	 	 d}d/Zed~d0Zfdd1Zgdd-deXdd2dfd3Zhdd4Zid5 Zjdd6Zkdd7ZlelZmeYfd8ZneYfd9Zoej                  fd:Zpej                  fd;Zqej                  fd<Zrej                  fd=Zsej                  fd>Ztej                  fd?Zud@ ZvdA Zwd+dej                  dd-d-fdBZxd+dej                  eYfdCZyej                  fdDZzej                  fdEZ{dF Z|	 	 	 	 	 	 	 ddGZ}dH Z~ej                  fdIZdJ ZddKZ	 ddLeJdMeeeef      dNeee   ef   fdOZddeVeXd-fdPZddeVeXdQd-fdRZddSZdT Zd|dUZdV ZddWZddXZddYZddZZd[ Zd\ Zd] Zdd^Zd_ Zd` Zda Z	 	 	 ddbeGdceddeeef   deee   dfedgefdhZdej                  eXddd-d-d-fdiZddjZdk ZddlZdmej                  d-d-fdnZdo Zd|dpZddqZdr Zds Zdt Zdu Zdv Zdw Zdx ZddyZdz Zy)a  Simple wrapper that provides porcelain-like functions on top of Dulwich.

Currently implemented:
 * archive
 * add
 * branch{_create,_delete,_list}
 * check-ignore
 * checkout
 * clone
 * commit
 * commit-tree
 * daemon
 * describe
 * diff-tree
 * fetch
 * init
 * ls-files
 * ls-remote
 * ls-tree
 * pull
 * push
 * rm
 * remote{_add}
 * receive-pack
 * reset
 * 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.

Functions should generally accept both unicode strings and bytestrings
    )
namedtuple)closingcontextmanager)BytesIO	RawIOBaseN)Path)DictOptionalTupleUnion)
tar_stream)get_transport_and_path)StackedConfig)
CHANGE_ADDCHANGE_DELETECHANGE_MODIFYCHANGE_RENAMECHANGE_COPYRENAME_CHANGE_TYPES)SendPackError)can_fast_forward)IgnoreFilterManager)blob_from_path_and_statget_unstaged_changes)tree_lookup_path)CommitTagformat_timezoneparse_timezonepretty_format_tree_entry)parse_commitparse_object	parse_refparse_reftuples
parse_tree)write_pack_indexwrite_pack_objects)write_tree_diff)ProtocolZERO_SHA)ANNOTATED_TAG_SUFFIXLOCAL_BRANCH_PREFIXstrip_peeled_refsRefsContainer)BaseRepoRepo)FileSystemBackendTCPGitServerReceivePackHandlerUploadPackHandlerupdate_server_info	GitStatuszstaged unstaged untrackedc                   *    e Zd ZdZddZd Zd Zd Zy)
NoneStreamz;Fallback if stdout or stderr are unavailable, does nothing.c                      y N )selfsizes     $lib/third_party/dulwich/porcelain.pyreadzNoneStream.read           c                      y r:   r;   )r<   s    r>   readallzNoneStream.readall   r@   rA   c                      y r:   r;   r<   bs     r>   readintozNoneStream.readinto   r@   rA   c                      y r:   r;   rE   s     r>   writezNoneStream.write   r@   rA   N))__name__
__module____qualname____doc__r?   rC   rG   rI   r;   rA   r>   r8   r8      s    ErA   r8   bufferutf-8c                   $     e Zd ZdZd fd	Z xZS )ErrorzPorcelain-based error. c                 :    t         t        |   |       || _        y r:   )superrR   __init__inner)r<   msgrV   	__class__s      r>   rU   zError.__init__   s    eT#C(
rA   r:   )rK   rL   rM   rN   rU   __classcell__)rX   s   @r>   rR   rR      s    ! rA   rR   c                       e Zd ZdZy)RemoteExistsz&Raised when the remote already exists.NrK   rL   rM   rN   r;   rA   r>   r[   r[      s    0rA   r[   c                 <    t        | t              r| S t        |       S )zEOpen an argument that can be a repository or a path for a repository.)
isinstancer/   r0   path_or_repos    r>   	open_repora      s    ,)rA   c              #      K   |  yw)zBContext manager that has the same api as closing but does nothing.Nr;   )objs    r>   _noop_context_managerrd      s      Is   c                 `    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^   r/   rd   r   r0   r_   s    r>   open_repo_closingrf      s)    
 ,)$\224%&&rA   c                    t         j                  dk  rt        |t              st	        j
                  |      }t        | t              st	        j
                  |       } t        j                  j                  ||       }|j                  d      rd|d| d}t        |      t        j                  j                  dk7  r9|j                  t        j                  j                  j                  d      d      }|S t         j                  d	k(  rt        j                  j                  |      }t        |      }|j!                         }t         j                  d	k(  rt        j                  j                  |       } t        |       j!                         } 	 |j#                  |       }t         j                  d	k(  rBt+        |      j                  t        j                  j                  d      j                  |      S t        |      S # t        $ rM |j%                         r9|j&                  j!                         }||j(                  z  j#                  |       }n Y w xY w)
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
    )      s   ..zPath z not in repo path ()/ascii   /win32)sysversion_infor^   bytesosfsencodepathrelpath
startswith
ValueErrorsepreplaceencodeplatformabspathr   resolverelative_to
is_symlinkparentnamestr)repopathrt   tree_encodingtreepatherr_msgresolved_pathru   r   s           r>   path_to_tree_pathr      s    & $&;;t$D(E*{{8,H77??42u%9=xHGW%%77;;#''(:(:7(CTJH <<7"77??4(DDz
 <<7"wwx0H>))+		#//9G <<7"w<''S9@@OO>!  	  ,,.!DII-::8D 	s   H AIIc                       e Zd ZdZy)DivergedBranchesz8Branches have diverged and fast-forward is not possible.Nr\   r;   rA   r>   r   r     s    BrA   r   c                 ^    	 t        | ||      }|st        ||      y# t        $ r d}Y w xY w)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   )repocurrent_shanew_shacans       r>   check_divergedr     sB    t[': {G44   s    ,,c                    |d}t        |       5 }t        ||      }t        |j                  |j                  |j                     |j
                        D ]  }|j                  |        	 ddd       y# 1 sw Y   yxY w)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)rf   r!   r   object_storetreecommit_timerI   )r   
committish	outstream	errstreamrepo_objcchunks          r>   archiver   !  sn     
	4	 H:.!!8#8#8#@!--
E OOE"
 
!	 	 s   AA55A>.c                 Z    t        |       5 }t        |       ddd       y# 1 sw Y   yxY w)z]Update server info files for a repository.

    Args:
      repo: path to the repository
    N)rf   server_update_server_infor   rs     r>   r5   r5   :  s"     
4	 A!!$ 
!	 	 s   !*Fc                     t        |       5 }t        |      }|s*||j                  j                         vrt	        d|z        |j                  j                  d|       ddd       y# 1 sw Y   yxY w)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 `%s` is not a ref   HEADN)rf   _make_branch_refrefskeysrR   set_symbolic_ref)r   ref_nameforcer   ref_paths        r>   symbolic_refr   D  s`     
4	 H#H-););)==6ABB&&w9	 
!	 	 s   AA))A2c                 T   t        |dd      r|j                  |xs t              }t        |dd      r|j                  |xs t              }t        |dd      r|j                  |xs t              }t        |       5 }|j	                  |||||      cddd       S # 1 sw Y   yxY w)a$  Create a new commit.

    Args:
      repo: Path to repository
      message: Optional commit message
      author: Optional author name and email
      committer: Optional committer name and email
      no_verify: Skip pre-commit and commit-msg hooks
    Returns: SHA1 of the new commit
    rz   N)messageauthor	committerencoding	no_verify)getattrrz   DEFAULT_ENCODINGrf   	do_commit)r   r   r   r   r   r   r   s          r>   commitr   S  s    ( w$'..!=-=>vx&x;+;<y(D)$$X%A1AB		4	 A{{  
 
!	 	 s   >BB'c                 n    t        |       5 }|j                  ||||      cddd       S # 1 sw Y   yxY w)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)rf   r   )r   r   r   r   r   r   s         r>   commit_treer   w  s4     
4	 A{{$)F  
 
!	 	 s   +4c                     t         j                  j                  |       st        j                  |        |rt	        j
                  |       S t	        j                  |       S )zCreate a new git repository.

    Args:
      path: Path to repository.
      bare: Whether to create a bare repository.
    Returns: A Repo instance
    )rr   rt   existsmkdirr0   	init_bareinit)rt   bares     r>   r   r     s?     77>>$
~~d##yyrA      originc                 ^   |ddl }	|	j                  dt        d       |}|| }|r|rt        d      || j	                  d      d   }t
        j                  j                  |      st        j                  |       |rt        j                  |      }
nt        j                  |      }
d	| j                  d
      z   }	 |
j                         }t        | t              s| j                  t               } |j#                  d|fd|        |j#                  d|fdd|z   dz          |j%                          t'        |
|f|||d|}|j(                  j+                         D ]!  \  }}|
j,                  j/                  ||       # 	 |
|j,                  d      }|j0                  |
d<   |r@|s>|<|j5                  d|j0                  z   dz          |
j7                  |j8                         |
S # t2        $ r d}Y Qw xY w# t:        $ r' t=        j>                  |       |
jA                           w xY w)a  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
    Returns: The new repository
    Nr   z7outstream= has been deprecated in favour of errstream=.rh   )
stacklevelz"checkout and bare are incompatiblerk   rJ   s   clone: from rP      remote   urls   fetchs   +refs/heads/*:refs/remotes/s   /*)r   r   depthr   s   Checking out    
)!warningswarnDeprecationWarningrR   splitrr   rt   r   r   r0   r   r   rz   
get_configr^   rq   r   setwrite_to_pathfetchsymrefsitemsr   r   idr   rI   reset_indexr   BaseExceptionshutilrmtreeclose)sourcetargetr   checkoutr   r   originr   kwargsr   r   reflog_messagetarget_configfetch_resultkeyheads                   r>   cloner     s&   2 E 	 	

 	8D899~c"2&77>>&!
NN6"IIf$v}}W'==N!&%(]]#34F9f-vv>*V3e;	

 	##%
  "
 
 (//557KCFF##C0 8	!\&&w/0D AgJDT%5OO,tww6>?MM$))$ H  	D	  f		s2   CG< G+ AG< +G96G< 8G99G< <0H,c                    t               }t        |       5 }t        |j                        j	                         }t        j                  |      }|s_t        t        t        t        t        j                               j	                               t        |      |j                                     }g }t        |t              s|g}|D ]g  }t        t        |      j	                         j                  |            }|j                  |      r|j!                  |       W|j#                  |       i |j%                  |       ddd       ||fS # 1 sw Y   |fS xY w)zAdd 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
    N)r   rf   r   rt   r}   r   	from_repolistget_untracked_pathsr   rr   getcwd
open_indexr^   r~   
is_ignoredaddappendstage)	r   pathsignoredr   	repo_pathignore_managerrelpathspru   s	            r>   r   r     s    eG	4	 AL((*	,66q9#RYY[)1134	NLLNE %&GEA$q'//+77	BCG((1G$OOG$  	
+ 
!, g- 
!, gs   D,EEc                    t         j                  j                  |      t         j                  j                  z   }t         j                  j                  |       t         j                  j                  z   }|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.
    )rr   rt   realpathrx   rv   )subdir	parentdirparentdir_abs
subdir_abss       r>   
_is_subdirr     sW     GG$$Y/"''++=M!!&)BGGKK7J  //rA   c                     |t        j                         }t        |       5 }t        ||j                        st        d      |j                         }|j                  ddd      }|j                         }t        j                  |      }t        ||j                        }t        t        |            D ]  \  }}	|	r:t        t        j                  |            dk(  }
|
s,t        j                   |       Bt#        |j                  |      }||v }t         j                  j%                  ||j                        }|j'                  |      }|r|rt        j(                  |        	 ddd       y# 1 sw Y   yxY w)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   )rr   r   rf   r   rt   rR   get_config_stackget_booleanr   r   r   _walk_working_dir_pathsreversedr   lenlistdirrmdirr   ru   r   remove)r   
target_dirr   configrequire_forceindexr   paths_in_wdapis_diris_emptyip
is_trackedrpr   s                  r>   cleanr    s,    YY[
	4	 A*aff-FGG##%**$
 ,66q9-j!&&A #4#45JB rzz"~.!3HHRL&qvvr25[
WW__R0+66r:
!*IIbM 6% 
!	 	 s   B?E4"A-E4E4E44E=c                 *   t        |       5 }|j                         }|D ]  }t        j                  t        j                  j                  |            }t        |j                  |      }	 ||   j                  }|s	 t        j                  |      }		 t        ||	      }
	 t        |j                  ||j                            j                  |      d   }|
j                   |k7  r||k7  rt        d|z        ||k7  rt        d|z        t        j"                  |       ||=  |j)                          ddd       y# t        $ r t        d|z        w xY w# t        $ r d}Y w xY w# t$        $ r Y Vw xY w# t&        $ r Y ew xY w# 1 sw Y   yxY w)zuRemove files from the staging area.

    Args:
      repo: Repository for the files
      paths: Paths to remove
    z%s did not match any files   NzAfile has staged content differing from both the file and head: %szfile has staged changes: %s)rf   r   rr   rs   rt   r|   r   shar   rR   lstatr   r   __getitem__r   r   r   r   IOErrorOSErrorrI   )r   r   cachedr   r  r   	full_path	tree_path	index_shastblobcommitted_shas               r>   r   r   O  s    
4	 AABGGOOA$67I)!&&!4I>!),00	 -),B-6y"E1,< !q{/?/?--!M  77i/I4N"'!BDE!F# 
 %5"'(E(I"JJ		),i G H 	M 
!	   >81<==>$  ( 1,0M1 #    
!	 s   AF	,D?;F	>E:E+!5EA F	?EF	E(%F	'E((F	+	E74F	6E77F	:	FF	FF		Fc                 z    | j                   r| j                   j                  d      }n|}|j                  |d      S )Nrl   ry   )r   decoder   contentsdefault_encodingr   s       r>   commit_decoder     s3    ??))'2#??8Y//rA   c                 x    | j                   r| j                   j                  d      }n|}|j                  |      S )Nrl   )r   r  rz   r  s       r>   commit_encoder"    s1    ??))'2#??8$$rA   c                    |j                  d       |j                  d| j                  j                  d      z   dz          t        | j                        dkD  rP|j                  ddj                  | j                  dd D cg c]  }|j                  d       c}      z   dz          |j                  d	 || j                        z   dz          | j                  | j                  k7  r'|j                  d
 || j                        z   dz          t        j                  | j                  | j                  z         }t        j                  d|      }t        | j                        j                  d      }|j                  d|z   dz   |z   dz          |j                  d       |j                   || j                        dz          |j                  d       yc c}w )zWrite a human-readable commit log entry.

    Args:
      commit: A `Commit` object
      outstream: A stream file to write to
    z3--------------------------------------------------
zcommit: rl   
r  zmerge: z...NzAuthor: zCommitter: %a %b %d %Y %H:%M:%SDate:    )rI   r   r  r   parentsjoinr   r   timegmtimeauthor_timeauthor_timezonestrftimer   r   )r   r  r   r   
time_tupletime_strtimezone_strs          r>   print_commitr2    s    OOO$OOJ!1!1'!::TAB
6>>QjjV^^AB5GH5G!((7+5GHIJ	

 OOJ!66=>}}(((v/?/?(@@4GHV//&2H2HHIJ}}3Z@H"6#9#9:AA'JLOOJ)C/,>EFOODOOF6>>*T12OOD Is   Gc                    |j                  d || j                        z   dz          t        j                  | j                  | j
                  z         }t        j                  d|      }t        | j
                        j                  d      }|j                  d|z   dz   |z   dz          |j                  d       |j                   || j                        dz          |j                  d       y)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: r$  r%  rl   r&  r'  N)
rI   taggerr*  r+  tag_timetag_timezoner.  r   r  r   )tagr  r   r/  r0  r1  s         r>   	print_tagr8    s     OOJ

!33d:;S\\C,<,<<=J}}3Z@H"3#3#34;;GDLOOJ)C/,>EFOODOOF3;;'$./OODrA   c                 F    |j                   ||j                               y)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)rI   data)r   r  r  r   s       r>   	show_blobr;    s     OOF499%&rA   c                 F   t        |||       |j                  r| |j                  d      }|j                  }nd}t               }t	        || j
                  ||j                         |j                  d       |j                  t        ||j                                      y)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
    )r  r   r   N)
r2  r(  r   r   r(   r   seekrI   r   getvalue)r   r   r  r   parent_commit	base_tree
diffstreams          r>   show_commitrB    s     )<~~V^^A./!&&		JJ 1 19fkkJOOAOOM&**=*=*?@ArA   c                 F    |D ]  }|j                   ||      dz           y)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
    r$  N)rI   )r   r   r  r   ns        r>   	show_treerE    s#     q	D() rA   c                 Z    t        |||       t        | | |j                  d      ||       y)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)r8  show_objectobject)r   r7  r  r   s       r>   show_tagrI    s+     c69%d3::a=)69=rA   c                 \    	 t        t        t        t        d|j                     | |||      S )N)s   trees   blobs   commits   tag)rE  r;  rB  rI  	type_name)r   rc   r  r   s       r>   rG  rG    s;    	
 
mm
 3	3 3rA   c              #   N  K   | D ]  }|st        |t              r|d   }|j                  t        k(  r|j                  j
                  }d}d}n|j                  t        k(  r|j                  j
                  }d}d}n|j                  t        k(  r|j                  j
                  }d}d}ni|j                  t        v rW|j                  j
                  }|j                  j
                  }|j                  t        k(  rd}n|j                  t        k(  rd}dd	d	  y
w)z5Print a simple status summary, listing changed files.r    ADMRC820N)r^   r   typer   newrt   r   oldr   r   r   r   )changeschangepath1path2kinds        r>   print_name_statusr]    s     fd#AYF;;*$JJOOEED[[M)JJOOEED[[M)JJOOEED[[//JJOOEJJOOE{{m++"&u551 s   D#D%c           	      8  
 t        |       5 }|j                  |||      }|D ]Z  

fd}t        
j                  ||       |s"|j	                  t        
j                               D 	cg c]  }	|	dz   	 c}	       \ 	 ddd       yc c}	w # 1 sw Y   yxY w)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                 0    t        j                  |       S r:   )r   r   )xentrys    r>   r  zlog.<locals>.decode7  s    $U\\155rA   r$  N)rf   
get_walkerr2  r   
writelinesr]  rX  )r   r   r   r_  r`  name_statusr   walkerr  linerc  s             @r>   logri  !  s    $ 
4	 A+UGTE6 vy9$$->u}}-OP-OTTD[-OP  
!	  Q 
!	 s#   8B&B,B8	BBBc                     |dg}t        |t              s|g}t        |       5 }|D ]8  }t        ||      t        t              rfd}nfd}t        |||       : 	 ddd       y# 1 sw Y   yxY w)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                     t        |       S r:   )r   )rb  r  os    r>   r  zshow.<locals>.decodeZ  s    (A/?@@rA   c                 &    | j                        S r:   )r  )rb  r  s    r>   r  zshow.<locals>.decode_  s    88$455rA   )r^   r   rf   r"   r   rG  )r   objectsr   r  r   	objectishr  rl  s      `   @r>   showrp  B  ss     (gt$)	4	 A IQ	*A!V$A
6 1fi0 ! 
!	 	 s   >A..A7c                 t    t        |       5 }t        ||j                  ||       ddd       y# 1 sw Y   yxY w)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)rf   r(   r   )r   old_treenew_treer   r   s        r>   	diff_treert  e  s,     
4	 A	1>>8XF 
!	 	 s   .7c                    t        |       5 }|j                  |D cg c]  }||   j                   c}      D ]*  }|j                  |j                  j                  dz          , 	 ddd       yc c}w # 1 sw Y   yxY w)zLists commit objects in reverse chronological order.

    Args:
      repo: Path to repository
      commits: Commits over which to iterate
      outstream: Stream to write to
    )includer   N)rf   rd  r   rI   r   )r   commitsr   r   r   rc  s         r>   rev_listrx  r  sh     
4	 A\\G*DGq1Q477G*D\EEOOELLOOe34 F 
!	 *D 
!	 s   A6A1
5A61A66A?c                  L    dd l }|j                  dt               t        | i |S )Nr   z0tag has been deprecated in favour of tag_create.)r   r   r   
tag_createargsr   r   s      r>   r7  r7    s)    MM:<N t&v&&rA   c	                    t        |       5 }	t        |	|      }
|rt               }||	j                  |	j	                               }||_        ||_        ||_        t        |
      |
j                  f|_
        |t        t        j                               }||_        |d}nt        |t              rt!        |      }||_        |rFddl}|j'                  d      5 }|j)                  |j+                               \  |_        }ddd       |	j.                  j1                  |       |j                  }n|
j                  }||	j2                  t5        |      <   ddd       y# 1 sw Y   ^xY w# 1 sw Y   yxY w)a  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
    Nr   T)armor)rf   r"   r   _get_user_identityr   r4  r   r   rU  r   rH  intr*  r5  r^   r   r   r6  gpgContextsignas_raw_string	signaturer   
add_objectr   _make_tag_ref)r   r7  r   r   	annotatedro  r5  r6  r  r   rH  tag_objr  r   unused_resulttag_ids                   r>   rz  rz    s<   2 
4	 Aa+eG~--a.@.@.BC#GN%GOGL"6lFII6GNtyy{+'G# L#.-l;#/G [[t[,78vvg>S>S>U7V4G%} -NN%%g.ZZFYYF%+}S!"A 
!	 2 -,3 
!	 s%   CE.(E"AE."E+	'E..E7c                  L    dd l }|j                  dt               t        | i |S )Nr   z4list_tags has been deprecated in favour of tag_list.)r   r   r   tag_listr{  s      r>   	list_tagsr    s)    MM> T$V$$rA   c                     t        |       5 }t        |j                  j                  d            }|cddd       S # 1 sw Y   yxY w)zfList all tags.

    Args:
      repo: Path to repository
      outstream: Stream to write tags to
    	   refs/tagsN)rf   sortedr   as_dict)r   r   r   tagss       r>   r  r    s4     
4	 Aaffnn\23 
!	 	 s	   &<Ac                     t        |       5 }t        |t              r|g}n!t        |t              r|}nt	        d|z        |D ]  }|j
                  t        |      =  	 ddd       y# 1 sw Y   yxY w)z^Remove a tag.

    Args:
      repo: Path to repository
      name: Name of tag to remove
    zUnexpected tag name type %rN)rf   r^   rq   r   rR   r   r  r   r   r   namess       r>   
tag_deleter    sf     
4	 AdE"FEd#E5<==D}T*+  
!	 	    AA))A2c                     |dk7  rt        d      t        |       5 }t        ||      }|j                  |j                         ddd       y# 1 sw Y   yxY w)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)rR   rf   r%   r   r   )r   modetreeishr   r   s        r>   resetr    sI     v~?@@	4	 A!W%	dgg 
!	 	 s   (AAr   remote_locationreturnc                 "   | j                         }|t        |       }t        |t              r|j	                         }n|}d|f}d }|j                  |      r%|j                         }|j                  |d      }|}nd }||j                         fS )Nr   url)r   get_branch_remoter^   r   rz   has_sectionr  get)r   r  r  encoded_locationsectionremote_namer  s          r>   get_remote_repor    s     __F+D1/3'*113**+GK'"&--/jj%()00233rA   c           	      F   t        |       5 t              gt        |      \  }}t        |fdj	                         i|\  }}	g i fd}
t        |dd      xs t        }|j                  |	      }	 |j                  |	|
j                  |j                        }|j                  d|j                  |      z   dz          |j                   xs i j#                         D ]A  \  }}|&|j                  d||j                  |      fz         .|j                  d|z         C |t%        j&                  |       ddd       y# t        $ r6}t        d|z   d	z   |j                  d
   j                         z   |      d}~ww xY w# 1 sw Y   yxY w)a1  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                 *   
j                  t        j                  |              i }
D ]G  \  }}}|t        ||<   d 	|<   	 j                  |   }|s|| v rt        | |   |       |||<   |	|<   I |S # t        $ r t        d|z        w xY w)Nr   z#No valid ref %s in local repository)extendr$   r   r*   r   rR   r   )r   new_refslhrh	force_reflocalshar   r   refspecsremote_changed_refsselected_refss         r>   update_refszpush.<locals>.update_refs8  s      xu!UVH'4#R:#+HRL.2'+P#$66": %t&q$r(H=#+HRL.6'+ (5 O $ P#$IB$NOOPs   A::Br   )generate_pack_dataprogresss   Push to s    successful.
zPush to z failed -> r   )rV   s   Push of ref %s failed: %s
s   Ref %s updated
)rf   active_branchr  r   r   r   r   get_url	send_packr  rI   rz   r   rR   r|  r  
ref_statusr   _import_remote_refsr   )r   r  r  r   r   r   r   r  clientrt   r  err_encodingresultereferrorr   r  r  s     `  `          @@@r>   pushr    s   * 
4	 A%a()H)8O)L&o .
$%$6$6$8
<B
  	 	& y*d;O?O ...	%%#$#7#7"	 & F OOo44\BBEVV ",,299;JC 2c5<<;U5VV  3c 9: < "5HIy 
!	 R  	_,}<qvvay?O?O?QQ 	S 
!	 s1   A0F)E+B!F	F1FFFF Tc                    t        |       5 t        |      \  }}dgg fd}	t        |fdj                         i|\  }
}|
j	                  ||j
                  |	      }D ]J  \  }}}	 t        j                  |   |j                  |          |j                  |   j                  |<   L r|j                  d   d      d<   d   j                  }j                  |	       |!t        j                  ||j                         ddd       y# t        $ r |r t        d      w xY w# 1 sw Y   yxY w)
a  Pull from remote via dulwich.client

    Args:
      repo: Path to repository
      remote_location: Location of the remote
      refspec: refspecs to fetch
      outstream: A stream file to write to output
      errstream: A stream file to write to errors
    Nr   c                     j                  t        | j                               D cg c]  \  }}}| |   j                  vr| |    c}}}S c c}}}w )Nr  )r  r$   r   r   )remote_refsr  r  r  r   r   r  r  s       r>   determine_wantszpull.<locals>.determine_wants  se      QVVXUK
 ,9+8'RYr?!..8 B+8  s   !Ar  )r  r  zmerge is not yet supportedr   r  )r   )rf   r  r   r   r   rI   r   r   r   NotImplementedErrorr   r   r  )r   r  r  r   r   fast_forwardr   r   r  r  r  rt   r   r  r  r  r   r   r  s     `   `          @@r>   pullr  j  sj   ( 
4	 A)8O)L&oyH	 .
$%$6$6$8
<B
 ||!ioo $ 
 $1RYLq!&&*l.?.?.CD &**2.AFF2J $1 %**=+;A+>?AgJ z	4 "\5F5FGO 
!	 4 $ L-.JKK	L5 
!	 s%   A&D>7'D#A<D>#D;;D>>Ec                 j   t        |       5 }t        |      }|j                         }|j                         }|j                  }t        t        ||j                  |            }t        |j                  |j                  ||       }t        |      }	t        |||	      cddd       S # 1 sw Y   yxY w)a  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`
    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_ignoredN)
rf   get_tree_changesr   get_blob_normalizercheckin_normalizer   r   rt   r   r6   )
r   r   r   tracked_changesr  
normalizerfilter_callbackunstaged_changesuntracked_pathsuntracked_changess
             r>   statusr    s     
4	 A*1-**,
$66 4UAFFO TU-FFAFFEw;
 !1*:<MN 
!	 	 s   BB))B2c              #   $  K   t        j                  |       D ]t  \  }}}d|v r|j                  d       ||k7  r"d|v r|j                  d       ||k7  r=|| k7  r|df |D ](  }t         j                  j	                  ||      }|df * v yw)zGet path, is_dir for files in working dir from frompath

    Args:
      frompath: Path to begin walk
      basepath: Path to compare to
    z.gitTFN)rr   walkr   rt   r)  )frompathbasepathdirpathdirnames	filenamesfilenamefilepaths          r>   r   r     s      )+(9$9XOOF#("YV$("h4-!Hww||GX6HE/! " ):s   BBc              #   x  K   |r*t        |       5 }t        j                  |      }ddd       nd}t        | |      D ]m  \  }}0|j	                  t
        j                  j                  ||             r8|r;t        ||      }||vsLt
        j                  j                  ||        o y# 1 sw Y   xY ww)zGet untracked paths.

    Args:
      frompath: Path to walk
      basepath: Path to compare to
      index: Index to check against
      exclude_ignored: Whether to exclude ignored paths
    N)	rf   r   r   r   r   rr   rt   ru   r   )	r  r  r  r  r   r   r  r  r	  s	            r>   r   r     s      x(A0::1=N )( -hA
F%.*C*CGGOOB)+
 "8R0Bggoob(33 B )(s(   B:B.AB:8B:	%B:.B73B:c                    t        |       5 }|j                         }g g g d}	 |d   j                  }|j	                  |j
                  |      D ]~  }|d   d   s|d   j                  |d   d          &|d   d   s|d   j                  |d   d          I|d   d   |d   d   k(  r|d   j                  |d   d          ut        d	       |cddd       S # t        $ r d}Y w xY w# 1 sw Y   yxY w)
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)rf   r   r   r   changes_from_treer   r   r  )r   r   r  r  tree_idrY  s         r>   r  r    s    
4	 A 

	jooG --anngFF!9Q<&--fQil;AYq\)001>11-)001>)*HII G 3 
!	   	G	 
!	 s.   C,CBC,C)&C,(C))C,,C5c                 T    t        |       }t        |||      }|j                          y)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)r1   r2   serve_forever)rt   addressportbackendservers        r>   daemonr    s(      %G'7D1F
rA   c                 |    ddl m}m}m}m} t        |       } ||      } ||||||      }	|	j                          y)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   )make_wsgi_chainmake_serverWSGIRequestHandlerLoggerWSGIServerLogger)handler_classserver_classN)dulwich.webr  r  r  r  r1   r  )
rt   r  r  r  r  r  r  r  appr  s
             r>   
web_daemonr  )  sI       %G
'
"C.%F rA   c                 x   )t        t        j                  dt        j                        |)t        t        j                  dt        j                        }t        j
                  j                  |       } t        |       }fd}t        |j                  |      }t        || g|      }|j                          y)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
    rO   c                 H    j                  |        j                          y r:   rI   flushr:  outfs    r>   send_fnzupload_pack.<locals>.send_fnS      

4

rA   r   )r   ro   stdoutstdinrr   rt   
expanduserr1   r)   r?   r4   handlert   infr  r  r  protohandlers     `    r>   upload_packr  D  s     |szz8SZZ8
{cii399577d#D%G SXXw'E$7GNNrA   c                 x   )t        t        j                  dt        j                        |)t        t        j                  dt        j                        }t        j
                  j                  |       } t        |       }fd}t        |j                  |      }t        || g|      }|j                          y)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
    rO   c                 H    j                  |        j                          y r:   r  r  s    r>   r  zreceive_pack.<locals>.send_fnm  r  rA   r   )r   ro   r  r   rr   rt   r  r1   r)   r?   r3   r  r  s     `    r>   receive_packr
  ^  s     |szz8SZZ8
{cii399577d#D%G SXXw'E 4&%8GNNrA   c                 X    t        | dd       r| j                  t              } t        | z   S )Nrz   )r   rz   r   r,   r   s    r>   r   r   x  s(    tXt${{+,%%rA   c                 P    t        | dd       r| j                  t              } d| z   S )Nrz   
   refs/tags/)r   rz   r   r  s    r>   r  r  ~  s(    tXt${{+,4rA   c                     t        |       5 }t        |t              r|}n|g}|D ]  }|j                  t	        |      =  	 ddd       y# 1 sw Y   yxY w)zbDelete a branch.

    Args:
      repo: Path to the repository
      name: Name of the branch
    N)rf   r^   r   r   r   r  s       r>   branch_deleter    sL     
4	 AdD!EFED'-.  
!	 	 s   4A

Ac                 f   t        |       5 }|d}t        ||      }t        |      }d|j                  d      z   }|r*|j                  j                  |d|j                  |       n6|j                  j                  ||j                  |      st        d|z        ddd       y# 1 sw Y   yxY w)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 rP   )r   z#Branch with name %s already exists.)	rf   r"   r   rz   r   set_if_equalsr   
add_if_newrR   )r   r   ro  r   r   rH  refnameref_messages           r>   branch_creater    s     
4	 AIa+"4(.1A1A'1JJFF  $		; O66$$Wfii$MADHII 
!	 	 s   BB''B0c                     t        |       5 }|j                  j                  t              cddd       S # 1 sw Y   yxY w)zEList all branches.

    Args:
      repo: Path to the repository
    )baseN)rf   r   r   r,   r   s     r>   branch_listr    s-     
4	 Avv{{ 3{4 
!	 	 s    6?c                     t        |       5 }|j                  j                  d      d   d   }|j                  t              st        |      |t        t              d cddd       S # 1 sw Y   yxY w)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)rf   r   followrv   r,   rw   r   )r   r   
active_refs      r>   r  r    sa     
4	 AVV]]7+A.q1
$$%89Z((#1245	 
!	 	 r  c                     t        |       5 }t        |j                        }|j                         }	 |j	                  d|fd      }ddd       |S # t
        $ r d}Y w xY w# 1 sw Y   S xY w)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   r   N)rf   r  rt   r   r  r   )r   r   branch_namer  r  s        r>   r  r    sr     
4	 A#AFF+	$ **i%=yIK	 
!   	$#K	$ 
! s(   &A"AAA"AA""A,refs_containerr  r   r   prune
prune_tagsc                    t        |      }|j                         D ci c]-  \  }}|j                  t              r|t	        t              d  |/ }	}}| j                  d|j                         z   |	||       |j                         D ci c]:  \  }}|j                  d      r$|j                  t              s|t	        d      d  |< }
}}| j                  d|
||       y c c}}w c c}}w )Ns   refs/remotes/)r   r   r  r  )	r-   r   rv   r,   r   import_refsrz   endswithr+   )r  r  r   r   r   r!  stripped_refsrD  vbranchesr  s              r>   r  r    s    &d+M $))++FQ<<+, 	
#!
"
$%q(+  
 ;--//	   $))++FQ<<&qzz:N/O 	
#m

"+ 	 
 |T7*U!s   2C%?C+c	           	      \   t        |       5 }
t        |
|      \  }}|d|j                  d      z   }t        |fd|
j	                         i|	\  }}|j                  ||
|j                  |      }|%t        |
j                  ||j                  |||       ddd       |S # 1 sw Y   S xY w)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 rP   r  )r  r   )r   r!  )	rf   r  rz   r   r   r   rI   r  r   )r   r  r   r   r   r   r   r!  r   r   r   r  r  rt   r   s                  r>   r   r     s    4 
4	 A)8O)L&o?%(>(>w(GGG-
$%$6$6$8
<B
 ||D!iooU|S"!!% 
!" # 
!" s   BB!!B+c                 r    |t        j                         }t        | fd|i|\  }}|j                  |      S )zList the refs in a remote.

    Args:
      remote: Remote repository location
      config: Configuration to use
    Returns:
      Dictionary with remote refs
    r  )r   defaultr   get_refs)remoter  r   r  	host_paths        r>   	ls_remoter.  $  s?     ~&&(.vOfOOFI??9%%rA   c                 x    t        |       5 }|j                  j                          ddd       y# 1 sw Y   yxY w)zRepack loose files in a repository.

    Currently this only packs loose objects.

    Args:
      repo: Path to the repository
    N)rf   r   pack_loose_objectsr   s     r>   repackr1  3  s*     
4	 A	))+ 
!	 	 s   09c           
      <   t        |       5 }t        ||j                  j                  d |D              |      \  }}ddd       |Ct	        j                         D 	cg c]  \  }}	||	d   |	d   f c}	}      }t        ||       yy# 1 sw Y   OxY wc c}	}w )zPack 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)
    c              3   $   K   | ]  }|d f 
 y wr:   r;   ).0oids     r>   	<genexpr>zpack_objects.<locals>.<genexpr>K  s     $GJSc4[Js   )delta_window_sizeNr   r  )rf   r'   r   	iter_shasr  r   r&   )
r   
object_idspackfidxfr7  r   entriesdata_sumkr&  s
             r>   pack_objectsr?  ?  s     
4	 A.NN$$$GJ$GG/
 
! Hfq!1adAaD/HIw1  
!	  Is   2B B
Br   c                     fdt        |       5 }t        ||      } |j                  |j                  d       ddd       y# 1 sw Y   yxY w)zList contents of a tree.

    Args:
      repo: Path to the repository
      tree_ish: Tree id to list
      outstream: Output stream (defaults to stdout)
      recursive: Whether to recursively list files
      name_only: Only print item name
    c                    | |   j                         D ]t  \  }}}|rt        j                  ||      }rj                  |dz          nj                  t	        |||             t        j                  |      sh	sk | ||       v y )Nr   )	iteritems	posixpathr)  rI   r    statS_ISDIR)
storetreeidr  r   r  r  	list_tree	name_onlyr   	recursives
         r>   rH  zls_tree.<locals>.list_treed  sw    !&v!8!8!:T4 ~~dD1u- 8tS IJ||D!i%d+ ";rA   rM  N)rf   r%   r   r   )r   r  r   rJ  rI  r   r   rH  s     ```  @r>   ls_treerK  S  s@    "	, 
4	 A!W%!..$''2. 
!	 	 s   +AAc                 ~   t        |t              s|j                  t              }t        |t              s|j                  t              }t	        |       5 }|j                         }d|f}|j                  |      rt        |      |j                  |d|       |j                          ddd       y# 1 sw Y   yxY w)znAdd a remote.

    Args:
      repo: Path to the repository
      name: Remote name
      url: Remote URL
    r   r   N)
r^   rq   rz   r   rf   r   r  r[   r   r   )r   r   r  r   r   r  s         r>   
remote_addrM  t  s     dE"{{+,c5!jj)*	4	 ALLNd#==!w''	gvs#	 
!	 	 s   AB33B<c              #     K   t        |       5 }|j                         }t        j                  |      }|D ]|  }|st	        |j
                  |      |v rt        j
                  j                  |      r*t        j
                  j                  ||j
                        }|j                  |      sy| ~ 	 ddd       y# 1 sw Y   yxY ww)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)
rf   r   r   r   r   rt   rr   isabsru   r   )r   r   no_indexr   r  r   rt   s          r>   check_ignorerQ    s      
4	 A,66q9D 1!&&$ ?5 Hww}}T"wwtQVV4((.
  
!	 	 s#   CB B?/B?6	C?CCc                 R   t        |       5 }|t        |      }nd}|r1|j                  |= t        ||      j                  |j                  |<   n&|j                  j                  |t        ||             ||j                  j                  d|       ddd       y# 1 sw Y   yxY w)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
      detach: Create a detached head
      target: Branch or committish to switch to
      new_branch: New branch to create
    Nr   )rf   r   r   r!   r   r   r#   )r   r   detached
new_branchr   to_sets         r>   update_headrV    s     
4	 A!%j1FF v)!V477AFF6NFF##FIa,@A!FF##GV4 
!	 	 s   BBB&c                    t        |       5 }ddlm} 	 |j                  t        j
                  j                  |j
                  d            }|j                  |      cddd       S # t        $ r
  |       }Y ,w xY w# 1 sw Y   yxY w)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)	rf   dulwich.mailmaprX  	from_pathrr   rt   r)  FileNotFoundErrorlookup)r   contactr   rX  mailmaps        r>   check_mailmapr_    sp     
4	 A+	 ''QVVZ(HIG ~~g& 
!	 
 ! 	 iG	  
!	 s.   A=9A'A='A:7A=9A::A==Bc              #      K   t        |       5 }|j                  D ]"  }|j                  |   }	 |j                          $ 	 ddd       y# t        $ r}||f Y d}~Cd}~ww xY w# 1 sw Y   yxY ww)zsCheck a repository.

    Args:
      repo: A path to the repository
    Returns: Iterator over errors/warnings
    N)rf   r   check	Exception)r   r   r  rl  r  s        r>   fsckrc    si      
4	 A >>Cs#A	 "	 
!	   Ah 
!	 sD   A2A&A
A&	A2
	A#AA&A##A&&A/+A2c                     t        |       5 }ddlm} |j                  |      }t	        t        |j                                     cddd       S # 1 sw Y   yxY w)z!List all stashes in a repository.r   StashN)rf   dulwich.stashrf  r   	enumerater   stashesr   r   rf  stashs       r>   
stash_listrl    s<    	4	 A'"emmo./	 
!	 	 s   9AAc                     t        |       5 }ddlm} |j                  |      }|j	                          ddd       y# 1 sw Y   yxY w)z Push a new stash onto the stack.r   re  N)rf   rg  rf  r   r  rj  s       r>   
stash_pushrn    s2    	4	 A'"

	 
!	 	 	   (=Ac                     t        |       5 }ddlm} |j                  |      }|j	                          ddd       y# 1 sw Y   yxY w)zPop a new stash from the stack.r   re  N)rf   rg  rf  r   poprj  s       r>   	stash_poprr    s2    	4	 A'"			 
!	 	 ro  c                 v    t        |       5 }t        |j                               cddd       S # 1 sw Y   yxY w)zList all files in an index.N)rf   r  r   r   s     r>   ls_filesrt    s&    	4	 Aalln% 
!	 	 s   /8c           
         t        |       5 }|j                         }i }|j                         D ]  \  }}|j                         }|j	                  |      }d|vr,|j                  dd      \  }}	 |j                  }	|j	                  |	d         }	t        j                  t        j                  |	j                        dd  |	j                  j                  d      g||<    t        |j                         d d	      }
t        |
      d
k(  rGdj                  ||j!                            j                  j                  d      dd       cddd       S d
}||j!                            }|j#                         }|D ]  }|j$                  j                  j                  d      }|
D ]d  }|d
   }|d   d   }||k(  s|d
k(  r|c c cddd       S dj                  |||j                  j                  d      dd       c c cddd       S  |dz  } dj                  |j                  j                  d      dd       cddd       S # t        $ r Y 'w xY w# 1 sw Y   yxY w)zDescribe the repository version.

    Args:
      projdir: git repository root
    Returns: a string description of the current git revision

    Examples: "gabcdefh", "v0.1" or "v0.1-5-gabcdefh".
    r  rk   r  Nri   rl   c                     | d   d   S )Nr  r   r;   )r7  s    r>   <lambda>zdescribe.<locals>.<lambda>!  s    3q6!9rA   T)r   r`  r   zg{}   z	{}-{}-g{})rf   r+  r   r  
get_objectrsplitrH  AttributeErrordatetimer*  r+  r   r   r  r   formatr   rd  r   )r   r   r   r  r   valuerc   _r7  r   sorted_tagscommit_countlatest_commitrg  rc  	commit_idtag_name
tag_commits                     r>   describer     sE    
4	 Azz|**,JC**,C,,u%Cc!ZZa(FAs1 fQi0!!4;;v/A/A#B2A#FG		  )DI '& TZZ\/DdS {q <<!&&( 5 5g >r BC7 
!	 <  !&&( E..w7I"q6 VAY

*#q('[ 
!	 ^  +11$(),,33G<Ra@  _ 
!	 P # AL! & ||M,,33G<Ra@Aq 
!	  "  
!	 sJ   A$I1I
=CIA&I<
I2I4I
	IIIII#c                    |d}t        |       5 }t        ||      }|j                  }t        |t              st        ||      }t        |j                  j                  ||      \  }}||   cddd       S # 1 sw Y   yxY w)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   )	rf   r!   r   r^   rq   r"  r   r   r  )r   rt   r   r   r   r@  r  r  s           r>   get_object_by_pathr  E  ss     
	4	 Aa,KK	$& .D&q~~'A'A9dSsv 
!	 	 s   AA77B c                     t        |       5 }|j                         j                  |j                        cddd       S # 1 sw Y   yxY w)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)rf   r   r   r   r   s     r>   
write_treer  Z  s2     
4	 A||~$$Q^^4 
!	 	 s	   )?A)r   )F)r   NNNNF)NNN)r   F)r   N)r   NF)NNFr   NNF)r   r:   )r   NN)NF)NFF)FN)rN   collectionsr   
contextlibr   r   ior   r   r|  rr   pathlibr   rC  r   rD  ro   r*  typingr	   r
   r   r   dulwich.archiver   dulwich.clientr   dulwich.configr   dulwich.diff_treer   r   r   r   r   r   dulwich.errorsr   dulwich.graphr   dulwich.ignorer   dulwich.indexr   r   dulwich.object_storer   dulwich.objectsr   r   r   r   r    dulwich.objectspecr!   r"   r#   r$   r%   dulwich.packr&   r'   dulwich.patchr(   dulwich.protocolr)   r*   dulwich.refsr+   r,   r-   r.   dulwich.repor/   r0   dulwich.serverr1   r2   r3   r4   r5   r   r6   r8   r   r  default_bytes_out_streamstderrdefault_bytes_err_streamr   rb  rR   r[   ra   rd   rf   r   r   r   r   r   r   r   r   r   r   r   r  r   rmr   r"  r2  r8  r;  rB  rE  rI  rG  r]  ri  rp  rt  rx  r7  rz  r  r  r  r  r   rq   r  r  r  r  r   r   r  r  r  r  r
  r   r  r  r  r  r  r  boolr  r   r.  r1  r?  rK  rM  rQ  rV  r_  rc  rl  rn  rr  rt  r  r  r  r;   rA   r>   <module>r     s  *$L # "  	     
    /   *  (  {$?@	   #3::x>N*, "3::x>N*,   I 15 1  
' 5E 6"rCu C5$ &&	#2%:  
!
H
& 	&
WtD0-"`-`  6F 0 6F % ,/:: 8 &)ZZ $ -0JJ 	' 14

 B* -0JJ 
* +.** 
>36< 

jjD 
jj%	 1F 36** 
G '*jj 
5' 	9,x% !ZZ 	,$$ @D4
4!)%U
*;!<4
8C=#46 &&
QJl &&
;H|O8"444 F644& / J,56$0  $V!VV sCx.V e_	V
 V V< jj&


+\&	,2, jj/B**58'$&0&BBJ*5rA   