
    G                     \   S r SSKJr  SSKrSSK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  SSKJrJrJrJr  SSKJr  SSKJr  SSKJr  SS	KJrJrJr  SS
KJrJrJ r J!r!  \RD                  " \#5      r$Sr%Sr&Sr'Sr(S0S\\)   S\*4S jjr+S\*4S jr,S\4S jr-S r.S r/S r0S r1S r2S r3S r4S r5 " S S\65      r7S r8 " S S \65      r9 " S! S"\65      r: " S# S$\65      r; " S% S&\65      r<S' r= " S( S)\5      r> " S* S+\5      r? " S, S-\5      r@\R                  4S. jrB\#S/:X  a  \B" 5         gg)1zDHTTP server for dulwich that implements the git smart HTTP protocol.    )BytesION)ListTupleOptional)WSGIRequestHandlerServerHandler
WSGIServermake_server)parse_qs)	log_utils)ReceivableProtocol)BaseRepoNotGitRepositoryRepo)DictBackendDEFAULT_HANDLERSgenerate_info_refsgenerate_objects_info_packsz200 OKz404 Not Foundz403 Forbiddenz500 Internal Server Error	timestampreturnc                     / SQn/ SQnU c  [         R                   " 5       n [         R                  " U 5      S S u  p4pVpxn	SX   UX$   UUUU4-  $ )N)MonTueWedThuFriSatSun)NJanFebMarAprMayJunJulAugSepOctNovDec   z#%s, %02d %3s %4d %02d:%02d:%02d GMD)timegmtime)
r   weekdaysmonthsyearmonthdayhhmmsswds
             lib/third_party/dulwich/web.pydate_time_stringr8   F   sm     AHF IIK	'+{{9'=bq'A$D""0


