a _ @s0dZddlmZddlmZmZddlZddlZddlZddl Z ddl Z ddl m Z m Z mZmZddlmZmZmZmZmZmZddlZddlmZddlmZmZmZdd l m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;mZ>m?Z?m@Z@mAZAmBZBmCZCmDZDdd lEmFZFmGZGdd lHmIZImJZJGd d d eKZLGdddeKZMddZNddZOe+e0gZPe1e)e*e.gePZQe-e'gePZRGdddeSZTddZUGdddeSZVGdddeSZWddZXGdddeSZYd d!ZZd"d#Z[Gd$d%d%eYZ\Gd&d'd'e\Z]Gd(d)d)eSZ^d*d+Z_Gd,d-d-e\Z`Gd.d/d/eYZaeaZbGd0d1d1eSZcGd2d3d3eKZdGd4d5d5ecZeGd6d7d7ecZfd8d9ZgeeZhGd:d;d;e\Zidd?ZkGd@dAdAeYZldNdBdCZmdDdEZndFdGZoejpqdHedIdJgZrderfdKdLZsdS)Oa1Client side support for the Git protocol. The Dulwich client supports the following capabilities: * thin-pack * multi_ack_detailed * multi_ack * side-band-64k * ofs-delta * quiet * report-status * delete-refs * shallow Known capabilities that are not supported: * no-progress * include-tag )closing)BytesIOBufferedReaderN)OptionalDictCallableSet)quoteunquoteurlparseurljoin urlunsplit urlunparse)get_xdg_config_home_path)GitProtocolErrorNotGitRepository SendPackError)$HangupException _RBUFSIZE agent_stringcapability_agentextract_capability_namesCAPABILITY_AGENTCAPABILITY_DELETE_REFSCAPABILITY_INCLUDE_TAGCAPABILITY_MULTI_ACKCAPABILITY_MULTI_ACK_DETAILEDCAPABILITY_OFS_DELTACAPABILITY_QUIETCAPABILITY_REPORT_STATUSCAPABILITY_SHALLOWCAPABILITY_SYMREFCAPABILITY_SIDE_BAND_64KCAPABILITY_THIN_PACKCAPABILITIES_REFKNOWN_RECEIVE_CAPABILITIESKNOWN_UPLOAD_CAPABILITIESCOMMAND_DEEPENCOMMAND_SHALLOWCOMMAND_UNSHALLOW COMMAND_DONE COMMAND_HAVE COMMAND_WANTSIDE_BAND_CHANNEL_DATASIDE_BAND_CHANNEL_PROGRESSSIDE_BAND_CHANNEL_FATAL PktLineParserProtocol ProtocolFile TCP_GIT_PORTZERO_SHAextract_capabilitiesparse_capability)write_pack_datawrite_pack_objects)read_info_refsANNOTATED_TAG_SUFFIXc@seZdZdZddZdS) InvalidWantszInvalid wants.cCst|d|dS)Nz/requested wants not in server provided refs: %r) Exception__init__)selfwantsr@0/usr/lib/python3/dist-packages/dulwich/client.pyr=uszInvalidWants.__init__N__name__ __module__ __qualname____doc__r=r@r@r@rAr;rsr;c@seZdZdZddZdS)HTTPUnauthorizedz!Raised when authentication fails.cCst|d||_||_dS)NzNo valid credentials provided)r<r=www_authenticateurl)r>rHrIr@r@rAr=~s zHTTPUnauthorized.__init__NrBr@r@r@rArG{srGcCstt|gggdddkS)z,Check if a file descriptor is readable. r)lenselect)filenor@r@rA_fileno_can_readsrMc CsXddlm}m}m}|}|}|j|ddd||||}|sRt||j S)zHWrapper around PeekNamedPipe to check how many bytes are available. r)byrefwintypeswindllN) ZctypesrNrOrPZDWORDZkernel32Z PeekNamedPipeOSErrorZ GetLastErrorvalue)handlerNrOrPZc_availZ c_messageZsuccessr@r@rA_win32_peek_avails rTc@s(eZdZdZddZddZddZdS) ReportStatusParserzEHandle status as reported by servers with 'report-status' capability.cCsd|_d|_g|_dS)NF)_done _pack_status _ref_statusesr>r@r@rAr=szReportStatusParser.__init__c cs|jdvrt|j|jD]z}z|dd\}}WntyHYqYn0|dkrt|dd\}}||dfVq|dkr|dfVqtd|qdS) zCheck if there were any errors and, if so, raise exceptions. Raises: SendPackError: Raised when the server could not unpack Returns: iterator over refs )s unpack okN sngutf-8sokNzinvalid ref status %r)rWrrXsplit ValueErrordecoder)r>statusrestreferrorr@r@rAchecks      zReportStatusParser.checkcCsN|jrtd|dur d|_dS|jdur6||_n|}|j|dS)zHandle a packet. Raises: GitProtocolError: Raised when packets are received after a flush packet. z&received more data after status reportNT)rVrrWstriprXappend)r>pkt ref_statusr@r@rA handle_packets  z ReportStatusParser.handle_packetN)rCrDrErFr=rdrir@r@r@rArUsrUcCsd}i}|D]N}|ddd\}}|dkrBt|dd|durVt|\}}|||<qt|dkrxitgfS|tt ikri}|t|fS)N r[sERRr\replacer) read_pkt_seqrstripr]rr_r5rJsetr$r4)protoserver_capabilitiesrefsrgsharbr@r@rA read_pkt_refss      rscsjeZdZdZgdZdddZddZdd Zd d Zd d Z ddZ ddZ fddZ ddZ ZS)FetchPackResultzResult of a fetch-pack operation. Attributes: refs: Dictionary with all remote refs symrefs: Dictionary with remote symrefs agent: User agent string clearcopyfromkeysgetitemskeyspoppopitem setdefaultupdatevaluesZ viewitemsZviewkeysZ viewvaluesNcCs"||_||_||_||_||_dSN)rqsymrefsagent new_shallow new_unshallow)r>rqrrrrr@r@rAr=s zFetchPackResult.__init__cCsddl}|jdtdddS)Nrz!Use FetchPackResult.refs instead. stacklevelwarningswarnDeprecationWarningr>rr@r@rA_warn_deprecateds z FetchPackResult._warn_deprecatedcCs@t|tr||j|kS|j|jko>|j|jko>|j|jkSr) isinstancedictrrqrrr>otherr@r@rA__eq__s     zFetchPackResult.__eq__cCs|||jvSrrrqr>namer@r@rA __contains__ szFetchPackResult.__contains__cCs||j|Srrrr@r@rA __getitem__szFetchPackResult.__getitem__cCs|t|jSrrrJrqrYr@r@rA__len__szFetchPackResult.__len__cCs|t|jSrriterrqrYr@r@rA__iter__szFetchPackResult.__iter__cs2|t|jvr"|t|j|Stt||Sr)type_FORWARDED_ATTRSrgetattrrqsuperrt__getattribute__r __class__r@rArs z FetchPackResult.__getattribute__cCsd|jj|j|j|jfS)Nz%s(%r, %r, %r))rrCrqrrrYr@r@rA__repr__"szFetchPackResult.__repr__)NNrCrDrErFrr=rrrrrrrr __classcell__r@r@rrArts  rtcsjeZdZdZgdZdddZddZdd Zd d Zd d Z ddZ ddZ fddZ ddZ ZS)SendPackResultaResult of a upload-pack operation. Attributes: refs: Dictionary with all remote refs agent: User agent string ref_status: Optional dictionary mapping ref name to error message (if it failed to update), or None if it was updated successfully ruNcCs||_||_||_dSr)rqrrh)r>rqrrhr@r@rAr=7szSendPackResult.__init__cCsddl}|jdtdddS)Nrz Use SendPackResult.refs instead.rrrrr@r@rAr<s zSendPackResult._warn_deprecatedcCs4t|tr||j|kS|j|jko2|j|jkSr)rrrrqrrr@r@rArBs  zSendPackResult.__eq__cCs|||jvSrrrr@r@rArHszSendPackResult.__contains__cCs||j|Srrrr@r@rArLszSendPackResult.__getitem__cCs|t|jSrrrYr@r@rArPszSendPackResult.__len__cCs|t|jSrrrYr@r@rArTszSendPackResult.__iter__cs2|t|jvr"|t|j|Stt||Sr)rrrrrqrrrrrr@rArXs zSendPackResult.__getattribute__cCsd|jj|j|jfS)Nz %s(%r, %r))rrCrqrrYr@r@rAr^szSendPackResult.__repr__)NNrr@r@rrAr's   rcCsnt}t}|D]P}|dd\}}|tkr@||q|tkrX||qtd|q||fS)NrZr[zunknown command %s)rnrlr]r(addrer)r)rorrrgcmdrrr@r@rA_read_shallow_updatescs rc @seZdZdZd$ddZddZed d Zd%d d Zd&d dZ d'ddZ ddZ ddZ e ddZddZddZd(eeeeegdfeeeeefdddZddZd d!Zdefd"d#ZdS)) GitClientzGit smart server client.TNFcCsp||_d|_tt|_|jttt|_|jt|rL|jt |s\|j t |rl|jt dS)a6Create a new GitClient instance. Args: thin_packs: Whether or not thin packs should be retrieved report_activity: Optional callback for reporting transport activity. include_tags: send annotated tags when sending the objects they point to N) _report_activity_report_status_parserrnUPLOAD_CAPABILITIES_fetch_capabilitiesrrRECEIVE_CAPABILITIES_send_capabilitiesrremover#r)r> thin_packsreport_activityquietZ include_tagsr@r@rAr=ws     zGitClient.__init__cCst|jdS)zRetrieves full url to given path. Args: path: Repository path (as string) Returns: Url to path (as string) N)NotImplementedErrorget_urlr>pathr@r@rArs zGitClient.get_urlcKst|jdS)zCreate an instance of this client from a urlparse.parsed object. Args: parsedurl: Result of urlparse() Returns: A `GitClient` object N)rfrom_parsedurlcls parsedurlkwargsr@r@rArs zGitClient.from_parsedurlcCst|jdS)apUpload a pack to a remote repository. Args: path: Repository path (as bytestring) update_refs: Function to determine changes to remote refs. Receive dict with existing remote refs, returns dict with changed refs (name -> sha, where sha=ZERO_SHA for deletions) generate_pack_data: Function that can return a tuple with number of objects and list of pack data to include progress: Optional progress function Returns: SendPackResult object Raises: SendPackError: if server rejects the pack data N)r send_pack)r>r update_refsgenerate_pack_dataprogressr@r@rArszGitClient.send_packc s|durjj}t|jvr8tfdd}dd}nj\}}z |j||j||d}Wnt y|Yn0| |j |j |S)aFetch into a target repository. Args: path: Path to fetch from (as bytestring) target: Target repository to fetch into determine_wants: Optional function to determine what refs to fetch. Receives dictionary of name->sha, should return list of shas to fetch. Defaults to all shas. progress: Optional progress function depth: Depth to fetch at Returns: Dictionary with all remote refs (not just those fetched) Ncs&r"djjddS)Nr)tellseek object_storeZ add_thin_packreadr@ftargetr@rAcommits zGitClient.fetch..commitcSsdSrr@r@r@r@rAabortszGitClient.fetch..abortrdepth) rZdetermine_wants_allr#rrZadd_pack fetch_packZget_graph_walkerwrite BaseExceptionZupdate_shallowrr) r>rrdetermine_wantsrrrrresultr@rrAfetchs$    zGitClient.fetchcCst|jdS)Retrieve a pack from a git smart server. Args: path: Remote path to fetch from determine_wants: Function determine what refs to fetch. Receives dictionary of name->sha, should return list of shas to fetch. graph_walker: Object with next() and ack(). pack_data: Callback called for each bit of data in the pack progress: Callback for progress reports (strings) depth: Shallow fetch depth Returns: FetchPackResult object N)rr)r>rr graph_walker pack_datarrr@r@rArszGitClient.fetch_packcCst|jdS)zRetrieve the current refs from a git smart server. Args: path: Path to the repo to fetch from. (as bytestring) Returns: N)rget_refsrr@r@rArs zGitClient.get_refsc Csj|D]\}t|dd}|dd}z ||}WntyRtd|Yq0|dur||qdS)aRead per-channel data. This requires the side-band-64k capability. Args: proto: Protocol object to read from channel_callbacks: Dictionary mapping channels to packet handlers to use. None for a callback discards channel data. Nr[zInvalid sideband channel %d)rlordKeyErrorAssertionError)r>rochannel_callbacksrgZchannelcbr@r@rA_read_side_band64k_data s    z!GitClient._read_side_band64k_datacCstdd|DS)Ncss|]}|tkVqdSrr4).0rrr@r@rA !z.GitClient._should_send_pack..)anyr)new_refsr@r@rA_should_send_packszGitClient._should_send_packc Cs g}dd|D}d}|D]}t|ts8td|||t} t| ts^td|| f||t} t| tstd|| f| | kr|r|| d| d|n0|| d| d|ddt|d }| |vr| tkr| | q|d ||fS) a:Handle the head of a 'git-receive-pack' request. Args: proto: Protocol object to read from capabilities: List of negotiated capabilities old_refs: Old refs, as received from the server new_refs: Refs to change Returns: (have, want) tuple cSsg|]}|tks|qSr@rrxr@r@rA 1rz7GitClient._handle_receive_pack_head..Fzrefname is not a bytestring: %rz'old sha1 for %s is not a bytestring: %rz&old sha1 for %s is not a bytestring %rrZTN) rrbytes TypeErrorryr4write_pkt_linejoinsortedrf) r>ro capabilitiesold_refsrwanthaveZsent_capabilitiesrefnameold_sha1new_sha1r@r@rA_handle_receive_pack_head#s>          z#GitClient._handle_receive_pack_headcCsD|j|@}d}|D]}t|\}}|tkr|}qt|t}||fSr)rr6rrr%)r>rpnegotiated_capabilitiesr capabilitykvunknown_capabilitiesr@r@rA$_negotiate_receive_pack_capabilitiesNs z.GitClient._negotiate_receive_pack_capabilities)rorrreturncCst|vrH|durdd}d|i}t|vr:t|jjj|d<|||n"t|vrj|D]}|j|qX|jdurt|j SdS)aHandle the tail of a 'git-receive-pack' request. Args: proto: Protocol object to read from capabilities: List of negotiated capabilities progress: Optional progress reporting function Returns: dict mapping ref name to: error message if the ref failed to update None if it was updated successfully NcSsdSrr@rr@r@rArnsz5GitClient._handle_receive_pack_tail..progressr[) r"rr0rriparserrlrrd)r>rorrrrgr@r@rA_handle_receive_pack_tail\s   z#GitClient._handle_receive_pack_tailc Csjt|t}i}d}|D]<}t|\}}|tkrH|dd\}} | ||<|tkr|}q|j|@} | ||fS)N:r[)rr&r6r!r]rr) r>rprrrrrrsrcZdstrr@r@rA#_negotiate_upload_pack_capabilities~s  z-GitClient._negotiate_upload_pack_capabilitiescCst|trt|dtsJ|td|dddt|d|ddD]}|td|dqT|dvst|ddr t|vrt d|j D]}|t d|dq|dur|t dt |d d|d|durt|\} } nd} } nt} } |dt|} | r|td| d|dur|r|} | dd} | dd kr|| d| d d vrn$| d d krqntd| d t|} q(|td| | fS)aHandle the head of a 'git-upload-pack' request. Args: proto: Protocol object to read from capabilities: List of negotiated capabilities graph_walker: GraphWalker instance to call .ack() on wants: List of commits to fetch can_read: function that returns a boolean that indicates whether there is extra graph data to read on proto depth: Depth for request Returns: rrZrjr[N)rNshallowz=server does not support shallow capability required for depthasciiACKr)continuecommonreadyz(%s not in ('continue', 'ready', 'common))rlistrrr,rrrr rrr(r'strencoderrnnextr+ read_pkt_linermr]ackrr*)r>rorrr?can_readrrrrrrrrgpartsr@r@rA_handle_upload_pack_heads^          z"GitClient._handle_upload_pack_headc Cs|}|rZ|dd}|ddkr6||dt|dksZ|ddvrPqZ|}qt|vr|d urrd d }||t|t|in| |} | d krq|| qd S) aHandle the tail of a 'git-upload-pack' request. Args: proto: Protocol object to read from capabilities: List of negotiated capabilities graph_walker: GraphWalker instance to call .ack() on pack_data: Function to call with pack data progress: Optional progress reporting function rbufsize: Read buffer size Returns: rjrZrrr[rr)r rr NcSsdSrr@rr@r@rArsz4GitClient._handle_upload_pack_tail..progressr) rrmr]rrJr"rr-r.r) r>rorrrrZrbufsizergrdatar@r@rA_handle_upload_pack_tails&   z"GitClient._handle_upload_pack_tail)TNFF)N)NNN)NN)N)rCrDrErFr=r classmethodrrrrrr staticmethodrrrr1rrrrrr rrrrrr@r@r@rArts<    .   +  "<rcCs*t|dd|D}|r&t|dS)zCheck that a set of wants is valid. Args: wants: Set of object SHAs to fetch refs: Refs dictionary to check against Returns: cSsh|]\}}|ts|qSr@)endswithr:)rrrr@r@rA s zcheck_wants..N)rnrzr;)r?rqZmissingr@r@rA check_wantss rcCs\|durtSdd|D}|D].}|dr$t|tddddSq$t|S)NcSsg|]}|dqS)rj)rm)rliner@r@rAr rz-_remote_error_from_stderr..sERROR: r\rk)r readlines startswithrrJr_)stderrlinesrr@r@rA_remote_error_from_stderrs  r csVeZdZdZdZeffdd ZddZddd Zdd d Zd d Z dddZ Z S)TraditionalGitClientzTraditional Git client.r\c s ||_tt|jfi|dSr)_remote_path_encodingrr!r=)r>Z path_encodingrrr@rAr=szTraditionalGitClient.__init__cCs tdS)aCreate a connection to the server. This method is abstract - concrete implementations should implement their own variant which connects to the server and returns an initialized Protocol object with the service ready for use and a can_read function which may be used to see if reads would block. Args: cmd: The git service name to which we should connect. path: The path we should pass to the service. (as bytestirng) N)r)r>rrr@r@rA_connects zTraditionalGitClient._connectNc CsD|d|\}}}|zt|\}} WntyDt|Yn0|| \} } t| vrdt|_|j} z|t|} }Wnt y| dYn0t |  t | r| dt| | idWdSt| vr4t|} | D]:\}}|tkrt| vr,| jd|dd| _| |=q| durd| dt|| idWdSt| dkrt|r| d| durt| }nd}t|| |dWdS||| || \}}|||t| vd\}}|| rt|||||| |}t| | |dWdS1s60YdS) aiUpload a pack to a remote repository. Args: path: Repository path (as bytestring) update_refs: Function to determine changes to remote refs. Receive dict with existing remote refs, returns dict with changed refs (name -> sha, where sha=ZERO_SHA for deletions) generate_pack_data: Function that can return a tuple with number of objects and pack data to upload. progress: Optional callback called with progress updates Returns: SendPackResult Raises: SendPackError: if server rejects the pack data s receive-packNrrhsng s& remote does not support deleting refsFrZ ofs_delta)r#rsrr rrrUrrrrrnrzissubsetrrr4rXrfZ_ref_status_okrJrdrrrr7 write_filer)r>rrrrroZunused_can_readrrrprrZreport_status_parserrZ orig_new_refsrbrrrhrrpack_data_countrr@r@rAr*sn            zTraditionalGitClient.send_packc CsL|d|\}}} |zt|\} } WntyDt| Yn0|| \} } }| dur|dt| | |WdSz || }Wnty|dYn0|durdd|D}|s|dt| | |WdS|j|| ||||d\}}| || |||t| | |||WdS1s>0YdS)r upload-packNcSsg|]}|tkr|qSr@rrZcidr@r@rArrz3TraditionalGitClient.fetch_pack..)r) r#rsrr rrrtrrr)r>rrrrrrrorrrqrprrrr?rrr@r@rAr|sD         zTraditionalGitClient.fetch_packc Cst|d|\}}}|Jzt|\}}WntyBt|Yn0|d|WdS1sf0YdS);Retrieve the current refs from a git smart server. r)N)r#rsrr r)r>rro_rrqr@r@rArs  zTraditionalGitClient.get_refsc  Csf|d|\} } } | 8|dur0| d|| d||dur^|D]} | d| qJ|durt| d|| dz | } Wntyt| Yn0| dks| dkrWddS| dks| dkrn8| d rt| d dd d d n t d| | }|dur*t d| | t |t |t |iWdn1sX0YdS)Nsupload-archivesargument --format=s argument sargument --prefix=sNACK sNACKsACK rsERR rjr\rkzinvalid response %rzexpected pkt tail)r#rrrr rrrmr_rrr-r.r/)r>rZ committishZ write_datarZ write_errorformatZsubdirsprefixrorrZsubdirrgZretr@r@rAarchives@      zTraditionalGitClient.archive)N)NN)NNNNN) rCrDrErFZDEFAULT_ENCODINGr=r#rrrr0rr@r@rrAr!s S 3 r!cs>eZdZdZd fdd ZeddZddZd d ZZ S) TCPGitClientz8A Git Client that works over TCP directly (i.e. git://).Nc s2|dur t}||_||_tt|jfi|dSr)r3_host_portrr1r=)r>hostportrrr@rAr=s zTCPGitClient.__init__cKs||jfd|ji|S)Nr5)hostnamer5rr@r@rArszTCPGitClient.from_parsedurlcCs:|j}|jdur(|jtkr(|d|j7}td||ddfS)N:%dgit)r2r3r3r r>rnetlocr@r@rArszTCPGitClient.get_urlc snt|tst|t|ts(||j}t|j|jtj tj }dt d|j}|D]\}}}}} t||| tj tjdz| WqWqXtj y} z$| }durdWYd} ~ qXd} ~ 00qXdur|ddddfdd} tjj| |jd }|d r>|dd}|d ||d |jd |fdddfS)Nzno address found for %sr[rbwbrcsdSr)closer@ZrfilesZwfiler@rAr?sz$TCPGitClient._connect..closers/~git-shost=rcstSr)rMr@)rAr@rArz'TCPGitClient._connect..)rrrr r"socketZ getaddrinfor2r3Z AF_UNSPECZ SOCK_STREAMrcZ setsockoptZ IPPROTO_TCPZ TCP_NODELAYZconnectr?Zmakefiler1rrrrZsend_cmd) r>rrZ sockaddrserrZfamilyZsocktyperoZ canonnameZsockaddrer?r@r@rAr#sD          zTCPGitClient._connect)N) rCrDrErFr=rrrr#rr@r@rrAr1s  r1c@s4eZdZdZddZeddZddZdd Zd S) SubprocessWrapperz:A socket-like object that talks to a subprocess via pipes.cCs"||_t|jj|_|jj|_dSr)procrstdoutrstdinr)r>rIr@r@rAr= szSubprocessWrapper.__init__cCs|jjSr)rIrrYr@r@rAr%szSubprocessWrapper.stderrcCsFtjdkr2ddlm}||jj}t|dkSt|jjSdS)Nwin32r) get_osfhandle) sysplatformZmsvcrtrMrIrJrLrTrM)r>rMrSr@r@rAr)s    zSubprocessWrapper.can_readcCs:|jj|jj|jjr,|jj|jdSr)rIrKr?rJrwaitrYr@r@rAr?1s    zSubprocessWrapper.closeN) rCrDrErFr=propertyrrr?r@r@r@rArHs  rHcCsRtjdkrHz ddl}Wnty0gdYS0|d\}}|gSndgSdS)z3Find command to run for system Git (usually C Git).rLrN)rz/cr8r8)rNrOwin32api ImportErrorZFindExecutable)rRr`r8r@r@rAfind_git_command9s   rTc@s(eZdZdZeddZdZddZdS)SubprocessGitClientz5Git client that talks to a server using a subprocess.cKs|fi|Srr@rr@r@rArJsz"SubprocessGitClient.from_parsedurlNcCst|tst|t|tr(||j}|jdur8t}||d|g}tj|dtj tj tj d}t |}t |j |j |j|jd|j|jfS)NrrbufsizerKrJrrB)rrrr_r" git_commandrT subprocessPopenPIPErHr1rrr?rrr)r>servicerrXargvpZpwr@r@rAr#Ps"     zSubprocessGitClient._connect)rCrDrErFrrrXr#r@r@r@rArUGs  rUc@s`eZdZdZdddZddZedd Zed d Zdd d Z dddZ dddZ ddZ dS)LocalGitClientz'Git Client that just uses a local Repo.TNcCs ||_dS)zCreate a new LocalGitClient instance. Args: thin_packs: Whether or not thin packs should be retrieved report_activity: Optional callback for reporting transport activity. N)r)r>rrconfigr@r@rAr=dszLocalGitClient.__init__cCstdd|ddfS)Nfiler9)r rr@r@rAroszLocalGitClient.get_urlcKs|fi|Srr@rr@r@rArrszLocalGitClient.from_parsedurlcCs,ddlm}t|ts t|}t||S)Nr)Repo)Z dulwich.reporbrr osfsdecoder)rrrbr@r@rA _open_repovs   zLocalGitClient._open_repocCsp|s dd}||:}|}|t|}dd|D}g} |D]*\} } | |vrL| | vrL| tkrL| | qL| st|t|rt |idWdS|j j ||| ddi} |D]p\} } | | t} | tkr |j | | | sBd | | f}|||| | <q|j | | s|d | d | | <qWdn1sZ0Yt || dS) aUpload a pack to a remote repository. Args: path: Repository path (as bytestring) update_refs: Function to determine changes to remote refs. Receive dict with existing remote refs, returns dict with changed refs (name -> sha, where sha=ZERO_SHA for deletions) with number of items and pack data to upload. progress: Optional progress function Returns: SendPackResult Raises: SendPackError: if server rejects the pack data cSsdSrr@rr@r@rArsz*LocalGitClient.send_pack..progresscSsg|]}|tkr|qSr@r)rZsha1r@r@rArrz,LocalGitClient.send_pack..)rhNTr%zunable to set %s to %szunable to remove %szunable to remove)rerrrrzr4rfrnr&rrZ add_pack_dataryrqZ set_if_equalsZremove_if_equals)r>rrrrrrrrrrrrhrmsgr@r@rAr}sF        *zLocalGitClient.send_packcCsT||6}|j||||d}t||jtWdS1sF0YdS)aFetch into a target repository. Args: path: Path to fetch from (as bytestring) target: Target repository to fetch into determine_wants: Optional function determine what refs to fetch. Receives dictionary of name->sha, should return list of shas to fetch. Defaults to all shas. progress: Optional progress function depth: Shallow fetch depth Returns: FetchPackResult object )rrrN)rerrtrq get_symrefsr)r>rrrrrrrqr@r@rArs  zLocalGitClient.fetchc Cs||x}|j||||d}|j} t} |durPtd| | WdStd|} t| |t|| | WdS1s0YdS)rrN) reZ fetch_objectsrqrgrrtr2r8r) r>rrrrrrrhZ objects_iterrrZprotocolr@r@rArs    zLocalGitClient.fetch_packcCs6||}|WdS1s(0YdS)r+N)rer)r>rrr@r@rArs zLocalGitClient.get_refs)TNN)N)NNN)NN) rCrDrErFr=rrrrerrrrr@r@r@rAr_as    ;  r_c@s$eZdZdZdddZdddZdS) SSHVendorz!A client side SSH implementation.NcCs*ddl}|dt|j||||||dS)Nrz?SSHVendor.connect_ssh has been renamed to SSHVendor.run_command)usernamer5password key_filename)rrr run_command)r>r4commandrjr5rkrlrr@r@rA connect_sshs zSSHVendor.connect_sshcCst|jdS)aConnect to an SSH server. Run a command remotely and return a file-like object for interaction with the remote command. Args: host: Host name command: Command to run (as argv array) username: Optional ame of user to log in as port: Optional SSH port to use password: Optional ssh password for login or private key key_filename: Optional path to private keyfile Returns: N)rrm)r>r4rnrjr5rkrlr@r@rArmszSSHVendor.run_command)NNNN)NNNN)rCrDrErFrormr@r@r@rAris rics eZdZdZfddZZS)StrangeHostnamez,Refusing to connect to strange SSH hostname.cstt||dSr)rrpr=)r>r6rr@rAr= szStrangeHostname.__init__)rCrDrErFr=rr@r@rrArpsrpc@seZdZdZdddZdS)SubprocessSSHVendorz6SSH vendor that shells out to the local 'ssh' command.Nc Cs|durtdddg}|r.|dt|g|rD|dt|g|rTd||f}|drht|d||tj||gd tjtjtjd }t |S) Nz6Setting password not supported by SubprocessSSHVendor.sshz-xz-p-i%s@%s-r6rrV) rextendr rrprfrYrZr[rH) r>r4rnrjr5rkrlargsrIr@r@rArm's(    zSubprocessSSHVendor.run_command)NNNNrCrDrErFrmr@r@r@rArq$srqc@seZdZdZdddZdS)PLinkSSHVendorz8SSH vendor that shells out to the local 'plink' command.Nc Cstjdkrddg}nddg}|durHddl}|d|dt|g|r^|dt|g|rt|d t|g|rd ||f}|d rt|d ||t j ||gdt j t j t j d } t | S)NrLz plink.exez-sshZplinkrzHInvoking PLink with a password exposes the password in the process list.z-pwz-PrsrtrurvrV) rNrOrrrwr rrprfrYrZr[rH) r>r4rnrjr5rkrlrxrrIr@r@rArmFs0      zPLinkSSHVendor.run_command)NNNNryr@r@r@rArzCsrzcKs.ddl}|dtddlm}|fi|S)NrzDParamikoSSHVendor has been moved to dulwich.contrib.paramiko_vendor.)ParamikoSSHVendor)rrrZdulwich.contrib.paramiko_vendorr{)rrr{r@r@rAr{hs r{csBeZdZd fdd ZddZeddZdd Zd d ZZ S) SSHGitClientNc  sV||_||_||_||_||_tt|jfi|i|_|durJ||_ nt |_ dSr) r4r5rjrkrlrr|r=alternative_paths ssh_vendorget_ssh_vendor) r>r4r5rjZvendorr`rkrlrrr@rAr=wszSSHGitClient.__init__cCsN|j}|jdur|d|j7}|jdurrr@r@rA _get_cmd_pathszSSHGitClient._get_cmd_pathcCst|tst|t|tr(||j}|dr>|dd}|||jd|d}i}|jdurt|j|d<|jdur|j|d<|j j |j |f|j |j d|}t|j|j|j|jd|jt|d dfS) Nz/~r[z ''rkrl)r5rjrBr)rrrr_r"rrrkrlr~rmr4r5rjr1rrr?rrr)r>rrr]rZconr@r@rAr#s<         zSSHGitClient._connect)NNNNNN) rCrDrEr=rrrrr#rr@r@rrAr|us  r|cCsddddtjDS)Nzgit/dulwich/%s.cSsg|] }t|qSr@)r rr@r@rArrz-default_user_agent_string..)rdulwich __version__r@r@r@rAdefault_user_agent_stringsrcKsd}}d}}|dur:dD]}tj|}|durq:q|dur|durnz|dd}WntylYn0z|dd}WntyYn0z|dd}Wntyd}Yn0z|dd}Wntyd}Yn0|durt}d |i} i} |durd | d <n|d ur$d | d <nd | d <|dur>|| d<| |d| vr| d d krz ddl} WntyYn0| | d<ddl } |dur|dur| j }t |t s|}||fd| i| } n"|dur| j}|fd| i| } | S)aReturn `urllib3` connection pool manager. Honour detected proxy configurations. Args: config: dulwich.config.ConfigDict` instance with Git configuration. kwargs: Additional arguments for urllib3.ProxyManager Returns: `pool_manager_cls` (defaults to `urllib3.ProxyManager`) instance for proxy configurations, `proxy_manager_cls` (defaults to `urllib3.PoolManager`) instance otherwise. N)Z https_proxyZ http_proxyZ all_proxyshttpsproxys useragents sslVerifyTs sslCAInfoz User-agentZ CERT_REQUIREDZ cert_reqsFZ CERT_NONEca_certsrheaders)rcenvironryrZ get_booleanrrcertifirSwhereurllib3Z ProxyManagerrr r_Z PoolManager)r`Zpool_manager_clsZproxy_manager_clsZoverride_kwargsZ proxy_serverZ user_agentrZ ssl_verifyZ proxynamerrrrZmanagerr@r@rAdefault_urllib3_managersl                   rc@speZdZdddZddZeddZdd Zd d Zdd dZ ddZ ddZ dddZ dddZ ddZdS) HttpGitClientNc Ks|dd|_||_||_||_|dur6t||_n||_|durtd||f}ddl} | jj |d} |jj | t j |fi|dS)N/%s:%sr) basic_auth)rm _base_urlZ _usernameZ _passworddumbr pool_managerZ urllib3.utilutilZ make_headersrrrr=) r>base_urlrrr`rjrkr credentialsrrr@r@rAr=s  zHttpGitClient.__init__cCs||dS)Nr)_get_urlrmrr@r@rAr)szHttpGitClient.get_urlcKs|j}|durt||d<|j}|dur4t||d<|j}|jrNd||jf}|jrbd|j|f}|j|d}|t|fi|S)Nrkrjrrt)r;)rk urlunquoterjr6r5_replacer)rrrrkrjr;r@r@rAr,s   zHttpGitClient.from_parsedurlcCsdt|j|j|jfS)Nz%s(%r, dumb=%r))rrCrrrYr@r@rAr<szHttpGitClient.__repr__cCs*t|ts|d}t|j|ddS)Nr\r)rr r_r rrmrr@r@rAr@s  zHttpGitClient._get_urlFc Cs|jj}|dur||d|d<|r4d|d<nd|d<|durX|jjd||d}n|jjd |||d }|jd kr|t|jd krt|d ||jdkrt d|j|ft |j j }|d|_ z |}Wnty||_Yn0||kr|nd|_||fS)aPerform HTTP request. Args: url: Request URL. headers: Optional custom headers to override defaults. data: Request data. allow_compression: Allow GZipped communication. Returns: Tuple (`response`, `read`), where response is an `urllib3` response object with additional `content_type` and `redirect_location` properties, and `read` is a consumable read method for the response data. Nzno-cacheZPragmaZgzipzAccept-EncodingZidentityZGET)rZPOST)rbodyiizWWW-Authenticatezunexpected http resp %d for %s Content-Typer9)rrrwrZrequestr`rrGZ getheaderrrrr content_typeZgeturlAttributeErrorZget_redirect_locationredirect_location) r>rIrrallow_compressionZ req_headersresprZresp_urlr@r@rA _http_requestGs8           zHttpGitClient._http_requestc CsN|ddksJd}ddi}|jdur8|d|d7}t||}|j||dd \}}|jr|j|s|td ||j|f|jdt| }z|j d  |_|jst |d}zt | \} Wnt ytd Yn0| d d|krtd| t||fW|St|t|fW|SW|n |0dS)Nr=rz info/refsAcceptz*/*Tz ?service=%sr)rz+Redirected from URL %s to URL %s without %szapplication/x-git-z%unexpected number of packets receivedrjs # service=z*unexpected first line %r from smart server)rr_r rrrrrJrrr1r rlr^rmrsr?r9rn) r>r\rtailrrIrrrorgr@r@rA_discover_referencessH      z"HttpGitClient._discover_referencescCsl|ddksJt||}d|}d||tt|d}||||\}}|j|krdtd|j||fS)Nr=rzapplication/x-%s-resultzapplication/x-%s-request)rrzContent-Lengthz$Invalid content-type from server: %s)r r rJrrr)r>r\rIrZresult_content_typerrrr@r@rA_smart_requests   zHttpGitClient._smart_requestcCsN||}|d|\}}}||\}} |tt|vrFt|_|t|} | durht || idSt |  t | rt | | idS|j rt|jt} td| j} || ||| \} }|| |t|vd\}}|| rt| |||jd|| d\}}z0t|d}||||}t | | |dW|S|0dS)aWUpload a pack to a remote repository. Args: path: Repository path (as bytestring) update_refs: Function to determine changes to remote refs. Receives dict with existing remote refs, returns dict with changed refs (name -> sha, where sha=ZERO_SHA for deletions) generate_pack_data: Function that can return a tuple with number of elements and pack data to upload. progress: Optional progress function Returns: SendPackResult Raises: SendPackError: if server rejects the pack data sgit-receive-packNr$r%zgit-receive-packr)rrrrrrrUrrrrnrzr&rrrrr1rrrrr7r'rgetvaluerr?)r>rrrrrIrrprrrreq_data req_protorrr(rrr resp_protorhr@r@rArsR          zHttpGitClient.send_packcCs||}|d|\}} }|| \} } } ||} | durJdd| D} | sZt|| | S|jrjt|jt}td|j }|j || || d|d\}}|j d|| d\}}zRt|d}|dur|durt |\}}||| |||t|| | ||W|S|0dS)aRetrieve a pack from a git smart server. Args: path: Path to fetch from determine_wants: Callback that returns list of commits to fetch graph_walker: Object with next() and ack(). pack_data: Callback called for each bit of data in the pack progress: Callback for progress reports (strings) depth: Depth for request Returns: FetchPackResult object git-upload-packNcSsg|]}|tkr|qSr@rr*r@r@rArrz,HttpGitClient.fetch_pack..)rrzgit-upload-packr)rrrrtrrrrr1rrrrrrr?)r>rrrrrrrIrqrprrrr?rrrrrrrr@r@rArsP         zHttpGitClient.fetch_packcCs ||}|d|\}}}|S)r+r)rr)r>rrIrqr,r@r@rArs   zHttpGitClient.get_refs)NNNNN)NNF)N)NN)rCrDrEr=rrrrrrrrrrrr@r@r@rArs$   :$ ; 1rcKst|}|jdkr*tj|fi||jfS|jdvrLtj|fi||jfS|jdvrrtj|fd|i||jfS|jdkrtj|fi||jfStd|jdS)aTObtain a git client from a URL. Args: url: URL to open (a unicode string) config: Optional config object thin_packs: Whether or not thin packs should be retrieved report_activity: Optional callback for reporting transport activity. Returns: Tuple with client instance and relative path. r8)zgit+sshrr)ZhttpZhttpsr`razunknown scheme '%s'N) r schemer1rrr|rdefault_local_git_client_clsr^)rIr`rZparsedr@r@rAget_transport_and_path_from_url(s4    rcCstd|vr&d|vr&|dd\}}d}nDd|vrb|dd\}}d|vrX|dd\}}qjd}|}ntd|||fS)zParse a rsync-style URL. :rr[Nznot a valid rsync-style URL)r]rsplitr^)locationr4ruserZ user_hostr@r@rAparse_rsync_urlFsrcKszt|fi|WSty$Yn0tjdkr^|dr^|dddkr^tfi||fSzt|\}}}Wn$tytfi||fYS0t|fd|i||fSdS)aQObtain a git client from a URL. Args: location: URL or path (a string) config: Optional config object thin_packs: Whether or not thin packs should be retrieved report_activity: Optional callback for reporting transport activity. Returns: Tuple with client instance and relative path. rLrr[rz:\rjN)rr^rNrOisalpharrr|)rrrjr6rr@r@rAget_transport_and_pathZs    rz~/.git-credentialsr8rc Cs|D]}zt|dl}|D]V}t|}|j|kr|j|kr|dusL|j|kr|j|jfWdWSqWdn1s0YWqtyYqYq0qdS)Nr<)openr rr6rjrkFileNotFoundError)rr6rjfnamesfnamerrZ parsed_liner@r@rAget_credentials_from_stores  H r)NN)N)trF contextlibriorrrcrKrErYrNtypingrrrrZ urllib.parser rr rr r r rrZdulwich.configrZdulwich.errorsrrrZdulwich.protocolrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r+r,r-r.r/r0r1r2r3r4r5r6Z dulwich.packr7r8Z dulwich.refsr9r:r<r;rGrMrTZCOMMON_CAPABILITIESrrobjectrUrsrtrrrrr r!r1rHrTrUr_rrirprqrzr{rr|rrrrrrr expanduserZDEFAULT_GIT_CREDENTIALS_PATHSrr@r@r@rAs   &  3@< N>"% : \ #