\x89\x50\x4E\x47\x0D\x0A\x1A\x0A PNG  \x89\x50\x4E\x47\x0D\x0A\x1A\x0A  13\c @@s?dZddlmZddlZddlZddlZddlZddlZddlm Z ddl m Z m Z m Z ddlmZddlmZmZmZmZmZmZmZmZmZmZmZddlmZmZydd lmZej Wne!k r$e"ZnXiZ#ej$e#Z$e$d d d erRd nddZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dddddddd e+gZ2e"d!Z3d"Z4d#ej5fd$YZ6ej7d%e8fd&YZ9ej:ej;ej7d'e<d(e8fd)YZ=ej:ej>ej7d*e<d+e8fd,YZ?ej:ej@d-e8fd.YZAd/ejBfd0YZCd1ZDd2ZEd3ZFej:ejGd4e8fd5YZHd6ZId7ZJd8ZKd9ZLd:ZMdS(;smstore repository data in SQLite (EXPERIMENTAL) The sqlitestore extension enables the storage of repository data in SQLite. This extension is HIGHLY EXPERIMENTAL. There are NO BACKWARDS COMPATIBILITY GUARANTEES. This means that repositories created with this extension may only be usable with the exact version of this extension/Mercurial that was used. The extension attempts to enforce this in order to prevent repository corruption. In addition, several features are not yet supported or have known bugs: * Only some data is stored in SQLite. Changeset, manifest, and other repository data is not yet stored in SQLite. * Transactions are not robust. If the process is aborted at the right time during transaction close/rollback, the repository could be in an inconsistent state. This problem will diminish once all repository data is tracked by SQLite. * Bundle repositories do not work (the ability to use e.g. `hg -R log` to automatically overlay a bundle on top of the existing repository). * Various other features don't work. This extension should work for basic clone/pull, update, and commit workflows. Some history rewriting operations may fail due to lack of support for bundle repositories. To use, activate the extension and set the ``storage.new-repo-backend`` config option to ``sqlite`` to enable new repositories to use SQLite for storage. i(tabsolute_importN(t_(tnullidtnullrevtshort(tattr( tancestortdagopterrort extensionst localrepotmdifftpycompatt registrart repositorytutiltverify(t interfaceutilt storageutil(tzstdtstoragessqlite.compressiontdefaultRtzlibsships-with-hg-coresexp-sqlite-001sexp-sqlite-comp-001=zstdsexp-sqlite-comp-001=zlibsexp-sqlite-comp-001=nonesexp-sqlite-shallow-filesiiiisCREATE TABLE delta ( id INTEGER PRIMARY KEY, compression INTEGER NOT NULL, hash BLOB UNIQUE ON CONFLICT ABORT, delta BLOB NOT NULL )sKCREATE TABLE filepath ( id INTEGER PRIMARY KEY, path BLOB NOT NULL )s8CREATE UNIQUE INDEX filepath_path ON filepath (path)scCREATE TABLE fileindex ( id INTEGER PRIMARY KEY, pathid INTEGER REFERENCES filepath(id), revnum INTEGER NOT NULL, p1rev INTEGER NOT NULL, p2rev INTEGER NOT NULL, linkrev INTEGER NOT NULL, flags INTEGER NOT NULL, deltaid INTEGER REFERENCES delta(id), deltabaseid INTEGER REFERENCES fileindex(id), node BLOB NOT NULL )sJCREATE UNIQUE INDEX fileindex_pathrevnum ON fileindex (pathid, revnum)sFCREATE UNIQUE INDEX fileindex_pathnode ON fileindex (pathid, node)sCREATE VIEW filedata AS SELECT fileindex.id AS id, filepath.id AS pathid, filepath.path AS path, fileindex.revnum AS revnum, fileindex.node AS node, fileindex.p1rev AS p1rev, fileindex.p2rev AS p2rev, fileindex.linkrev AS linkrev, fileindex.flags AS flags, fileindex.deltaid AS deltaid, fileindex.deltabaseid AS deltabaseid FROM filepath, fileindex WHERE fileindex.pathid=filepath.idsPRAGMA user_version=%dcC@sQ|jdjddjdgt|t||gt|j}g}d}x|D]\} } } | }| tkr|j | } nC| t kr| } n.| t krt j | } nt d| |j| qcW||kr|||} n |j} |jtj| |} t| tsMt| } n| S(s&Resolve a delta chain for a file node.sWITH RECURSIVE deltachain(deltaid, baseid) AS ( SELECT deltaid, deltabaseid FROM fileindex WHERE pathid=? AND node=? UNION ALL SELECT fileindex.deltaid, deltabaseid FROM fileindex, deltachain WHERE fileindex.id=deltachain.baseid AND deltachain.baseid IS NOT NULL AND fileindex.id NOT IN ({stops}) ) SELECT deltachain.baseid, compression, delta FROM deltachain, delta WHERE delta.id=deltachain.deltaidtstopst,t?sunhandled compression type: %dN(texecutetformattjointlenttupletlisttkeystNonetCOMPRESSION_ZSTDt decompresstCOMPRESSION_NONEtCOMPRESSION_ZLIBRtSQLiteStoreErrortappendtpoptreverseR tpatchest isinstancetbytes(tdbtpathidtnodet revisioncachetstopridstzstddctxtrestdeltastlastdeltabaseidt deltabaseidt compressiontdeltatbasetexttfulltext((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytresolvedeltachains2  %        cC@sUy |jd|||fjSWn.tjk rP|jd|fjdSXdS(Ns=INSERT INTO delta (compression, hash, delta) VALUES (?, ?, ?)s!SELECT id FROM delta WHERE hash=?i(Rt lastrowidtsqlite3tIntegrityErrortfetchone(R-R7thashR8((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyt insertdeltasR&cB@seZRS((t__name__t __module__(((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyR&st revisionentrycB@steZejZejZejZejZejZejZ ejZ ejZ ejZ RS(( RBRCRtibtridtrevR/tp1revtp2revtp1nodetp2nodetlinkrevtflags(((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyRDs        tslotstsqliterevisiondeltacB@szeZejZejZejZejZejZejZ ejZ ejZ ejddZ RS(RN(RBRCRRER/RJRKtbasenodeRMtbaserevisionsizetrevisionR8R!tlinknode(((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyROs        tfrozent sqliteproblemcB@s>eZejddZejddZejddZRS(RN(RBRCRRER!twarningRR/(((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyRU!stsqlitefilestorecB@seZdZdZdZdZdZdZdd%dZ dZ d Z d Z d Z d Zd ZdZdZdZd%d%dZdZdZeedZdZdZdZd%eeedZdZd%dd%dZd%edZddZ dZ!dZ"d Z#eeeeed!Z$d"Z%d%d%d#Z&d%dd$Z'RS(&s2Implements storage for an individual tracked path.cC@s||_||_d|_i|_i|_i|_tjd|_ ||_ |dkrt j dd|_ t j|_nd|_ d|_|jdS(Ni Rtleveli(t_dbt_pathR!t_pathidt _revtonodet _nodetorevt _revisionsRt lrucachedictt_revisioncachet _compengineRtZstdCompressort_cctxtZstdDecompressort_dctxt _refreshindex(tselfR-tpathR7((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyt__init__,s          cC@si|_i|_i|_t|jjd|jf}|sOd|_dS|dd|_|jjd|jf}xt |D]\}}|\}}}}}} } ||krt t dn|t krt } n |j|} |t krt } n |j|} td|d|d|d|d |d | d | d | d | } ||j|<||j|<| |j|s tstartrevtstoprevs( R!RRRGRRtheadrevssubsetRwR{R/(RgRtRuRRRwRG((Rgs7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytheadss  !cC@sK|j|}|jjd|j||f}g|D]}|d^q7S(NsZSELECT node FROM filedata WHERE path=? AND (p1rev=? OR p2rev=?) ORDER BY revnum ASCi(RGRYRRZ(RgR/RGR3Rl((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytchildrens  cC@sp|tkrdS||jkr.t|n|j|}|j|r]t|j|St|j|S(Ni(RR\RztrenamedRtreadRR(RgRGR/((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytsizes  c@s"|ttfkrdSt|tr7j|}n|jkrgtj|jt dn|j krj |Sfdj D}|sd|ds iR2(RRR+tintR/R]RRxRZRR`R!R;RYR[ReR^RMtFLAG_MISSING_P1tFLAG_MISSING_P2Rrt _checkhash(RgR/trawt _verifyhashR1R:((Rgs7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyRRs*!       cC@stj|j|S(N(RtfiltermetadataRR(RgR/((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyR'scC@stj||S(N(Rtfilerevisioncopied(RgR/((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyR*scC@stj||| S(N(Rtfiledataequivalent(RgR/R:((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytcmp-sc c@s&|dkr"tjd|ng|D]}|tkr)|^q)}|sQdS|jjddjdgt|t|j g|}i}xF|D]>\} } |jjd|j | f}|j d || lllRRc@stj|dtS(NR(RRRtTrue(tx(Rg(s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytss0UPDATE fileindex SET p1rev=?, flags=? WHERE id=?s0UPDATE fileindex SET p2rev=?, flags=? WHERE id=?Rt storedeltaRM(&RtREVISION_FLAG_CENSOREDR~R&RRsRRRGRRtstructtcalcsizeRRRRRrR treplacediffheaderRtCensoredBaseErrorRZRtdeltaiscensoredR'R^RMRJR]RHRYRRFRKRItpatchR!R(RgR4t linkmapperRt addrevisioncbtmaybemissingparentsRR/RRRSt deltabaseR8t wireflagst storeflagstbaserevthlentoldlentnewlenRLRmttextR((Rgs7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytaddgrouprsp"                    Rc C@s|tji|d6d}t|t|j|dtkrXtjtdn|jj d|j |j fj d}t |jj d||f}x:|D]2}|\}}} t|j|| iidd6d |j} tj| j} |jd kr+|jj| } t} n[|jd krRtj| } t} n4|jd krp| } t} ntjd |jt| t| kr| } t} nt|j| | | }|jj d||fqWtj|j} t|jt| |}|j |j}|tO}|jj d|||j|f|jj d|f|j |j!j"dS(NtcensoredRRs5censor tombstone must be no longer than censored datas(SELECT deltaid FROM fileindex WHERE id=?isGSELECT id, pathid, node FROM fileindex WHERE deltabaseid=? OR deltaid=?iR2RRtnones unhandled compression engine: %ss;UPDATE fileindex SET deltaid=?, deltabaseid=NULL WHERE id=?sSUPDATE fileindex SET flags=?, deltaid=?, deltabaseid=NULL WHERE pathid=? AND node=?sDELETE FROM delta WHERE id=?(#RRRRRRRtAbortRRYRR^RFR?RR;R!Rethashlibtsha1tdigestRaRctcompressR"RR%R$RRARMR~R[RfR`tclear(Rgttrt censornodet tombstonetcensoreddeltaidtrowsRlRFR.R/R:t deltahasht deltablobR7RttombstonedeltaidRM((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytcensorrevisionsX'                   cC@sKtj|t|dg|jD]}|j|^q#|j|jS(Ni(RtresolvestripinfoRRRGRLR{(RgtminlinkR((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyt getstrippoints%cC@st|sdS|j|\}}|t|kr;dSx<|j|D]+}|jjd|j|j|fqKW|jdS(Ns/DELETE FROM fileindex WHERE pathid=? AND node=?(RRRwRYRR[R/Rf(RgRRRGt_ignored((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytstrip!s  cC@sgS(N((Rg((s7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pytfiles7sc@si}|rg|dJst trackedsizet storedsize(RtsumR]R!(RgRRRRRtd((Rgs7/usr/lib64/python2.7/site-packages/hgext/sqlitestore.pyt storageinfo:s   cc@st|d%s      L         =    %  4