4      c                 `    SU R                   SU R                  5        R                  S5      -   $ )zExtract the URL prefix from a regex match.

Args:
  mat: A regex match object.
Returns: The URL prefix, defined as the text before the match in the
    original string. Normalized to start with one leading slash and end
    with zero.
/N)stringstartstrip)mats    r7   
url_prefixr@   k   s+     Mciik*00555r9   c                 6    U R                  [        U5      5      $ )z>Get a Repo instance for the given backend and URL regex match.)open_repositoryr@   )backendr?   s     r7   get_reporD   w   s    "":c?33r9   c              #   8  #    Uc  U R                  S5      v   g U R                  [        U5         UR                  S5      nU(       d  OUv   M  UR                  5         g! [         a    U R                  S5      v    N0f = f! UR                  5         f = f7f)a	  Send a file-like object to the request output.

Args:
  req: The HTTPGitRequest object to send output to.
  f: An open file-like object to send; will be closed.
  content_type: The MIME type for the file.
Returns: Iterator over the contents of the file, as chunks.
NzFile not foundi (  zError reading file)	not_foundrespondHTTP_OKreadIOErrorerrorclose)reqfcontent_typedatas       r7   	send_filerQ   |   s      	ymm,--
G\*66%=DJ	  	
	  .ii,--. 	
	s@   B/A" 
B A" B"B?B BB BBc                 V    U R                  S[        R                  R                  5      $ )Nr;   )replaceospathsep)urls    r7   _url_to_pathrX      s    ;;sBGGKK((r9   c                     U R                  5         [        UR                  5       5      n[        R	                  SU5        [        U [        X5      R                  U5      S5      $ )NzSending plain text file %s
text/plain)nocacherX   grouploggerinforQ   rD   get_named_filerM   rC   r?   rU   s       r7   get_text_filera      sI    KKM		$D
KK,d3S(70??E|TTr9   c              #     #    UR                  S5      UR                  S5      -   R                  S5      n[        R                  SU5        [	        X5      R
                  nUR                  U5      (       d  U R                  S5      v   g  XC   R                  5       nU R                  5         U R                  [        S5        Uv   g ! [         a    U R                  S5      v    g f = f7f)N      asciizSending loose object %szObject not foundzError reading objectzapplication/x-git-loose-object)r\   encoder]   r^   rD   object_storecontains_looserF   as_legacy_objectrJ   rK   cache_foreverrG   rH   )rM   rC   r?   sharg   rP   s         r7   get_loose_objectrl      s     99Q<#))A,&
.
.w
7C
KK)3/G)66L&&s++mm.// 113 KK9:
J  ii.//s*   BC+C +C+C(%C+'C((C+c                     U R                  5         [        UR                  5       5      n[        R	                  SU5        [        U [        X5      R                  U5      S5      $ )NSending pack file %sz application/x-git-packed-objectsrj   rX   r\   r]   r^   rQ   rD   r_   r`   s       r7   get_pack_filerp      sS    		$D
KK&---d3* r9   c                     U R                  5         [        UR                  5       5      n[        R	                  SU5        [        U [        X5      R                  U5      S5      $ )Nrn   z$application/x-git-packed-objects-tocro   r`   s       r7   get_idx_filerr      sS    		$D
KK&---d3. r9   c              #     #    [        U R                  S   5      nUR                  SS /5      S   n [        X5      nU(       Ga
  U R                  (       d  U R                  R                  UR                  S5      S 5      nUc  U R                  S5      v   g U R                  5         U R                  [        SU-  5      n[        [        5       R                   U5      n	U" U[#        U5      /U	U SS9n
U
R$                  R'                  S	UR                  S5      -   S
-   5        U
R$                  R'                  S 5        U
R)                  5         g U R                  5         U R                  [        S5        [*        R-                  S5        [/        U5       H  nUv   M	     g ! [         a&  nU R                  [        U5      5      v    S nAg S nAff = f7f)NQUERY_STRINGservicer   re   Unsupported servicezapplication/x-%s-advertisementT)stateless_rpcadvertise_refss
   # service=   
rZ   zEmulating dumb info/refs)r   environgetrD   r   rF   strdumbhandlersrf   	forbiddenr[   rG   rH   r   r   rI   r@   protowrite_pkt_linehandler]   r^   r   )rM   rC   r?   paramsru   repoehandler_clswriter   handlertexts               r7   get_info_refsr      sv    ckk.12FjjTF+A.G% sxxll&&w~~g'>E-- 566G%E%OP"79>>59_
 	$$]W^^G5L%Lu%TU$$T* 	G\*./&t,DJ -7  mmCF##s.   /GF! E$G!
G+GGGGc                     U R                  5         U R                  [        S5        [        R	                  S5        [        [        X5      5      $ )NrZ   zEmulating dumb info/packs)r[   rG   rH   r]   r^   r   rD   )rM   rC   r?   s      r7   get_info_packsr      s6    KKMKK&
KK+,&x'=>>r9   c                   (    \ rS rSrSrS rSS jrSrg)_LengthLimitedFile   zWrapper class to limit the length of reads from a file-like object.

This is used to ensure EOF is read from the wsgi.input object once
Content-Length bytes are read. This behavior is required by the WSGI spec
but not implemented in wsgiref as of 2.5.
c                     Xl         X l        g N)_input_bytes_avail)selfinput	max_bytess      r7   __init___LengthLimitedFile.__init__   s    %r9   c                     U R                   S::  a  gUS:X  d  XR                   :  a  U R                   nU =R                   U-  sl         U R                  R                  U5      $ )Nr   r9   )r   r   rI   )r   sizes     r7   rI   _LengthLimitedFile.read   sV    !2: 1 11$$DT!{{%%r9   )r   r   N)r   )__name__
__module____qualname____firstlineno____doc__r   rI   __static_attributes__ r9   r7   r   r      s    &&r9   r   c              #   T  #    UR                  5       R                  S5      n[        R                  SU5        U R                  R                  UR                  S5      S 5      nUc  U R                  S5      v   g  [        X5        U R                  5         U R                  [        SU-  5      n[        U R                   S   R"                  U5      nU" U[%        U5      /XpS9nUR'                  5         g ! [         a&  nU R                  [        U5      5      v    S nAg S nAff = f7f)Nr;   zHandling service request for %sre   rv   zapplication/x-%s-result
wsgi.input)rw   )r\   lstripr]   r^   r~   r{   rf   r   rD   r   rF   r|   r[   rG   rH   r   rz   rI   r@   r   )	rM   rC   r?   ru   r   r   r   r   r   s	            r7   handle_service_requestr   	  s     iik  %G
KK17;,,""7>>'#:DAKmm122 KKMKK!:W!DEEs{{<8==uEE 'JsO#4eOGNN  mmCF##s1   A8D(;C5 A/D(5
D%?D D( D%%D(c                       \ rS rSrSrSS\4S jjrS r\SS4S\	S\
\	   S	\
\\\	\	4         4S
 jjrS\	S\4S jrS\	S\4S jrS\	S\4S jrSS jrSS jrSrg)HTTPGitRequesti  zrClass encapsulating the state of a single git HTTP request.

:ivar environ: the WSGI environment for the request.
Nr}   c                 P    Xl         X0l        X@l        X l        / U l        / U l        g r   )rz   r}   r~   _start_response_cache_headers_headers)r   rz   start_responser}   r~   s        r7   r   HTTPGitRequest.__init__$  s&    	 - r9   c                 <    U R                   R                  X45        g)zAdd a header to the response.N)r   append)r   namevalues      r7   
add_headerHTTPGitRequest.add_header,  s    d]+r9   statusrO   headersc                    U(       a  U R                   R                  U5        U(       a  U R                   R                  SU45        U R                   R                  U R                  5        U R	                  XR                   5      $ )z9Begin a response with the given status and other headers.zContent-Type)r   extendr   r   r   )r   r   rO   r   s       r7   rG   HTTPGitRequest.respond0  s`     MM  )MM  .,!?@T001##FMM::r9   messager   c                     / U l         [        R                  SU5        U R                  [        S5        UR                  S5      $ )z;Begin a HTTP 404 response and return the text of a message.zNot found: %srZ   re   )r   r]   r^   rG   HTTP_NOT_FOUNDrf   r   r   s     r7   rF   HTTPGitRequest.not_found?  5     OW-^\2~~g&&r9   c                     / U l         [        R                  SU5        U R                  [        S5        UR                  S5      $ )z;Begin a HTTP 403 response and return the text of a message.zForbidden: %srZ   re   )r   r]   r^   rG   HTTP_FORBIDDENrf   r   s     r7   r   HTTPGitRequest.forbiddenF  r   r9   c                     / U l         [        R                  SU5        U R                  [        S5        UR                  S5      $ )z;Begin a HTTP 500 response and return the text of a message.z	Error: %srZ   re   )r   r]   rK   rG   
HTTP_ERRORrf   r   s     r7   rK   HTTPGitRequest.errorM  s5     ['*Z.~~g&&r9   c                     / SQU l         g)z2Set the response to never be cached by the client.))ExpireszFri, 01 Jan 1980 00:00:00 GMT)Pragmazno-cache)Cache-Controlz$no-cache, max-age=0, must-revalidateN)r   )r   s    r7   r[   HTTPGitRequest.nocacheT  s    
r9   c                 t    [         R                   " 5       nS[        U5      4S[        US-   5      4S/U l        g)z4Set the response to be cached forever by the client.Dater   i3)r   zpublic, max-age=31536000N)r,   r8   r   )r   nows     r7   rj   HTTPGitRequest.cache_forever\  s:    iik%c*+(x899
r9   )r   r   r   r}   rz   r~   )FN)r   N)r   r   r   r   r   boolr   r   rH   r|   r   r   r   rG   bytesrF   r   rK   r[   rj   r   r   r9   r7   r   r     s    
d , &*37	;; sm; $uS#X/0	;' ' '' ' ''S 'U '

r9   r   c                      \ rS rSrSrS\R                  " S5      4\S\R                  " S5      4\S\R                  " S5      4\S\R                  " S5      4\S\R                  " S5      4\	S\R                  " S	5      4\
S\R                  " S
5      4\S\R                  " S5      4\S\R                  " S5      4\S\R                  " S5      4\0
rSS\4S jjrS rSrg)HTTPGitApplicationif  zuClass encapsulating the state of a git WSGI application.

