o ]LbQi@sddlmZddlZddlZddlmZddlmZddlm Z ddl m Z m Z m ZmZmZmZmZmZmZmZmZmZmZddlmZmZejZejZed Zed Z d ee fZ!d d Z"ddZ#ddZ$ddZ%ddZ&e'Z(dfddZ)e)ddddddZ*e)dd ddd!d"Z+e)d#ddd$d%Z,e)d&d'ddd(d)Z-e)d*d+ddd,d-Z.gd.Z/d/d0Z0e)d1ddd2d3Z1e)d4d5ddd6d7Z e)d8d9ddd:d;Z2e)dd?Z3d@dAZ4e)dBdCdddDdEZ5e)dFdddGdHZ6e)dIdddJdKZ7e)dLdMdddNdOZ8e)dPdQdddRdSZ9e)dTdUdddVdWZ:e)dXdYdddZd[Z;e)d\d]ddd^d_Ze)d`dddadbZ (if generaldelta active) 2. server.bundle1. 3. server.bundle1gd (if generaldelta active) 4. server.bundle1 r s bundle1gd.%sNs bundle1.%ss bundle1gdsbundle1)r!requirementsmodGENERALDELTA_REQUIREMENTr configbool)r$actionr!gdvrrrbundle1allowedbs   r>pushcs`ddtjDdvrtddurdtts%tdfdd }|S) aDecorator to declare a wire protocol command. ``name`` is the name of the wire protocol command being provided. ``args`` defines the named arguments accepted by the command. It is a space-delimited list of argument names. ``*`` denotes a special value that says to accept all named arguments. ``permission`` defines the permission type needed to run this command. Can be ``push`` or ``pull``. These roughly map to read-write and read-only, respectively. Default is to assume command requires ``push`` permissions because otherwise commands not declaring their permissions could modify a repository that is supposed to be read-only. cSs h|] \}}|ddkr|qS)sversionrr).0r6r=rrr sz#wireprotocommand..r?pullsCinvalid wire protocol permission; got %s; expected "push" or "pull"Ns:arguments for version 1 commands must be declared as bytescs0tvr tdtj|dt<|S)Ns+%s command already registered for version 1)r- transports permission)r)r ProgrammingErrorr commandentry)r+r-namerFrErrregisters z"wireprotocommand..register)r TRANSPORTSitemsr rG isinstancebytes)rJr-rFrKrrIrwireprotocommands"  rPsbatchscmds *rC)rFcsptj}g}|dD]}|dd\}}i} |dD]} | r.| d\} } || | || <qt|\} }t|j}|dvs@J|||r|}i|D]$}|dkrmi}| D] }||vrg| |||<q[|d<qO| ||<qO| ||gfdd |DR}n| ||}t|tjr|St|tj t fsJt|tj r|j }| t |q t d|S) N; rr=rB*csg|]}|qSrr)r@r6datarr szbatch..)runescapebatchargrr)rF checkpermr3rNooberror bytesresponserOrVappendescapebatchargr1)r$rcmdsr4 unescapeargrespairopr-valsanr=r+r,permr3r6starkeyresultrrUrbatchsF       "   rjsbetweenspairscCsLdd|dD}g}||D] }|t|dqtd|S)NcSsg|]}t|dqS)-)r decodelist)r@prrrrWszbetween..rR rD)rbetweenr\r encodelistr[r1)r$rpairsrbrrrros ro branchmapcCs\|}g}t|D]\}}tt|}t|}| d||fq t d |S)Ns%s %srn) branchmapr iteritemsurlreqquoter fromlocalrrpr\r[r1)r$rruheadsbranchnodes branchname branchnodesrrrrus rusbranchesnodescCsBt|}g}||D] }|t|dq td|S)NrnrD)rrlbranchesr\rpr[r1)r$rr|rrrsrrrrs rs clonebundlesrDcCst|jtjS)aZServer command for returning info for available bundles to seed clones. Clients will parse this response and determine what bundle to fetch. Extensions may wrap this command to filter or dynamically emit data depending on the request. e.g. you could advertise URLs for the closest data center given the client's IP address. )rr[vfstryreadrCB_MANIFEST_FILEr$rrrr clonebundless r)lookuprtpushkeyknown getbundles unbundlehashcCstt}td|r|dt|r=|jddr |dt |}|t j hs1|dn |dd t ||jdd rXttj|dd }|d t||d d tj|jdd r}|tj|jddr}|tj|||S)a)return a list of capabilities for a repo This function exists to allow extensions to easily wrap capabilities computation - returns a lists: easy to alter - change done here will be propagated to both `capabilities` and `hello` command without any other action needed. changegroupsubsetr spreferuncompressedsstream-preferredsstreams streamreqs=%srs experimentalsbundle2-advertise)rolesbundle2=s unbundle=%ssnarrowsnarrowservebrokenellipses)list wireprotocapsr)commandavailabler\rallowservergenerationr!r:streamed_requirementsr8REVLOGV1_REQUIREMENTr1sortedr encodecaps getrepocapsrwrxbundlepriorityr NARROWCAP ELLIPSESCAPaddcapabilities)r$rcapsrequiredformatscapsblobrrr _capabilitiess&          rs capabilitiescCst||}tdt|S)NrR)rrr[r1rr$rrrrr capabilitiesEs rs changegroupsrootscsLt|}tj|||d}t||ddtfddd}tj|dS)N missingroots ancestorsof01servec dSNireadrcgrrR zchangegroup..rDgen) rrlr outgoingrzchangegroupmodmakechangegroupiter streamres)r$rrootsr|rrrrrr Ks   r rs bases headscsRt|}t|}tj|||d}t||ddtfddd}tj|dS)Nrrrcrrrrrrrr\rz#changegroupsubset..rDr)rrlr rrrrr)r$rbasesrzrrrrrchangegroupsubsetVs   r debugwireargss one two *cCs0tdddg|}t|j||fit|S)Nrsthreesfour)r7rr[ debugwireargsr strkwargs)r$ronetwor4r5rrrr`src sdd}|jd}|sdSt||}t||}|sdS|jjfdd|Dddjfd d|Dddt|} |D]} | d } t j j | } | r^| | vr^| | vr^qEd | vrz|| d } Wn t ysYqEw| |rzqEtfd d | DrqEtfdd | DrqEd| vrz|| d}Wn t yYqEwtfdd |DsqE| d}|jd|z |j|WSty|jd|YqEwdS)aReturn a file object for the first matching pullbundle. Pullbundles are specified in .hg/pullbundles.manifest similar to clonebundles. For each entry, the bundle specification is checked for compatibility: - Client features vs the BUNDLESPEC. - Revisions shared with the clients vs base revisions of the bundle. A bundle can be applied only if all its base revisions are known by the client. - At least one leaf of the bundle's DAG is missing on the client. - Every leaf of the bundle's DAG is part of node set the client wants. E.g. do not send a bundle of all changes if the client wants only one specific branch of many. cSsdd|dDS)NcSsh|]}t|qSr)binascii unhexlify)r@hrrrrAzz;find_pullbundle..decodehexstring..rQ)r)srrrdecodehexstringysz(find_pullbundle..decodehexstringspullbundles.manifestNcg|]}|qSrrevr@rclrrrWrz#find_pullbundle..T) inclusivecrrrrrrrrWrs COMPRESSIONheadsc3|] }|vVqdSr(rrr common_ancrr z"find_pullbundle..c3s,|]}|vo|vVqdSr(rrrr heads_ancrrrs  sbasesc3rr(rrrrrrrsURLssending pullbundle "%s" spullbundle "%s" not accessible )rrrparseclonebundlesmanifestfilterclonebundleentries unfiltered changelog ancestorsrgetr compengines _bundlenames TypeErrorissubsetallanyr!debugopenIOError)r$rr5clheadsrzcommonrmanifestr` compformatsentrycompaltcomp bundle_heads bundle_basespathrrrfind_pullbundleis`         rrrTc Cstdtj|}t|D]O\}}tj|}|dkr#t|||<q|dkr1t|d||<q|dkr?t |d||<q|dkrS|dkrLd||<qt |||<q|d kr]t d |qt |d s|t |d s||jd kruttStjttdzyt |j}t |dt }t |dt } | |j|jddrd|vrt|||||| } | rtjt !| ddWS|jddr|dd} | r| s||krtjt"dt"ddt j#|dfit$|\} } | dd}Wn^tjyS}zPt |d s|jd krt|j%dWYd}~St&'|j}d|j%fg}g}|j(dur9|)d|j(f|*t&+d|||,} d}WYd}~nd}~wwtj| | dS) Nrrscsvrsscsvsboolean0Fsplains unknown getbundle option type %srCs bundlecapshttp-v1hintrscommonr s pullbundles partial-pullT)rprefer_uncompressedsdisablefullbundlescgs%server has pull-based clones disableds/remove --pull if specified or upgrade Mercurialrsprefercompressedrnmessagehint error:abort)-r7rGETBUNDLE_ARGUMENTSr3rrvrlrrsetboolKeyErrorr>r bundle2requestedrrJrZbundle2requiredr Abortbundle2requiredmainbundle2requiredhintrrzdiscardnullidr!r:rrrr filechunkiterrgetbundlechunksrmessagerbundle20rr\addpart bundlepart getchunks)r$rr4r5r6r=keytyperrzrbundler infochunksprefercompressedexcbundlermanargsadvargsrrr getbundles                 r rcCs|}tt|dS)Nrn)rzrr[rp)r$rrrrrrzsrzshellocCst||j}td|S)afCalled as part of SSH handshake to obtain server info. Returns a list of lines describing interesting things about the server, in an RFC822-like format. Currently, the only one defined is ``capabilities``, which consists of a line of space separated tokens describing server abilities: capabilities: scapabilities: %s )rrVrr[rrrrhellos rslistkeys namespacecCs(t|t|}tt|Sr() rlistkeysr tolocalrMrr[ pushkeymod encodekeys)r$r namespacedrrrrsrrkeyc Csjzt|}||}t|}d}Wnty+}z t|}d}WYd}~nd}~wwtd||fS)Nrrs%d %s ) r rlookupr Exceptionr forcebytestrrr[)r$rrhr6rerrsuccessinstrrrrs   rrsnodes *cCs*ddd|t|D}t|S)NrDcss|] }|rdp dVqdS)1rNr)r@rsrrrr)s  zknown..)r1knownrrlr[)r$rr|r4r=rrrr's  rs protocapsscapscCs&|jtjkrt|d|_tdS)NrRsOK)rJrSSHV1rr _protocapsr[rrrr protocaps/s  r rsnamespace key old newcCst|dkr#t||kr#z |dt|}Wnty"Ynwt|}|}|t|t|t||p?d}Wdn1sJwY|rU| nd}t dt ||fS)Nzutf-8FrDs%d %s) lenr escapestrdecoder rUnicodeDecodeErrormayberedirectstdiorgetvaluerr[int)r$rrrholdnewoutputrrrrrr6s(     rs stream_outcCstt|S)zIf the server supports streaming clone, it advertises the "stream" capability with a value representing the version and flags of the repo it is serving. Client checks to see if it understands the format. )rstreamreslegacyrgeneratev1wireprotorrrrstreamSsr.sunbundlecs$t|}|}}zt||ddd}z||jddr/fdd}t n3d\fd d}t j d d \}|j d t |t d D]}|qUdt|jd}t|tjrt|ds|jdkrttW|WWdStjttdt|||d|} t | drtj!| "dW|WWdSt#| |r|$ndW|WWdS|wtj%tjtj&fy} zt'| ddsMztjy%} z-t(j)| *t(j)+t#d|r |$ndWYd} ~ WYd} ~ WdSd} ~ wtj&yLt,t -| |r:|$ndYWYd} ~ WdSwt./|j} t'| ddD]} | 0| qYzztj1y} zrt'| dd} | durd| 2ddvr| 3d}|4d| j5| j6dur|j4d| j6dd | j7dur|j4d!| j7dd | j8dur|j4d"| j8dd | j9dur|j4d#| j9dd | j:dur|j4d$| j:dd WYd} ~ nd} ~ wwWntj%y} z&| 3d%}| j;dur|4d&| j;| j<r|4d'd(=| j<WYd} ~ nWd} ~ wtjyM} z&d)| j>fg}g}| j?dur9|@d*| j?f| 0t.Ad+||WYd} ~ n$d} ~ wtj&yl} z| 3d,d)tBC| fgWYd} ~ nd} ~ wwtj!| "dWYd} ~ WdSd} ~ ww1swYdS)-Nspreparing changescSsdSr(rrrrrrcszunbundle..r sstreamunbundlecsD]}qdSr(r)rm)payloadrrcleanuphszunbundle..cleanup)NNcs"rrtdSdSr()closeosunlinkr)fptempnamerrr0ss s hg-unbundle-)prefixs"redirecting incoming bundle to %s swb+rr?rrrsaddpartrrDduringunbundle2F_bundle2salvagedoutputr _replycapsrserrors error:pushkeys in-reply-tor) mandatoryrsnewsoldsretserror:unsupportedcontentsparttypesparamsrrrserror:pushraced)Drrlr&r check_heads getpayloadr!r:r chunkbufferrmkstemprr2fdopensysstrr0seek readbundlerNr cg1unpackerr>rJrZrr rrrunbundleclient safehasattrr,rpushresr'BundleValueError PushRacedrrr/formatflushpusherrbytestrrrr PushkeyFailedrnewpartaddparampartidrrhr*r)retparttypeparamsr1rrr\rrr)r$rrz their_headsr+r0fdrmrrrr r out remotecapsparterrpartr r r)r4r/r5rrE\s        , 7< MM              >rE)Nr?)> __future__rrr2i18nrnoderrrrrr rr r r r rrrr8rrrutilsrrurlerrrwrrrrr'r.r7r> commanddictr)rPrjrorurrrrrrrrr rzrrrrr r.rErrrrs~    <     0  -     +      F  N