
                            S r SSKrSSKrSSKrSSKrSSKrSSKJrJrJ	r	J
r
Jr  SSKrSSKrSSKJr  SSKJrJrJrJrJrJrJr  SSKJr  SSKJrJr  SSKJr  SS	KJ r J!r!J"r"J#r#J$r$J%r%J&r&J'r'J(r(J)r)J*r*J+r+J,r,J-r-J.r.J/r/J0r0J1r1J2r2J3r3J4r4J5r5J6r6J7r7J8r8J9r9J:r:J;r;J<r<J=r=J>r>J?r?J@r@JArAJBrBJCrCJDrD  SS
KEJFrFJGrG  SSKHJIrIJJrJ  \R                  " \L5      rM " S S\N5      rO " S S\N5      rP " S S\O5      rQ " S S\O5      rR " S S\N5      rS " S S\S5      rT " S S\T5      rUS rVS rWS rXS rY " S S\N5      rZ\2\1S4r[ " S  S!\N5      r\ " S" S#\N5      r] " S$ S%\N5      r^ " S& S'\T5      r_ " S( S)\S5      r`\U\_\`S*.ra " S+ S,\R                  5      rc " S- S.\R                  5      re\R                  4S/ jrg\R                  S\R                  \R                  4S0 jrjS1 rkS2 rlS3 rm\LS4:X  a  \g" 5         gg)5a  Git smart network protocol server implementation.

For more detailed implementation on the network protocol, see the
Documentation/technical directory in the cgit distribution, and in particular:

* Documentation/technical/protocol-capabilities.txt
* Documentation/technical/pack-protocol.txt

Currently supported capabilities:

 * include-tag
 * thin-pack
 * multi_ack_detailed
 * multi_ack
 * side-band-64k
 * ofs-delta
 * no-progress
 * report-status
 * delete-refs
 * shallow
 * symref
    N)ListTupleDictOptionalIterable)
tar_stream)ApplyDeltaErrorChecksumMismatchGitProtocolError	HookErrorNotGitRepositoryUnexpectedCommandErrorObjectFormatException)	log_utils)Commitvalid_hexsha)write_pack_objects)%BufferedPktLineWritercapability_agentCAPABILITIES_REFCAPABILITY_AGENTCAPABILITY_DELETE_REFSCAPABILITY_INCLUDE_TAGCAPABILITY_MULTI_ACK_DETAILEDCAPABILITY_MULTI_ACKCAPABILITY_NO_DONECAPABILITY_NO_PROGRESSCAPABILITY_OFS_DELTACAPABILITY_QUIETCAPABILITY_REPORT_STATUSCAPABILITY_SHALLOWCAPABILITY_SIDE_BAND_64KCAPABILITY_THIN_PACKCOMMAND_DEEPENCOMMAND_DONECOMMAND_HAVECOMMAND_SHALLOWCOMMAND_UNSHALLOWCOMMAND_WANT	MULTI_ACKMULTI_ACK_DETAILEDProtocolProtocolFileReceivableProtocolSIDE_BAND_CHANNEL_DATASIDE_BAND_CHANNEL_PROGRESSSIDE_BAND_CHANNEL_FATAL
SINGLE_ACKTCP_GIT_PORTZERO_SHAack_typeextract_capabilitiesextract_want_line_capabilitiessymref_capabilities)ANNOTATED_TAG_SUFFIXwrite_info_refs)BaseRepoRepoc                       \ rS rSrSrS rSrg)Backend}   z2A backend for the Git smart server implementation.c                 ,    [        U R                  5      e)zOpen the repository at a path.

Args:
  path: Path to the repository
Raises:
  NotGitRepository: no git repository was found at path
Returns: Instance of BackendRepo
)NotImplementedErroropen_repositoryselfpaths     !lib/third_party/dulwich/server.pyrB   Backend.open_repository   s     "$"6"677     N)__name__
__module____qualname____firstlineno____doc__rB   __static_attributes__rI   rH   rF   r>   r>   }   s
    <	8rH   r>   c                   Z    \ rS rSrSrSrSrS\\\4   4S jr	S\S\
\   4S jrS
S jrS	rg)BackendRepo   zRepository abstraction used by the Git server.

The methods required here are a subset of those provided by
dulwich.repo.Repo.
Nreturnc                     [         e)zB
Get all the refs in the repository

Returns: dict of name -> sha
rA   rD   s    rF   get_refsBackendRepo.get_refs   s
     "!rH   namec                     g)ac  Return the cached peeled value of a ref, if available.

Args:
  name: Name of the ref to peel
Returns: The peeled value of the ref. If the ref is known not point to
    a tag, this will be the SHA the ref refers to. If no cached
    information about a tag is available, this method may return None,
    but it should attempt to peel the tag if possible.
NrI   )rD   rY   s     rF   
get_peeledBackendRepo.get_peeled   s     rH   c                     [         e)z
Yield the objects required for a list of commits.

Args:
  progress: is a callback to send progress messages to the client
  get_tagged: Function that returns a dict of pointed-to sha ->
    tag sha for including tags.
rU   )rD   determine_wantsgraph_walkerprogress
get_taggeds        rF   fetch_objectsBackendRepo.fetch_objects   s
     "!rH   rI   N)rJ   rK   rL   rM   rN   object_storerefsr   bytesrW   r   r[   rb   rO   rI   rH   rF   rQ   rQ      sD     LD"$ue|, "
u 
% 
	"rH   rQ   c                   0    \ rS rSrSrS rS\S\4S jrSr	g)	DictBackend   z?Trivial backend that looks up Git repositories in a dictionary.c                     Xl         g rd   repos)rD   rm   s     rF   __init__DictBackend.__init__   s    
