$Jc@sdZddklZlZlZlZlZddklZddk Z ddk Z ddk Z ddk Z ddk Z ddkZddkZddkZddkZeiZeiZeiZeiZeiZdZdZd ZeZeZ e eBZ!dZ"e i#Z#e i$Z$d Z%d Z&d Z'eeZ(d Z)d ZdZde*fdYZ+de*fdYZ,de*fdYZ-dZ.dZ/de*fdYZ0dZ1dZ2dZ3de*fdYZ4de*fdYZ5dS(!sStorage back-end for Mercurial. This provides efficient delta storage with O(1) retrieve and append and O(changes) merge between branches. i(tbinthextnullidtnullrevtshort(t_NiiiicCst|d?S(Ni(tint(tq((s#/sys/lib/python/mercurial/revlog.pyt getoffset'scCst|d@S(Ni(R(R((s#/sys/lib/python/mercurial/revlog.pytgettype*scCstt|d>|BS(Ni(tlong(toffsetttype((s#/sys/lib/python/mercurial/revlog.pyt offset_type-scCsx|tjoti}|i|n8||g}|it|d}|i|d|i||iS(sgenerate a hash from the given text and its parent hashes This hash combines both the current file contents and its history in a manner that makes it easy to distinguish nodes with the same content in the revision graph. ii(Rtnullhashtcopytupdatetsortt_shatdigest(ttexttp1tp2tstl((s#/sys/lib/python/mercurial/revlog.pythash2s     cCsH|pd|fSnt|}d }|djon|djoti}g}d}x?||jo1|d }|i|i|||!|}q`W|i|ittt||jodi |}qn t |}|d jpt||jo-|ddjod|fSnd|fSnd|fS( s7 generate a possibly-compressed representation of text ti,i@BiiittuNi( tlentNonetzlibt compressobjtappendtcompresstflushtsumtmaptjoint _compress(RRRtztptpostpos2((s#/sys/lib/python/mercurial/revlog.pyR"Gs.        cCs||p|Sn|d}|djo|Sn|djot|Sn|djo |dSnttd|dS(s decompress the given input iRtxRisunknown compression type %rN(t _decompresst RevlogErrorR(Rtt((s#/sys/lib/python/mercurial/revlog.pyt decompressds     t lazyparsercBsDeZdZdZdZddZdZdddZRS(sK this class avoids the need to parse the entirety of large indices cCsyti|i}Wntj o d}nX||_tit|_||_ ||i|_ dg|i |_ ht t<|_d|_d|_d|_dS(Ni(tutiltfstattst_sizetAttributeErrortdataftstructtcalcsizet indexformatngRtdatasizeRRtindexRRR%tallmaptallt mapfind_count(tselfR6tsize((s#/sys/lib/python/mercurial/revlog.pyt__init__zs     c Cs|iodSn|i}d|_d}d}|id}|iidx||jo|ii|}d}xftdD]X}||t|td!}||i|<|d7}||i joPn||i7}qW||7}qPWdS(s during a commit, we need to make sure the rev being added is not a duplicate. This requires loading the entire index, which is fairly slow. loadmap can load up just the node map, which takes much less time. Niiii( R<R:RR6tseektreadtxranget ngshaoffsetR%R( R?tendtcurtcountt blocksizetdatatoffR,tn((s#/sys/lib/python/mercurial/revlog.pytloadmaps(       c CsU|iodSn|djoT|ii||||ijot|i|d}n|ii|}nt||i}||i}d}|t|i |jot|i |}nxt |D]v}|i ||djoK||||i!}||i ||<|t t d!} |||i | RMR%RR;R=RRNR6RBRCtTruetfindRE( R?tnodetlastRFRItstartRJtfindendRKRQRL((s#/sys/lib/python/mercurial/revlog.pytfindnodesF              cCs|iodSnt}|djo-d}d|i|i}|i}t}nX|o(||i}||i}||}n)|d@|i}|id}||}x,||jo|i||||7}qW|o t|_ndS(Niiiii(R=tFalseRRR:RTRS(R?RQRFR=RORI((s#/sys/lib/python/mercurial/revlog.pyt loadindexs(        N( t__name__t __module__t__doc__RARMRRSRZR\(((s#/sys/lib/python/mercurial/revlog.pyR1qs     -t lazyindexcBsVeZdZdZdZdZdZdZdZdZ dZ RS( s!a lazy version of the index arraycCs ||_dS(N(R)(R?tparser((s#/sys/lib/python/mercurial/revlog.pyRAscCst|iiS(N(RR)R;(R?((s#/sys/lib/python/mercurial/revlog.pyt__len__scCsE|djo|t|ii7}n|ii||ii|S(Ni(RR)R;R\(R?R*((s#/sys/lib/python/mercurial/revlog.pytloads cCs'tt|ii|p |i|S(N(t_unpackR9R)R;Rc(R?R*((s#/sys/lib/python/mercurial/revlog.pyt __getitem__ scCstt||ii|4l20s20s20si8t revlogoldiocBs#eZdZdZdZRS(cCstit|_dS(N(R7R8t indexformatv0R@(R?((s#/sys/lib/python/mercurial/revlog.pyRAAsc Cs+|i}g}htt<}d}}t|tjo||i7}nt|} x||| jo||||!} ||7}tt| } t| dd| dd| d| d|i | dt|i | dt| df} |i | ||| d<|d7}q^W||dfS( Niiiiiiii( R@RRRt _prereadsizeRCRdRvR tgetR!R( R?tfpRJtinlineRR;tnodemapRLRKRRGRkte2((s#/sys/lib/python/mercurial/revlog.pyt parseindexDs"    (3 cCsVt|d|d|d|d||d||d|df}tt|S(Niiiiiii(RRfRv(R?tentryRVtversiontrevR|((s#/sys/lib/python/mercurial/revlog.pyt packentryYs"'(R]R^RAR}R(((s#/sys/lib/python/mercurial/revlog.pyRu@s  s>Qiiiiii20s12xi s>ItrevlogiocBs#eZdZdZdZRS(cCstit|_dS(N(R7R8R9R@(R?((s#/sys/lib/python/mercurial/revlog.pyRAmsc Cst|tjotioz| ort|}t|}t|}t|d}t|d}t d||d<||d<||dfSq||i 7}nt i ||\}}} ||| fS(Ni(RRwR2t openhardlinksR1R`RltlistR R RRCtparserst parse_index( R?RyRJRzRaR;R{RkR tcache((s#/sys/lib/python/mercurial/revlog.pyR}ps    cCs;tt|}|djott||d}n|S(Nii(RfR9t versionformat(R?R~RVRRR)((s#/sys/lib/python/mercurial/revlog.pyRs (R]R^RAR}R(((s#/sys/lib/python/mercurial/revlog.pyRls  trevlogcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZd.dZdZdZd.d.dZd.d.dZd.d.dZdZdZdZdZdZdZ dZ!dZ"d Z#d!Z$d"Z%d#Z&d$Z'd.d%Z(d.d&Z)d'Z*d(Z+d.d)Z,d*Z-d+Z.d,Z/d-Z0RS(/sM the underlying revision storage object A revlog consists of two parts, an index and the revision data. The index is a file with a fixed record size containing information on each revision, including its nodeid (hash), the nodeids of its parents, the position and offset of its data within the data file, and the revision it's based on. Finally, each entry contains a linkrev entry that can serve as a pointer to external data. The revision data itself is a linear collection of data chunks. Each chunk represents a revision and is usually represented as a delta against the previous chunk. To bound lookup time, runs of deltas are limited to about 2 times the length of the original version data. This makes retrieval of a version proportional to its size, or O(1) relative to the number of revisions. Both pieces of the revlog are written to in an append-only fashion, which means we never need to rewrite a file to insert or remove data, and can use some simple techniques to avoid the need for locking while reading. c Cs||_|d d|_||_d|_d|_htt<|_g|_ t }t |do&|i }|t @o|tO}qnd}yV|i|i}|it}t|djotit|d d}nWn/tj o#}|itijoqnX||_|t@|_|d@}|d@}|tjo.|o'ttd|i|d ?fnq|t jo3|t@o'ttd |i|d ?fn1|t jo#ttd |i|fnt|_|itjot|_n|oy|ii |||i} Wn4t!t"fj o"} ttd |inX| \|_ |_|_|ip|i#qn|i gjp+t$|i t%p|i d dtjo,|i i&dddd d d d tfndS(s create a revlog object opener is a function that abstracts the file opening operation and can be used to implement COW semantics or the like. is.diRt defversioniis*index %s unknown flags %#04x for format v0is)index %s unknown flags %#04x for revlogngsindex %s unknown format %dsindex %s is corruptediiN(iRi('t indexfiletdatafiletopenerRt_cachet _chunkcacheRRR{R;tREVLOG_DEFAULT_VERSIONthasattrRtREVLOGNGtREVLOGNGINLINEDATARCRwRR7tunpackRtIOErrorterrnotENOENTRt_inlinetREVLOGV0R.RRt_ioRuR}t ValueErrort IndexErrort _chunkclearRpR`R!( R?RRtvRQtftinsttflagstfmttdRk((s#/sys/lib/python/mercurial/revlog.pyRAs`       "           #cCs1t|ito|iii||ndS(s8load a block of indexes all at once from the lazy parserN(RpR;R`R)R\(R?RXRF((s#/sys/lib/python/mercurial/revlog.pyt _loadindexscCs=t|ito&|ii}|i|i|_ndS(s5loads both the map and the index from the lazy parserN(RpR;R`R)R\R%R{(R?R)((s#/sys/lib/python/mercurial/revlog.pyt _loadindexmaps  cCs=t|ito&|iii|iii|_ndS(s"loads the map from the lazy parserN(RpR{RlR)RMR%(R?((s#/sys/lib/python/mercurial/revlog.pyt_loadmapscCs|it|idS(Ni(RVRR;(R?((s#/sys/lib/python/mercurial/revlog.pyttipscCst|idS(Ni(RR;(R?((s#/sys/lib/python/mercurial/revlog.pyRbsccs&xtt|D] }|VqWdS(N(RDR(R?RQ((s#/sys/lib/python/mercurial/revlog.pyRsscCsDy|i|SWn.tj o"t||itdnXdS(Nsno node(R{Rmt LookupErrorRR(R?RV((s#/sys/lib/python/mercurial/revlog.pyRscCs|i|dS(Ni(R;(R?R((s#/sys/lib/python/mercurial/revlog.pyRVscCs|i|dS(Ni(R;(R?R((s#/sys/lib/python/mercurial/revlog.pytlinkrevscCs>|i}||i|}||dd||ddfS(Niii(R;R(R?RVRQR((s#/sys/lib/python/mercurial/revlog.pytparentss cCs|i|dd!S(Nii(R;(R?R((s#/sys/lib/python/mercurial/revlog.pyt parentrevsscCst|i|dd?S(Nii(RR;(R?R((s#/sys/lib/python/mercurial/revlog.pyRXscCs|i||i|S(N(RXtlength(R?R((s#/sys/lib/python/mercurial/revlog.pyRF scCs|i|dS(Ni(R;(R?R((s#/sys/lib/python/mercurial/revlog.pyR scCs|i|dS(Ni(R;(R?R((s#/sys/lib/python/mercurial/revlog.pytbasescCsH|i|d}|djo|Sn|i|i|}t|S(s?return the length of the uncompressed text for a given revisionii(R;trevisionRVR(R?RRR/((s#/sys/lib/python/mercurial/revlog.pyR@s  cCst|f}|g}|o|i|}nd}x|o|id}||joq;n|tjoq;nx_|i|D]N}|i||joqn||jo|i||i|qqWq;W|S(sxreturn the set of all nodes ancestral to a given node, including the node itself, stopping when stop is matchedi(tsetRtpopRRtaddR!(R?RVtstopt reachabletvisittstopnRLR)((s#/sys/lib/python/mercurial/revlog.pyR.s&      cgst|}ttg}x_|oWxP|i|idD]6}||jo#|i||i||Vq>q>WqWdS(s:Generate the ancestors of revs using a breadth-first visitiN(RRRRRR!R(R?trevsRtseentparent((s#/sys/lib/python/mercurial/revlog.pyt ancestorsEs     cgst|}xrtt|dt|D]Q}xH|i|D]7}|tjo$||jo|i||VPqBqBWq,WdS(s5Generate the descendants of revs in topological orderiN(RRDtminRRRR(R?RRRQR,((s#/sys/lib/python/mercurial/revlog.pyt descendantsPs   c Cs|djo tg}n|djo|i}ng}|D]}||i|qB~}g}|D]}||i|ql~}t|i|}|it|i|t}g}|D]} | |jo || qq~} xt| ol| i d} | |joqq|i| x5|i | D]$} | |jo| i | q?q?WqWt |}|i g} |D]} | |i| q~ S(sR returns the topologically sorted list of nodes from the set: missing = (ancestors(heads) \ ancestors(common)) where ancestors() is the set of ancestors from heads, heads included if heads is None, the heads of the revlog are used if common is None, nullid is assumed to be a common node iN(RRtheadsRRRRRRRRR!RRRV( R?tcommonRt_[1]RLt_[2]thastmissingt_[3]trRR)t_[4]((s#/sys/lib/python/mercurial/revlog.pyt findmissingZs.   **   2      cCs1gggf}|dj oOt|}|p|Sntg}|D]}||i|qE~}ntg}t}|tjoQ|djoDg}|D]}||i|q~tgt|ifSn|djo t|d} d} h}nt|}|p|Snt } t i |d}t |} t g} | D]}| |i|qU~ } x| o| i }|tjoqzn|i|}||jo|| joS| i|| ig} |i|D]}|tjo | |qq~ q?||jo|i |q?qzqzW| p|Sn|tjoug}|D]}|| jo ||qkqk~}|o4tg}|D]}||i|q~}q|Snt}tg}t |}|i}g}xtt |d| dD]}|i|}t}|tjo t}n||joct}||joLt|i|}|d|jp|d|jo|i|qqnOt|i|}|d|jp|d|jo|i|t}n|o| djp || jo~|i|| dj o||jod||     A    0    cCsg}|i|}xt|dt|D]}g}|i|D]}|tjo ||qIqI~}|o<x`|D]-}||jo|i|i|q~q~Wq/|tjo|i|i|q/q/W|S(s!find the children of a given nodei(RtrangeRRRR!RV(R?RVtcR)RRtprtprevs((s#/sys/lib/python/mercurial/revlog.pytchildren>s; " c Csht|ttfo|i|Snt|djo5y|}|i||SWqotj oqoXnyt|}t||jo tn|djot||}n|djp|t|jo tn|i|SWntt fj onXt|djoAy!t |}|i||SWqdt tfj oqdXndS(Niii(( RpR RRVRRRRqRt OverflowErrorRt TypeError(R?tidRVR((s#/sys/lib/python/mercurial/revlog.pyt_matchLs6         c Cs"t|djo yt|d}t||d }g}|iD]"}|| |jo ||qHqH~}g}|D]'}t|i|o ||q~q~~}t|djo>t|djo |dSnt||itdndSWqt j oqXndS(Ni(iiisambiguous identifier( RRR{Rt startswithRRRRR(R?RRtbin_idRRLtnlR((s#/sys/lib/python/mercurial/revlog.pyt _partialmatchns9;  cCsa|i|}|dj o|Sn|i|}|o|Snt||itddS(slocate a node based on: - revision number or str(revision number) - nodeid or subset of hex nodeid sno match foundN(RRRRRR(R?RRL((s#/sys/lib/python/mercurial/revlog.pytlookups cCs+|i|\}}t||||jS(s'compare text with a given file revision(RR(R?RVRRR((s#/sys/lib/python/mercurial/revlog.pytcmpscCsm|i\}}|t||jo4t|t|tjo|||f|_n||f|_dS(N(RRRw(R?R RJtoR((s#/sys/lib/python/mercurial/revlog.pyt _addchunks4cCs|io|i|i}n|i|i}td|}|i||i|}|i||||jo || Sn|S(Ni(RRRRRNRBRCR(R?R Rtdft readaheadR((s#/sys/lib/python/mercurial/revlog.pyt _loadchunks    cCs|i\}}t|}||}||}|djo>||jo1|djo||jo|Sn|||!Sn|i||S(Ni(RRR(R?R RRRRt cachestarttcacheend((s#/sys/lib/python/mercurial/revlog.pyt _getchunks   cCsX|i|}|i||}|io||d|ii7}n|i||S(Ni(RXRFRRR@R(R?RtendrevRXR((s#/sys/lib/python/mercurial/revlog.pyt _chunkraws  cCst|i||S(N(R0R(R?R((s#/sys/lib/python/mercurial/revlog.pyt_chunkscCs d|_dS(NiR(iR(R(R?((s#/sys/lib/python/mercurial/revlog.pyRscCsu|d|jo0|i||i|jo|i|Snti|i|i||i|i|S(s1return or calculate a delta between two revisionsi(RRtmdiffttextdiffRRV(R?trev1trev2((s#/sys/lib/python/mercurial/revlog.pytrevdiffs0c Cs|tjodSn|io)|id|jot|idSnd}|i|}|i|}|i|dd@o)ttd|i|dd@n|ioL|id|jo8|id|jo$|id}t|id}n|i ||d|i |||djo|i |}ng}t |d|dD]}||i |qa~}t i||}|i|\}} |t||| jo#ttd|i|fn|||f|_|S( s/return an uncompressed revision of a given nodeRiiisincompatible revision flag %xisintegrity check failed on %s:%dN(RRRqRRRR;R.RRRRRDRtpatchesRRR( R?RVRRRRRtbinsRR((s#/sys/lib/python/mercurial/revlog.pyRs2  2  ; c Cs|i p#|id|iddjodSn|i|i}|djottd|in|d}|i|}|i|i ||o|i |i n|i |i d}z.x'|D]}|i |i||qWWd|i X|i |iddt}|itM_t|_xC|D];}|ii|i||i|i|} |i | qIW|i|i|i||ii|idS(Niis%s not found in the transactionitwt atomictemp(RRXRRURRR.RRRR#tcloseRtwriteRRTRRR[RRR;RVtrenametreplaceR@R( R?ttrRyttrinfottrindextdataoffRRRQRk((s#/sys/lib/python/mercurial/revlog.pytcheckinlinesizes8.    !  ( c Csd}|ip|i|id}n|i|id}z&|i||||||||SWd|o|in|iXdS(sadd a revision to the log text - the revision data to add transaction - the transaction object used for rollback link - the linkrev data to add p1, p2 - the parent nodeids of the revision d - an optional precomputed delta tasa+N(RRRRRt _addrevisionR( R?Rt transactiontlinkRRRtdfhtifh((s#/sys/lib/python/mercurial/revlog.pyt addrevisions  &c Cst|||} | |ijo| Snt|} | d} |i| } |i| } | oz|p.|i|i| }ti||}nt |}t|dt|d}|| |i | }n| p|t|djo4t |}t|dt|d}| } nt | d|t|| ||i ||i || f}|i id|| |i| <|ii||i|i| }|ip||i|i| |i|i| t||do|i|dn|i|d|i|i|nj| | |ii7} |i|i| | |i||i|d|i|d|i||| | |f|_| S(Niiii(RR{RRRFRRVRRR"RXR RR;RjRRRRRRRRR#R@RR(R?RR R RRRR R RVtcurrtprevRR tptextRJRtdistRkR~((s#/sys/lib/python/mercurial/revlog.pyR+sN     ' !    csXfd}tii|i||}|djotSni|S(s4calculate the least common ancestor of nodes a and bcs9g}i|D]}|tjo ||qq~S(N(RR(RRR)(R?(s#/sys/lib/python/mercurial/revlog.pyR`sN(tancestorRRRRV(R?RRRRR((R?s#/sys/lib/python/mercurial/revlog.pyR]s ' ccsg}|D]}||i|q ~}|ptiVdSn|i|dd}|id|xWtt|dD]?}||||d} } |i| } |dj o|| n|i | }| |d|d|| } | djo,|i | }| t i t|7} n|i | | }tit| t|V| Vt|djoAd} x=| t|jo | d }|| |!V|} qWq|VqWtiVdS( sGcalculate a delta group Given a list of changeset revs, return a set of deltas and metadata corresponding to nodes. the first delta is parent(nodes[0]) -> nodes[0] the receiver is guaranteed to have this parent as it has all history before these changesets. parent is parent[0] Niiiiiiii(Rt changegroupt closechunkRRjRDRRVRRRRttrivialdiffheaderRt chunkheader(R?tnodelistRt infocollectRRLRR)RRRRtnbtmetaR*R+((s#/sys/lib/python/mercurial/revlog.pytgroupis8 *       cCst|}|d}d }t}}d} } } |o|i|} n|i|id} ||ii} |io$|i |i| | |d }n?|i |i| ||i |i | |i|i d}zd }x|D]}t i d|d \}}}}||}||i jo |}qnt|d}~xC||fD]5}||i jot||itdq_q_W|p9|}||i jot||itdqn||jo@t|}t|dt|d}ti| |} n||jp| | || d jo|o|in| i|i|}t|djot|d }nti||g}~|i|||||d | |}| o9|i o.|i|i d}|i|id} n||jottd nt|} n/t| d|| |||i||i||f}|iid |||i |<|ii||i|i|}|io{| i || i |d| i |d|i!|| |ip.|i|i d}|i|id} q}n0|i |d|i |d| i |||d||f\}}}}|i"|}|i#|} |i|} qWWd |o|i$n| i$X|S(s add a delta group given a set of deltas, add them to the revision log. the first delta is against its parent, which should be in our log, the rest are against the previous delta. iisa+Rt 20s20s20s20siPsunknown parents unknown baseii sconsistency error adding groupiN(%RRRRFRRRR@RRRR7RR{tbufferRRR"Rt patchedsizeR#RRRR.R RR;RjRRVRRRRRXR(R?Rt linkmapperR RR/RVRRRXRFttextlenR tisizeR tchaintchunkRRtcsR tdeltaR)tcdeltat cdeltalenRtchkRkR~((s#/sys/lib/python/mercurial/revlog.pytaddgroups     "  ##  &   $ !    " cCs,t|djodSnt|ito|inx/|D]#}|i|d|joPqCqCWdS|i|}|ip'|i|i|||i i }n|||i i 7}|i|i |d|_ |ix0t|t|D]}|i|i|=qW|i|d5dS(s6truncate the revlog on the first revision with a linkrev >= minlink This function is called when we're stripping revision minlink and its descendants from the repository. We have to remove all revisions with linkrev >= minlink, because the equivalent changelog revisions will be renumbered after the strip. So we truncate the revlog on the first of these revisions, and trust that the caller has saved the revisions that shouldn't be removed and that it'll readd them after this truncation. iNii(RRpR;R`RRXRRRRR@RRRRRDR{RV(R?tminlinkR RRFR,((s#/sys/lib/python/mercurial/revlog.pytstrip s*    c Csd}t|o&td|it|d}ny<|i|i}|idd|i}||}Wn5tj o)}|iti jond}nXy|i|i }|idd|i}|i i }td||}|||}|i oUd} x*|D]"} | td|i| 7} q"Wd}|t||| }nWn5tj o)}|iti jond}nX||fS(Niii(RRNRFRRRBttellRRRRRR@RR( R?texpectedRtactualtddRRRQtdit databytesR((s#/sys/lib/python/mercurial/revlog.pyt checksize9s> &        cCs.|ig}|ip|i|in|S(N(RRR!R(R?tres((s#/sys/lib/python/mercurial/revlog.pytfiles\s  N(1R]R^R_RARRRRRbRsRRVRRRRXRFRRR@RRRRRRRRRRRRRRRRRRRRRR RRRR)R+R2R4(((s#/sys/lib/python/mercurial/revlog.pyRs\ >                  '(  "           % '  2 1 s , #i(6R_RVRRRRRti18nRRRRRterrorR2R7RRtpackRfRRdR"R'R0R-tsha1RRRRtREVLOG_DEFAULT_FLAGStREVLOG_DEFAULT_FORMATRRwR.RRR R RRtobjectR1R`RlRvt v0shaoffsetRuR9RERRR(((s#/sys/lib/python/mercurial/revlog.pys sH(H$               %(