:ivar backend: the Backend object backing this application
GETz/HEAD$z/info/refs$z/objects/info/alternates$z/objects/info/http-alternates$z/objects/info/packs$z&/objects/([0-9a-f]{2})/([0-9a-f]{38})$z(/objects/pack/pack-([0-9a-f]{40})\.pack$z'/objects/pack/pack-([0-9a-f]{40})\.idx$POSTz/git-upload-pack$z/git-receive-pack$Nr}   c                     Xl         X l        [        [        5      U l        X@l        Ub  U R                  R                  U5        g g r   )rC   r}   dictr   r~   fallback_appupdate)r   rC   r}   r~   r   s        r7   r   HTTPGitApplication.__init__  s<    	-.(MM  *  r9   c                    US   nUS   n[        XU R                  U R                  S9nS nU R                  R	                  5        H6  u  pxXt:w  a  M  UR                  U5      n	U	(       d  M&  U R                  Xx4   n  O   Uc0  U R                  b  U R                  X5      $ UR                  S5      /$ U" XPR                  W	5      $ )N	PATH_INFOREQUEST_METHOD)r}   r~   z#Sorry, that method is not supported)	r   r}   r~   serviceskeyssearchr   rF   rC   )
r   rz   r   rU   methodrM   r   smethodspathr?   s
             r7   __call__HTTPGitApplication.__call__  s    {#)*$))dmm
 "mm002NG ,,t$Cs--7 3 ?  ,((AA&KLMMsLL#..r9   )rC   r}   r   r~   )FNN)r   r   r   r   r   recompilera   r   r   rl   rp   rr   r   r   r   r   r   r   r   r9   r7   r   r   f  s     


8$%}	

=)*M	