rH   rE   rS   c                     [         R                  SU5         U R                  U   $ ! [         a    [	        S[        US9-  5      ef = f)NzOpening repository at %sz'No git repository was found at %(path)s)rE   )loggerdebugrm   KeyErrorr   dictrC   s     rF   rB   DictBackend.open_repository   sM    /6	::d## 	"9DdOK 	s	   '  Arl   N)
rJ   rK   rL   rM   rN   rn   strr;   rB   rO   rI   rH   rF   ri   ri      s    IC H rH   ri   c                   L   ^  \ rS rSrSr\R                  4U 4S jjrS rSr	U =r
$ )FileSystemBackend   zDSimple backend looking up Git repositories in the local file system.c                    > [         [        U ]  5         [        R                  R                  U5      [        R                  -   R                  [        R                  S-  [        R                  5      U l        g )N   )	superrx   rn   osrE   abspathsepreplaceroot)rD   r   	__class__s     rF   rn   FileSystemBackend.__init__   sG    /1WW__T*RVV3<<RVVaZP	rH   c                    [         R                  SU5        [        R                  R	                  [        R                  R                  U R                  U5      5      [        R                  -   n[        R                  R                  U5      n[        R                  R                  U R                  5      nUR                  U5      (       d  [        SU< SU R                  < 35      e[        U5      $ )Nzopening repository at %szPath z not inside root )rq   rr   r}   rE   r~   joinr   r   normcase
startswithr   r<   )rD   rE   r~   normcase_abspathnormcase_roots        rF   rB   !FileSystemBackend.open_repository   s    /6''//"'',,tyy$"?@266I77++G4((3**=99"4#STTG}rH   )r   )rJ   rK   rL   rM   rN   r}   r   rn   rB   rO   __classcell__r   s   @rF   rx   rx      s    NFF Q rH   rx   c                   (    \ rS rSrSrSS jrS rSrg)Handler   z*Smart protocol command handler base class.Nc                 (    Xl         X l        X0l        g rd   backendprotostateless_rpc)rD   r   r   r   s       rF   rn   Handler.__init__   s    
*rH   c                 ,    [        U R                  5      erd   )rA   handlerV   s    rF   r   Handler.handle   s    !$++..rH   r   rd   )rJ   rK   rL   rM   rN   rn   r   rO   rI   rH   rF   r   r      s    4+
/rH   r   c                      ^  \ rS rSrSrSU 4S jjr\S 5       r\S\\	   4S j5       r
\S\\	   4S j5       r\S\\	   4S	 j5       rS
\\	   SS4S jrS\	S\4S jrSS jrSrU =r$ )PackHandler   zProtocol handler for packs.Nc                 J   > [         [        U ]  XU5        S U l        SU l        g NF)r|   r   rn   _client_capabilities_done_received)rD   r   r   r   r   s       rF   rn   PackHandler.__init__   s$    k4)'-H$(!#rH   c                     [         R                  SU5        SR                  U Vs/ s H  nSU-   PM
     sn5      $ s  snf )NzSending capabilities: %srH       )rq   infor   )clscapabilitiescs      rF   capability_linePackHandler.capability_line   s6    .=xx<8<a<8998s   <rS   c                 ,    [        U R                  5      erd   )rA   r   r   s    rF   r   PackHandler.capabilities   s    !#"2"233rH   c                 @    [         [        [        [        [	        5       /$ rd   )r   r#   r   r   r   r   s    rF   innocuous_capabilities"PackHandler.innocuous_capabilities   s      # " 
 	
rH   c                     / $ )zAReturn a list of capabilities that we require the client to have.rI   r   s    rF   required_capabilities!PackHandler.required_capabilities   s	     	rH   capsc                    [        U R                  5       5      nUR                  U R                  5       5        U H5  nUR	                  [
        S-   5      (       a  M"  X2;  d  M)  [        SU-  5      e   U R                  5        H  nX1;  d  M
  [        SU-  5      e   [        U5      U l        [        R                  SU5        g )N   =z7Client asked for capability %r that was not advertised.z/Client does not support required capability %r.zClient capabilities: %s)setr   updater   r   r   r   r   r   rq   r   )rD   r   allowable_capscaps       rF   set_client_capabilities#PackHandler.set_client_capabilities  s    T88:;d//12C~~.566(&PSVV 	  --/C&H3N  0
 %(I!-t4rH   r   c                 T    U R                   c  [        SU-  5      eXR                   ;   $ )Nz=Server attempted to access capability %r before asking client)r   r   )rD   r   s     rF   has_capabilityPackHandler.has_capability  s5    $$,"RUXX  ////rH   c                     SU l         g )NT)r   rV   s    rF   notify_donePackHandler.notify_done  s
    "rH   )r   r   rd   rS   N)rJ   rK   rL   rM   rN   rn   classmethodr   r   rg   r   r   r   r   boolr   r   rO   r   r   s   @rF   r   r      s    %$ : : 4Xe_ 4 4 
x 
 
 huo  5HUO 5 5$0% 0D 0# #rH   r   c                   f   ^  \ rS rSrSrS
U 4S jjr\S 5       r\S 5       rS r	SS jr
S rS	rU =r$ )UploadPackHandleri!  z4Protocol handler for uploading a pack to the client.c                    > [         [        U ]  XUS9  UR                  US   5      U l        S U l        XPl        SU l        g )Nr   r   F)r|   r   rn   rB   repo_graph_walkeradvertise_refs_processing_have_linesrD   r   argsr   r   r   r   s         rF   rn   UploadPackHandler.__init__$  sM    /- 	0 	
 ++DG4	!, ',#rH   c           	      `    [         [        [        [        [        [
        [        [        [        /	$ rd   )	r   r   r"   r#   r   r   r   r!   r   r   s    rF   r   UploadPackHandler.capabilities0  s)     * $  ""

 
	
rH   c                 $    [         [        [        4$ rd   )r"   r#   r   r   s    rF   r   'UploadPackHandler.required_capabilities>  s     %  
 	
rH   c                     U R                  [        5      (       d  U R                  (       a  g U R                  R	                  [
        U5        g rd   )r   r   r   r   write_sidebandr0   )rD   messages     rF   r`   UploadPackHandler.progressF  s4    566$:U:U

!!"<gFrH   c                 $   U R                  [        5      (       d  0 $ Uc  U R                  R                  5       nUc  [	        U R                  SS5      nUc  0 $ 0 nUR                  5        H!  u  pEUR                  U5      nXe:w  d  M  XSU'   M#     U$ )a|  Get a dict of peeled values of tags to their original tag shas.

Args:
  refs: dict of refname -> sha of possible tags; defaults to all
    of the backend's refs.
  repo: optional Repo instance for getting peeled refs; defaults
    to the backend's repo, if available
Returns: dict of peeled_sha -> tag_sha, where tag_sha is the sha of a
    tag whose peeled value is peeled_sha.
Nr   )r   r   r   rW   getattritemsr[   )rD   rf   r   taggedrY   sha
peeled_shas          rF   ra   UploadPackHandler.get_taggedK  s     ""#9::I<99%%'D<499fd3D|
 	 ID.J %(z" & rH   c                   ^ ^^ U 4S jn[        T T R                  R                  T R                  R                  T R                  R                  R
                  5      m/ mUU4S jnT R                  R                  UTT R                  T R                  S9nST l	        [        T5      S:X  a  g ST l	        TR                  T R                  [        5      (       + T R                  5      (       d  g T R                  S[        U5      -  R                  S5      5        [!        [#        S U5      U5        T R$                  R'                  S 5        g )	Nc                 D   > TR                   R                  [        U 5      $ rd   r   r   r/   xrD   s    rF   write'UploadPackHandler.handle.<locals>.writel      ::,,-CQGGrH   c                 H   > TR                  TR                  U 5      5        T$ rd   )extendr^   )rf   r_   wantss    rF   wants_wrapper/UploadPackHandler.handle.<locals>.wants_wrapperw  s    LL55d;<LrH   )ra   Tr   Fzcounting objects: %d, done.
ascii)_ProtocolGraphWalkerr   re   r[   rf   get_symrefsrb   r`   ra   r   lenhandle_doner   r   r   encoder   r-   r   write_pkt_line)rD   r   r   objects_iterr_   r   s   `   @@rF   r   UploadPackHandler.handlek  s   	H ,II""II  IINN&&	
 	 yy..MM	 / 
 '+# u:? ',#''##$6779L9L
 
 ,s</@@HHQ	
 	<e4lC

!!$'rH   )r   r   r   r   r   )NN)rJ   rK   rL   rM   rN   rn   r   r   r   r`   ra   r   rO   r   r   s   @rF   r   r   !  sI    >
, 
 
 
 
G
@3( 3(rH   r   c                    U (       d  S/nO!U R                  S5      R                  SS5      nUS   nUb  X1;  a  [        U5      e[        U5      S:X  a  U[        S4;   a  US4$ [        U5      S:X  a]  U[
        [        [        [        4;   a)  [        US   5      (       d  [        S5      e[        U5      $ U[        :X  a  U[        US   5      4$ [        SU -  5      e)	a'  Split a line read from the wire.

Args:
  line: The line read from the wire.
  allowed: An iterable of command names that should be allowed.
    Command names not listed below as possible return values will be
    ignored.  If None, any commands from the possible return values are
    allowed.
Returns: a tuple having one of the following forms:
    ('want', obj_id)
    ('have', obj_id)
    ('done', None)
    (None, None)  (for a flush-pkt)

Raises:
  UnexpectedCommandError: if the line cannot be parsed into one of the
    allowed return values.
N   
r      r   r{   zInvalid shaz%Received invalid line from client: %r)rstripsplitr   r   r%   r)   r&   r'   r(   r   r   tupler$   int)lineallowedfieldscommands       rF   _split_proto_liner     s    & U#))$2QiGw5$W--
6{aGd';;	V		
 
  q	**&}55= &Cq	N**
BTI
JJrH   c                   ^ ^^ 0 mUU 4S jn/ nU HH  nT R                  U5      n[        U[        5      (       d  M+  UR                  UR                  S45        MJ     [        5       n[        5       nU(       ai  UR                  5       u  pX:  a8  UR                  U	5        U
S-   mUR                  U4S jU" U	5       5       5        OUR                  U	5        U(       a  Mi  X4$ )a  Find shallow commits according to a given depth.

Args:
  store: An ObjectStore for looking up objects.
  heads: Iterable of head SHAs to start walking from.
  depth: The depth of ancestors to include. A depth of one includes
    only the heads themselves.
Returns: A tuple of (shallow, not_shallow), sets of SHAs that should be
    considered shallow and unshallow according to the arguments. Note that
    these sets may overlap if a commit is reachable along multiple paths.
c                 b   > TR                  U S 5      nU(       d  TU    R                  nUTU '   U$ rd   )getparents)r   resultr  stores     rF   get_parents"_find_shallow.<locals>.get_parents  s3    S$'3Z''F!GCLrH   r   c              3   *   >#    U  H  oT4v   M
     g 7frd   rI   ).0p	new_depths     rF   	<genexpr> _find_shallow.<locals>.<genexpr>  s     A0@1I0@s   )	peel_sha
isinstancer   appendidr   popaddr   )r  headsdepthr  todohead_shaobjnot_shallowshallowr   	cur_depthr  r  s   `          @@rF   _find_shallowr    s     G DnnX&c6""KK$ 
 %KeG
OOC !AIKKAC0@AAKK $ rH   c                 |   X   n[         R                  " U/5      n[        U/5      nU(       a  UR                  5       nUR                  U;   a  gUR
                  S:w  a  M:  UR                   HB  nX;   a  M
  UR                  U5        X   n	U	R                  U:  d  M1  UR                  U	5        MD     U(       a  M  g)NTs   commitF)
collectionsdequer   popleftr  	type_namer  r  commit_timer  )
r  haveswantearliestopendingknowncommitparent
parent_objs
             rF   _want_satisfiedr,    s    A$GKE
"99y(nnFIIfJ%%1z* % ' rH   c                     [        U5      nU(       a)  [        U Vs/ s H  o0U   R                  PM     sn5      nOSnU H  n[        XXT5      (       a  M    g   gs  snf )ab  Check whether all the current wants are satisfied by a set of haves.

Args:
  store: Object store to retrieve objects from
  haves: A set of commits we know the client has.
  wants: A set of commits the client wants
Note: Wants are specified with set_wants rather than passed in since
    in the current interface they are determined outside this class.
r   FT)r   minr"  r,  )r  r#  r   hr%  r$  s         rF   _all_wants_satisfiedr0    sZ     JEe<ea,,e<=uT<<   =s   Ac                   z    \ rS rSrSrS rS rS rS rS r	S r
\
rS	 rS
 rS rSS jrS rS rS rS rS rSrg)r   i!  a  A graph walker that knows the git protocol.

As a graph walker, this class implements ack(), next(), and reset(). It
also contains some base methods for interacting with the wire and walking
the commit tree.

The work of determining which acks to send is passed on to the
implementation instance stored in _impl. The reason for this is that we do
not know at object creation time what ack level the protocol requires. A
call to set_ack_type() is required to set up the implementation, before
any calls to next() or ack() are made.
c                 :   Xl         X l        X0l        X@l        UR                  U l        UR
                  U l        UR                  U l        / U l        [        5       U l	        [        5       U l
        [        5       U l        SU l        / U l        SU l        S U l        g )NFr   )handlerr  r[   r   r   r   r   _wantsr   r  client_shallow	unshallow_cached_cache_cache_index_impl)rD   r3  re   r[   r   s        rF   rn   _ProtocolGraphWalker.__init__/  s~    !
$&]]
$22%44u!e
rH   c           
         U R                  5       n[        UR                  5       5      nU R                  (       d  U R                  (       Gd   [        [        UR                  5       5      5       H  u  nu  pV U R                  U5      nUS-   U-   nU(       dS  USU R                  R                  U R                  R                  5       [        UR                  5       5      -   5      -   -  nU R                  R                  US-   5        Xv:w  d  M  U R                  R                  US-   U-   [         -   S-   5        M     U R                  R                  S5        U R                  (       a  / $ U R                  R#                  5       n	U	(       d  / $ [%        U	5      u  pU R                  R'                  U
5        U R)                  [+        U
5      5        [,        [.        [0        S4n[3        X5      u  p/ nU[,        :X  aC  Xc;  a  [5        SU-  5      eUR7                  U5        U R9                  U5      u  pU[,        :X  a  MC  U R;                  U5        U[.        [0        4;   a"  U R=                  X5        U R?                  U5        U R                  (       a!  U R                  RA                  5       (       a  / $ U$ ! [         a     GMV  f = f)a  Determine the wants for a set of heads.

The given heads are advertised to the client, who then specifies which
refs they want using 'want' lines. This portion of the protocol is the
same regardless of ack type, and in fact is used to set the ack type of
the ProtocolGraphWalker.

If the client has the 'shallow' capability, this method also reads and
responds to the 'shallow' and 'deepen' lines from the client. These are
not part of the wants per se, but they set up necessary state for
walking the graph. Additionally, later code depends on this method
consuming everything up to the first 'have' line.

Args:
  heads: a dict of refname->SHA1 to advertise
Returns: a list of SHA1s requested by the client
r       r   NzClient wants invalid object %s)!r   r   valuesr   r   	enumeratesortedr   r[   rs   r3  r   r   r8   r   r   r9   read_pkt_liner7   r   set_ack_typer5   r)   r'   r$   r   r   r  read_proto_line	set_wantsunread_proto_line_handle_shallow_requesteof)rD   r  symrefsr>  irefr   r   r   r$  r   r   r   	want_revss                 rF   r^   $_ProtocolGraphWalker.determine_wants@  sT   $ ""$U\\^$d&8&8&8!*6%++-+@!A:C!%!5J TzC'Gdll&B&B113-gmmo>?'  D 

))$,7$JJ--"T)C/2FFN! "B* JJ%%d+""	 zz'')I3D9
,,T2(4.).$G(7	% &'G#'MNNS!//8LG	 % 	y!77""70((3$**.."2"2
 Ii    	s   8J77
KKc                     [        U[        5      (       a  [        U5      R                  S5      nU R                  R                  US-   U-   5        g )Nr   r   )r  r   rv   r   r   unread_pkt_line)rD   r   values      rF   rE  &_ProtocolGraphWalker.unread_proto_line  s>    eS!!J%%g.E

""7T>E#9:rH   c                 r    [        U5      S:w  a  [        SU-  5      eU R                  R                  U5      $ )N(   zinvalid sha %r)r   
ValueErrorr:  ackrD   have_refs     rF   rT  _ProtocolGraphWalker.ack  s2    x=B-899zz~~h''rH   c                      SU l         SU l        g )NTr   )r7  r9  rV   s    rF   reset_ProtocolGraphWalker.reset  s    rH   c                 8   U R                   (       d8  U R                  (       d  U R                  (       a  g [        U R                  5      $ U =R                  S-  sl        U R                  [        U R                  5      :  a  g U R                  U R                     $ )Nr   )r7  r:  r   nextr9  r   r8  rV   s    rF   r\  _ProtocolGraphWalker.next  sj    ||::$"4"4

##Qs4;;//{{4,,--rH   c                 J    [        U R                  R                  5       U5      $ )zRead a line from the wire.

Args:
  allowed: An iterable of command names that should be allowed.
Returns: A tuple of (command, value); see _split_proto_line.
Raises:
  UnexpectedCommandError: If an error occurred reading the line.
)r   r   rA  )rD   r   s     rF   rC  $_ProtocolGraphWalker.read_proto_line  s     !!9!9!;WEErH   c                     U R                  [        [        45      u  p#U[        :X  a  UnOU R                  R	                  U5        MG  U R                  S5        [        U R                  X5      u  pVU R                  R                  XV-
  5        U R                  U R                  -
  nX`R                  -  =ol	        [        U5       H(  n	U R                  R                  [        S-   U	-   5        M*     [        U5       H(  n	U R                  R                  [        S-   U	-   5        M*     U R                  R                  S 5        g )Nrd   r   )rC  r$   r'   r5  r  r  r  r  r   r6  r@  r   r   r(   )
rD   r   r   valr  r  r  new_shallowr6  r   s
             rF   rF  ,_ProtocolGraphWalker._handle_shallow_request  s   //0QRLG.(##C(  	W%,TZZF 	G12llT%8%88%03F3F%FF	N+&CJJ%%o&<s&BC ')$CJJ%%&7$&>&DE % 	

!!$'rH   c                 8    U R                   R                  5         g rd   )r3  r   rV   s    rF   r    _ProtocolGraphWalker.notify_done  s      "rH   c                 d    U(       a  SU-   nU R                   R                  SU-   U-   S-   5        g )Nr   s   ACK r   r   r   )rD   r   r5   s      rF   send_ack_ProtocolGraphWalker.send_ack  s.    hH

!!'C-(":U"BCrH   c                 :    U R                   R                  S5        g )Ns   NAK
rg  rV   s    rF   send_nak_ProtocolGraphWalker.send_nak  s    

!!(+rH   c                 8    U R                   R                  X5      $ rd   )r:  r   rD   done_requireddone_receiveds      rF   r    _ProtocolGraphWalker.handle_done  s    zz%%mCCrH   c                     Xl         g rd   )r4  )rD   r   s     rF   rD  _ProtocolGraphWalker.set_wants  s    rH   c                 B    [        U R                  XR                  5      $ )a  Check whether all the current wants are satisfied by a set of haves.

Args:
  haves: A set of commits we know the client has.
Note: Wants are specified with set_wants rather than passed in since
    in the current interface they are determined outside this class.
)r0  r  r4  )rD   r#  s     rF   all_wants_satisfied(_ProtocolGraphWalker.all_wants_satisfied  s     $DJJ{{CCrH   c                 b    [         [        [        [        [        [
        0nX!   " U 5      U l        g rd   )r*   MultiAckGraphWalkerImplr+   MultiAckDetailedGraphWalkerImplr2   SingleAckGraphWalkerImplr:  )rD   r5   impl_classess      rF   rB  !_ProtocolGraphWalker.set_ack_type  s,    . ?0

 "+D1
rH   )r8  r9  r7  r:  r4  r   r5  r[   r   r3  r   r  r   r  r6  N)rH   )rJ   rK   rL   rM   rN   rn   r^   rE  rT  rY  r\  __next__rC  rF  r   rh  rk  r   rD  ru  rB  rO   rI   rH   rF   r   r   !  s_    "L\;
(
. H	F(0#D
,DD2rH   r   c                   4    \ rS rSrSrS rS rS r\rS r	Sr
g)	rz  i  z@Graph walker implementation that speaks the single-ack protocol.c                     Xl         / U l        g rd   walker_commonrD   r  s     rF   rn   !SingleAckGraphWalkerImpl.__init__      rH   c                     U R                   (       d7  U R                  R                  U5        U R                   R                  U5        g g rd   )r  r  rh  r  rU  s     rF   rT  SingleAckGraphWalkerImpl.ack  s2    ||KK  *LL) rH   c                     U R                   R                  [        5      u  pUS [        4;   a  U R                   R	                  5         g U[
        :X  a  U$ g rd   )r  rC  _GRAPH_WALKER_COMMANDSr%   r   r&   rD   r   r   s      rF   r\  SingleAckGraphWalkerImpl.next   sK    {{223IJt\**KK##%$J %rH   c                     U R                   (       d  U R                  R                  5         U(       a  U(       d  gU(       d  U R                   (       d  gg)NFT)r  r  rk  rn  s      rF   r   $SingleAckGraphWalkerImpl.handle_done  s4    ||KK  " T\\ rH   r  r  NrJ   rK   rL   rM   rN   rn   rT  r\  r}  r   rO   rI   rH   rF   rz  rz    s     J*
 HrH   rz  c                   4    \ rS rSrSrS rS rS r\rS r	Sr
g)	rx  i   z?Graph walker implementation that speaks the multi-ack protocol.c                 ,    Xl         SU l        / U l        g r   )r  _found_baser  r  s     rF   rn    MultiAckGraphWalkerImpl.__init__#  s     rH   c                     U R                   R                  U5        U R                  (       dO  U R                  R	                  US5        U R                  R                  U R                   5      (       a  SU l        g g g )N   continueT)r  r  r  r  rh  ru  rU  s     rF   rT  MultiAckGraphWalkerImpl.ack(  s\    H%KK  ;7{{..t||<<#'  =  rH   c                 D    U R                   R                  [        5      u  pUc  U R                   R                  5         MA  U[        :X  a  U R                   R                  5         g U[        :X  a/  U R                  (       a  U R                   R                  US5        U$ M  )Nr  )	r  rC  r  rk  r%   r   r&   r  rh  r  s      rF   r\  MultiAckGraphWalkerImpl.next0  s    ;;667MNLG$$& L('')L(##KK((k:
 rH   c                     U(       a  U(       d  gU(       d  U R                   (       d  gU R                   (       a)  U R                  R                  U R                   S   5        gU R                  R                  5         gNFTr  r  rh  rk  rn  s      rF   r   #MultiAckGraphWalkerImpl.handle_doneC  X     T\\  <<KK  b!12  KK  "rH   )r  r  r  Nr  rI   rH   rF   rx  rx     s     I
(" HrH   rx  c                   4    \ rS rSrSrS rS rS r\rS r	Sr
g)	ry  i[  zEGraph walker implementation speaking the multi-ack-detailed protocol.c                     Xl         / U l        g rd   r  r  s     rF   rn   (MultiAckDetailedGraphWalkerImpl.__init__^  r  rH   c                 r    U R                   R                  U5        U R                  R                  US5        g )Ns   common)r  r  r  rh  rU  s     rF   rT  #MultiAckDetailedGraphWalkerImpl.ackb  s(    H%Xy1rH   c                     U R                   R                  [        5      u  pUc  U R                   R                  U R                  5      (       a)  U R                   R                  U R                  S   S5        U R                   R                  5         U R                   R                  (       a  g O1U[        :X  a  U R                   R                  5         g U[        :X  a  U$ M  )Nr  s   ready)r  rC  r  ru  r  rh  rk  r   r%   r   r&   r  s      rF   r\  $MultiAckDetailedGraphWalkerImpl.nextg  s    ;;667MNLG;;224<<@@KK((b)98D$$&;;,,   - L('')L( 
- rH   c                     U(       a  U(       d  gU(       d  U R                   (       d  gU R                   (       a)  U R                  R                  U R                   S   5        gU R                  R                  5         gr  r  rn  s      rF   r   +MultiAckDetailedGraphWalkerImpl.handle_done  r  rH   r  Nr  rI   rH   rF   ry  ry  [  s     O2
6 HrH   ry  c                      ^  \ rS rSrSrSU 4S jjr\S\\   4S j5       r	S\
\\\\4      S\
\\\4      4S jrS	\
\\\4      SS4S
 jrS rSS jrSrU =r$ )ReceivePackHandleri  z8Protocol handler for downloading a pack from the client.Nc                 h   > [         [        U ]  XUS9  UR                  US   5      U l        XPl        g )Nr   r   )r|   r  rn   rB   r   r   r   s         rF   rn   ReceivePackHandler.__init__  s;     $0- 	1 	
 ++DG4	,rH   rS   c                 B    [         [        [        [        [        [
        /$ rd   )r    r   r   r   r"   r   r   s    rF   r   ReceivePackHandler.capabilities  s      %" $
 	
rH   rf   c                    [         [        [        [        [        [
        R                  [        R                  [        4n/ nSnU H  nUS   [        :w  d  M  SnM     U(       ad   [        U R                  SS 5      nU R                  R                  R                  U R                  R                  U5        UR!                  S5        OUR!                  S5        U H  u  pn
S
n U	[        :X  aJ  [(        U R+                  5       ;  a  [-        S5      e U R                  R.                  R1                  X5        O' U R                  R.                  R3                  XU	5        UR!                  X45        M     U$ ! U aE  nUR!                  S[#        U5      R%                  SS5      R'                  S	5      45         S nANS nAff = f! U a    Sn Npf = f! U a    Sn N~f = f! [4         a    Sn Nf = f)NFr   Trecv)   unpack   okr  
 utf-8r  z8Attempted to delete refs without delete-refs capability.s   failed to deletes   failed to writes   bad ref)IOErrorOSErrorr
   r	   AssertionErrorsocketerrorzlibr   r4   r   r   r   re   add_thin_packreadr  rv   r   r   r   r   r   rf   remove_if_equalsset_if_equalsrs   )rD   rf   all_exceptionsstatuswill_send_packr   r  eoldshar   rJ  
ref_statuss               rF   _apply_packReceivePackHandler._apply_pack  s    LLJJ!	
 GqzX%!%  Utzz648		&&44TZZ__dK01 MM,- $FJ((?-T5F5F5HH.* 9		77D8		44S#F
 MM3+,) !%, ? " Uy#a&..r*B*I*I'*RSTTU( * 9%8
9
 * 8%7
8 ('
(sg   %A"E7 $-G!%G9&G7G=;F==GGG!GG!GG!GG!!G0/G0r  c                 h  ^ ^ T R                  [        5      (       a#  [        U 4S j5      mTR                  nU U4S jnOT R                  R
                  nS nU HE  u  pEUS:X  a  U" SU-   S-   5        M  US:X  a  U" SU-   S-   5        M1  U" S	U-   S
-   U-   S-   5        MG     U" S 5        U" 5         g )Nc                 D   > TR                   R                  [        U 5      $ rd   r   )drD   s    rF   <lambda>3ReceivePackHandler._report_status.<locals>.<lambda>  s    $**334JANrH   c                  \   > TR                  5         T R                  R                  S 5        g rd   )flushr   r   )rD   writers   rF   r  0ReceivePackHandler._report_status.<locals>.flush  s    

))$/rH   c                      g rd   rI   rI   rH   rF   r  r    s    rH   r  s   unpack r   r  s   ok s   ng r   )r   r"   r   r   r   r   )rD   r  r   r  rY   msgr  s   `     @rF   _report_status!ReceivePackHandler._report_status  s    788*NF LLE0
 JJ--E  IDy j3&./ftme+,ftmd*S0589   	drH   c                 r   U R                   R                  R                  SS 5      nU(       d  g  UR                  U5      nU(       a!  U R                  R                  [        U5        g g ! [         aB  nU R                  R                  [        [        U5      R                  S5      5         S nAg S nAff = f)Nzpost-receiver  )r   hooksr  executer   r   r0   r   r1   rv   r   )rD   client_refshookoutputerrs        rF   _on_post_receive#ReceivePackHandler._on_post_receive  s    yy"">48	Y\\+.F

))*DfM  	YJJ%%&=s3xw?WXX	Ys   8A* *
B648B11B6c           	         U R                   (       d  U R                  (       GdV  [        U R                  R	                  5       R                  5       5      n[        U R                  R                  R                  5       R                  5       5      nU(       d  [        [        4/nU R                  R                  US   S   S-   US   S   -   S-   U R                  U R                  5       [        U5      -   5      -   S-   5        [        S[!        U5      5       H1  nX   nU R                  R                  US   S-   US   -   S-   5        M3     U R                  R                  S 5        U R                   (       a  g / nU R                  R#                  5       nUc  g [%        U5      u  pFU R'                  U5        U(       aB  UR)                  UR+                  5       5        U R                  R#                  5       nU(       a  MB  U R-                  U5      nU R/                  U5        U R1                  [2        5      (       a  U R5                  U5        g g )Nr   r   r   r=  r   )r   r   r@  r   rW   r   rf   r   r   r4   r   r   r   r   r8   ranger   rA  r6   r   r  r   r  r  r   r    r  )rD   rf   rH  rI  rJ  r  r   r  s           rF   r   ReceivePackHandler.handle  s   d&8&8&8$)),,.4467DTYY^^779??ABG)845JJ%%Q
q'!*  &&%%'*=g*FF	 	 1c$i(g

))#a&4-#a&*@5*HI ) JJ%%d+""jj&&( ;(-	$$T* syy{+****,C c
 !!+.k* 788' 9rH   )r   r   r   r   )rJ   rK   rL   rM   rN   rn   r   r   rg   r   r   r   r  r  r  r   rO   r   r   s   @rF   r  r    s    B- 
Xe_ 
 
:ueU234:	eE5L!	":xT%u*=%> 4 6	Y0( 0(rH   r  c                   2   ^  \ rS rSrSU 4S jjrS rSrU =r$ )UploadArchiveHandleriF  c                 `   > [         [        U ]  XU5        UR                  US   5      U l        g )Nr   )r|   r  rn   rB   r   )rD   r   r   r   r   r   s        rF   rn   UploadArchiveHandler.__init__G  s+    "D27=Q++DG4	rH   c                 "  ^  U 4S jn/ nT R                   R                  5        HK  nUR                  SS5      u  pEUS:w  a  [        SU-  5      eUR	                  UR                  S5      5        MM     SnSnS	nT R                  R                  n	U[        U5      :  as  X(   n
U
S
:X  a
  US-  nX(   nOIU
S:X  a  US-  nX(   R                  S5      nO*T R                  R                  U
   nXU   R                     nUS-  nU[        U5      :  a  Ms  T R                   R                  S5        T R                   R                  S 5        [        U	W[        R                  " 5       XgS9 H  nU" U5        M     T R                   R                  S 5        g )Nc                 D   > TR                   R                  [        U 5      $ rd   r   r   s    rF   r   *UploadArchiveHandler.handle.<locals>.writeL  r   rH   r   r   s   argumentzunknown command %sr   rH   tarr   s   --prefixs   --formatr   s   ACK)mtimeprefixformat)r   read_pkt_seqr   r   r  r   r   re   r   decoderf   treer   r   time)rD   r   	argumentspktkeyrO  r  r  rI  r  argument
commit_shar  chunks   `             rF   r   UploadArchiveHandler.handleK  st   	H 	::**,C99T1-LSk!&';c'ABBU\\%01	 -
 		&&#i.  |H;&Q"[(Q",,W5!YY^^H5
:.334FA #i.  	

!!&)

!!$'4tyy{6
E %L
 	

!!$'rH   r   rd   )rJ   rK   rL   rM   rn   r   rO   r   r   s   @rF   r  r  F  s    5 (  (rH   r  )s   git-upload-packs   git-receive-packs   git-upload-archivec                        \ rS rSrS rS rSrg)TCPGitRequestHandleriv  c                 X    Xl         [        R                  R                  " U /UQ70 UD6  g rd   )handlerssocketserverStreamRequestHandlerrn   )rD   r  r   kwargss       rF   rn   TCPGitRequestHandler.__init__w  s%     ))224I$I&IrH   c                    [        U R                  R                  U R                  R                  5      nUR                  5       u  p#[        R                  SX#5        U R                  R                  US 5      n[        U5      (       d  [        SU-  5      eU" U R                  R                  X15      nUR                  5         g )NzHandling %s request, args=%szInvalid service %s)r.   
connectionr  wfiler   read_cmdrq   r   r  r  callabler   serverr   r   )rD   r   r   r   r   r/  s         rF   r   TCPGitRequestHandler.handle{  s    "4??#7#79I9IJ(2GBmm.}}"#7'#ABB##T1	
rH   )r  N)rJ   rK   rL   rM   rn   r   rO   rI   rH   rF   r  r  v  s    J	rH   r  c                   d    \ rS rSrSr\R                  R                  rS r	\
S4S jrS rS rSrg)	TCPGitServeri  Tc                 4    [        U R                  /UQ70 UD6$ rd   )r  r  )rD   r   r  s      rF   _make_handlerTCPGitServer._make_handler  s    #DMMCDCFCCrH   Nc                     [        [        5      U l        Ub  U R                  R                  U5        Xl        [
        R                  SX#5        [        R                  R                  XU4U R                  5        g )Nz&Listening for TCP connections on %s:%d)rt   DEFAULT_HANDLERSr  r   r   rq   r   r  	TCPServerrn   r	  )rD   r   listen_addrportr  s        rF   rn   TCPGitServer.__init__  s\    -.MM  *<kP''D.A4CUCUVrH   c                 0    [         R                  SU5        g)NzHandling request from %sT)rq   r   rD   requestclient_addresss      rF   verify_requestTCPGitServer.verify_request  s    .?rH   c                 0    [         R                  SU5        g )Nz7Exception happened during processing of request from %s)rq   	exceptionr  s      rF   handle_errorTCPGitServer.handle_error  s    H	
rH   )r   r  )rJ   rK   rL   rM   allow_reuse_addressr  r  serve_foreverserver	  r3   rn   r  r  rO   rI   rH   rF   r  r    s6    ""00ED 3? W
rH   r  c           	      ~   SSK nUR                  5       nUR                  SSSSSS9  UR                  S	S
S[        [        SS9  UR                  U 5      u  p4[        R                  " 5         [        U5      S:  a  US   nOSn[        U5      n[        XcR                  UR                  5      nUR                  5         g)z*Entry point for starting a TCP git server.r   Nz-lz--listen_addresslisten_address	localhostzBinding IP address.)destdefaulthelpz-pz--portr  zBinding TCP port.)r!  typer"  r#  r   .)optparseOptionParser
add_optionr   r3   
parse_argsr   default_logging_configr   rx   r  r  r  r  )argvr&  parseroptionsr   gitdirr   r  s           rF   mainr/    s    ""$F
"       %%d+MG$$&
4y1}a'G'#9#97<<HF
rH   c                    ^ Uc
  [        5       nU4S jn[        UR                  U5      nU " X!SS U5      nUR                  5         g)a  Serve a single command.

This is mostly useful for the implementation of commands used by e.g.
git+ssh.

Args:
  handler_cls: `Handler` class to use for the request
  argv: execv-style command-line arguments. Defaults to sys.argv.
  backend: `Backend` to use
  inf: File-like object to read from, defaults to standard input.
  outf: File-like object to write to, defaults to standard output.
Returns: Exit code for use with sys.exit. 0 on success, 1 on failure.
Nc                 H   > TR                  U 5        TR                  5         g rd   )r   r  )dataoutfs    rF   send_fnserve_command.<locals>.send_fn  s    

4

rH   r   r   )rx   r,   r  r   )handler_clsr+  r   infr3  r4  r   r3  s       `   rF   serve_commandr8    sH      #% SXXw'E'8U3GNNrH   c                 L    U R                  5       n[        XR                  5      $ )zGenerate an info refs file.)rW   r:   re   )r   rf   s     rF   generate_info_refsr:    s    ==?D4!2!233rH   c              #      #    U R                   R                   H5  nS[        R                  " UR                  R
                  5      -   S-   v   M7     g7f)z Generate an index for for packs.s   P r   N)re   packsr}   fsencoder2  filename)r   packs     rF   generate_objects_info_packsr@    s>     !!''r{{499#5#566>? (s   AAc                 &   U R                  [        R                  R                  SS5      SR                  [	        U 5      5      5        U R                  [        R                  R                  SSS5      SR                  [        U 5      5      5        g)zGenerate server info for dumb file access.

This generates info/refs and objects/info/packs,
similar to "git update-server-info".
r   rf   rH   objectsr<  N)_put_named_filer}   rE   r   r:  r@  r  s    rF   update_server_inforD    sk     	
VV$chh/A$/G&H 	
Y0,T23rH   __main__)nrN   r  r}   r  sysr  typingr   r   r   r   r   r  r  dulwich.archiver   dulwich.errorsr	   r
   r   r   r   r   r   dulwichr   dulwich.objectsr   r   dulwich.packr   dulwich.protocolr   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   dulwich.refsr9   r:   dulwich.repor;   r<   	getLoggerrJ   rq   objectr>   rQ   ri   rx   r   r   r   r   r  r,  r0  r   r  rz  rx  ry  r  r  r  r  r  r  r  r+  r/  stdinstdoutr8  r:  r@  rD  rI   rH   rF   <module>rT     s  ,.  	  
  8 8   &   & & & & & & & & & &N 
		X	&8f 8'"& '"T'   "	/f 	/;#' ;#|}( }(@(KV& R,,M26 M2` 'd; )v )X8f 8v>f >Bg( g(T%(7 %(T *+/ <<< "
<)) 
6 hh D hh#))#**<4@  zF rH   