678-	

;<=}	

123^JJ?@	
 JJBC	
 JJAB	
 	/013I	0124J'H,+d +/r9   r   c                   $    \ rS rSrSrS rS rSrg)GunzipFilteri  zcWSGI middleware that unzips gzip-encoded requests before
passing on to the underlying application.
c                     Xl         g r   appr   applications     r7   r   GunzipFilter.__init__      r9   c                    UR                  SS5      S:X  a>   US   R                  5         US   n[        R                  " S USS9US'   US	 S	U;   a  US		 U R                  X5      $ ! [        [        [        4 aD    [
        R                  " S5      n[        R                  " US   U5        UR                  S5         Nf = f)
NHTTP_CONTENT_ENCODING gzipr   i   r   r)filenamefileobjmodeCONTENT_LENGTH)r{   tellAttributeErrorrJ   NotImplementedErrortempfileSpooledTemporaryFileshutilcopyfileobjseekr   GzipFiler   )r   rz   r   
wsgi_inputs       r7   r   GunzipFilter.__call__  s    ;;.3v=
#%**,$\2
 %)MMz%GL! /07*,-xx00! #G-@A #
 &::;KL
""7<#8*E"#s   A& &AB?>B?r   Nr   r   r   r   r   r   r   r   r   r9   r7   r   r     s    1r9   r   c                   $    \ rS rSrSrS rS rSrg)LimitedInputFilteri  z_WSGI middleware that limits the input length of a request to that
specified in Content-Length.
c                     Xl         g r   r   r   s     r7   r   LimitedInputFilter.__init__  r   r9   c                     UR                  SS5      nU(       a  [        US   [        U5      5      US'   U R                  X5      $ )Nr   r   r   )r{   r   intr   )r   rz   r   content_lengths       r7   r   LimitedInputFilter.__call__  sG    
 !%5r:$6%s>':%GL! xx00r9   r   Nr  r   r9   r7   r  r    s    
1r9   r  c                  D    [        U 0 UD6n[        [        U5      5      nU$ )zhFactory function to create an instance of HTTPGitApplication,
correctly wrapped with needed middleware.
)r   r  r   )argskwargsr   wrapped_apps       r7   make_wsgi_chainr    s(     d
-f
-C$\#%67Kr9   c                   *    \ rS rSrSrS rS rS rSrg)ServerHandlerLoggeri  z@ServerHandler that uses dulwich's logger for logging exceptions.c                 ,    [         R                  SUS9  g Nz/Exception happened during processing of request)exc_infor]   	exceptionr   r  s     r7   log_exception!ServerHandlerLogger.log_exception      = 	 	
r9   c                 2    [         R                  " U/UQ76   g r   r]   r^   r   formatr  s      r7   log_messageServerHandlerLogger.log_message      F"T"r9   c                 *    [         R                  " U6   g r   r]   rK   r   r  s     r7   	log_errorServerHandlerLogger.log_error      dr9   r   N)	r   r   r   r   r   r  r"  r(  r   r   r9   r7   r  r    s    J
#r9   r  c                   0    \ rS rSrSrS rS rS rS rSr	g)	WSGIRequestHandlerLoggeri  zEWSGIRequestHandler that uses dulwich's logger for logging exceptions.c                 ,    [         R                  SUS9  g r  r  r  s     r7   r  &WSGIRequestHandlerLogger.log_exception  r  r9   c                 2    [         R                  " U/UQ76   g r   r  r   s      r7   r"  $WSGIRequestHandlerLogger.log_message  r$  r9   c                 *    [         R                  " U6   g r   r&  r'  s     r7   r(  "WSGIRequestHandlerLogger.log_error  r*  r9   c                 H   U R                   R                  5       U l        U R                  5       (       d  g[	        U R                   U R
                  U R                  5       U R                  5       5      nXl        UR                  U R                  R                  5       5        g)zHandle a single HTTP requestN)rfilereadlineraw_requestlineparse_requestr  wfile
get_stderrget_environrequest_handlerrunserverget_app)r   r   s     r7   r   WSGIRequestHandlerLogger.handle   sw      $zz224!!##%JJ

DOO$5t7G7G7I
 #'DKK'')*r9   )r6  N)
r   r   r   r   r   r  r"  r(  r   r   r   r9   r7   r,  r,    s    O
#+r9   r,  c                       \ rS rSrS rSrg)WSGIServerLoggeri  c                 F    [         R                  S[        U5      -  5        g)zHandle an error. z7Exception happened during processing of request from %sN)r]   r  r|   )r   requestclient_addresss      r7   handle_errorWSGIServerLogger.handle_error  s     E.!"	
r9   r   N)r   r   r   r   rE  r   r   r9   r7   rA  rA    s    
r9   rA  c           	      0   SSK nUR                  5       nUR                  SSSSSS9  UR                  S	S
S[        SSS9  UR	                  U 5      u  p4[        U5      S:  a  US   nO[        R                  " 5       n[        R                  " 5         [        S[        U5      05      n[        U5      n[        UR                  UR                  U[         ["        S9n[$        R'                  SUR                  UR                  5        UR)                  5         g)z,Entry point for starting an HTTP git server.r   Nz-lz--listen_addresslisten_address	localhostzBinding IP address.)destdefaulthelpz-pz--portporti@  zPort to listen on.)rJ  typerK  rL  rc   r;   )handler_classserver_classz'Listening for HTTP connections on %s:%d)optparseOptionParser
add_optionr  
parse_argslenrT   getcwdr   default_logging_configr   r   r  r
   rH  rM  r,  rA  r]   r^   serve_forever)	argvrQ  parseroptionsr  gitdirrC   r   r=  s	            r7   mainr]    s
   ""$F
"   !   %%d+MG
4y1}a$$&3V-.G
'
"C.%F KK1
 r9   __main__r   )Cr   ior   r   r   r   rT   r   sysr,   typingr   r   r   wsgiref.simple_serverr   r   r	   r
   urllib.parser   dulwichr   dulwich.protocolr   dulwich.repor   r   r   dulwich.serverr   r   r   r   	getLoggerr   r]   rH   r   r   r   floatr|   r8   r@   rD   rQ   rX   ra   rl   rp   rr   r   r   objectr   r   r   r   r   r  r  r  r,  rA  rY  r]  r   r9   r7   <module>rk     sk  , K     	 	 
  ( (  "  
  
		X	&   (
" "3 "J	6s 	64h 4
2)U"!H?& &.*E
V E
P:/ :/z16 1@1 1*-  +1 +:
z 
 hh *Z zF r9   