o ]Lb}}@sddlmZddlZddlZddlZddlZddlZddlmZddl m Z m Z m Z ddl mZmZmZmZddlmZejZejZdd Zd d Zd Zd ZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-Gd d!d!e.Z/e/dd"e,d#Z0e/dd"e,d#Z1e/d$d"e+d#Z2e/d%d"e-d#Z3e/d&Z4e/d'Z5e/d(d"e+d#Z6e/d)d"e+d#Z7e/d*Z8e/d+Z9e/dZ:e/d,Z;e/d-Ze/d1d"d/Z?e/d2d"e-d#Z@e/d3d"e+d#ZAe:eascii)r0decoder;rrr__repr__szMergeAction.__repr__cC|jSrr0r;rrr __bytes__zMergeAction.__bytes__cCs&|durdSt|ts J|j|jkSNF) isinstancer/r0r7otherrrr__eq__s zMergeAction.__eq__cCs |j|jkSrrBrGrrr__lt__s zMergeAction.__lt__)FFN)__name__ __module__ __qualname____doc__weakrefWeakSetr1r4r9r<r@rCrIrJrrrrr/js   r/T)r5r6agpprsamcsdcscdsdgsdmk)r3skasknescmc@seZdZdZddZddZd9ddZejd d Z ejd d Z ejd dZ ejddZ ddZ ddZeddZddZddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zd+d,Zd-d.Zd/d0Zd1d2Zd3d4Zd5d6Z d7d8Z!dS):_mergestate_baseatrack 3-way merge state of individual files The merge state is stored on disk when needed. Two files are used: one with an old format (version 1), and one with a new format (version 2). Version 2 stores a superset of the data in version 1, including new kinds of records in the future. For more about the new format, see the documentation for `_readrecordsv2`. Each record can contain arbitrary content, and has an associated type. This `type` should be a letter. If `type` is uppercase, the record is mandatory: versions of Mercurial that don't support it should abort. If `type` is lowercase, the record can be safely ignored. Currently known records: L: the node of the "local" part of the merge (hexified version) O: the node of the "other" part of the merge (hexified version) F: a file to be merged entry C: a change/delete or delete/change conflict P: a path conflict (file vs directory) f: a (filename, dictionary) tuple of optional values for a given file l: the labels for the parts of the merge. Merge record states (stored in self._state, indexed by filename): u: unresolved conflict r: resolved conflict pu: unresolved path conflict (file conflicts with directory) pr: resolved path conflict o: file was merged in favor of other parent of merge (DEPRECATED) The resolve command transitions between 'u' and 'r' for conflicts and 'pu' and 'pr' for path conflicts. cCs:||_i|_tt|_d|_d|_d|_i|_ d|_ dS)z^Initialize the merge state. Do not use this directly! Instead call read() or clean().NF) _repo_state collections defaultdictdict _stateextras_local_other_labels_results_dirtyr7rrrrr9s  z_mergestate_base.__init__cCsdSrrr;rrrresetsz_mergestate_base.resetNcCs||_||_||_dSr)r_r`ra)r7noderHlabelsrrrstarts z_mergestate_base.startcC|jdur d}t||jS)Ns(local accessed but self._local isn't set)r_rProgrammingErrorr7msgrrrlocal  z_mergestate_base.localcC |j|jSr)rYrmr;rrrlocalctx  z_mergestate_base.localctxcCri)Ns(other accessed but self._other isn't set)r`rrjrkrrrrHrnz_mergestate_base.othercCror)rYrHr;rrrotherctxrqz_mergestate_base.otherctxcCst|jp t|jS)zWhether mergestate is active. Returns True if there appears to be mergestate. This is a rough proxy for "is a merge in progress." )boolr_rZr;rrractivesz_mergestate_base.activecCsdS)z*Write current state on disk (if necessary)Nrr;rrrcommit#sz_mergestate_base.commitcCstt|S)zUhash the path of a local file context for storage in the .hg/merge directory.)rr sha1digest)pathrrr getlocalkey&sz_mergestate_base.getlocalkeycCtrNotImplementedErrorr7fctxlocalkeyrrr _make_backup-rDz_mergestate_base._make_backupcCrzrr{r7r~rflagsrrr_restore_backup0rDz _mergestate_base._restore_backupc Cs|r |jjj}n t|}|||t|||t | |t | | g|j |<t | |j|d<d|_dS)a/add a new (potentially?) conflicting file the merge state fcl: file context for local, fco: file context for remote, fca: file context for ancestors, fd: file path of the resulting merge. note: also write the local version to the `.hg/merge` directory. ancestorlinknodeTN)isabsentrYrr mergestateryrxrMERGE_RECORD_UNRESOLVEDrfilenoderrZrfr^rc)r7fclfcofcafdrrrrr23s      z_mergestate_base.addcCst||g|j|<d|_dS)zadd a new conflicting path to the merge state path: the path that conflicts frename: the filename the conflicting file was renamed to forigin: origin of the file ('l' or 'r' for local/remote) TN)MERGE_RECORD_UNRESOLVED_PATHrZrc)r7rxfrenameforiginrrraddpathconflictNs z _mergestate_base.addpathconflictcCs|j||d|_dS)zHstores information which is required at commit into _stateextrasTN)r^updaterc)r7rxrrrr addcommitinfoWs z_mergestate_base.addcommitinfocCs ||jvSrrZr7dfilerrr __contains__]r=z_mergestate_base.__contains__cCs|j|dS)Nrrrrrr __getitem__`z_mergestate_base.__getitem__cCstt|jSr)itersortedrZr;rrr__iter__crz_mergestate_base.__iter__cCs |jSr)rZkeysr;rrrfilesfr=z_mergestate_base.filescCs||j|d<d|_dS)NrT)rZrc)r7rstaterrrmarkis z_mergestate_base.markccs2t|jD]\}}|dttfvr|VqdS)z%Obtain the paths of unresolved files.rN)r iteritemsrZrr)r7rentryrrr unresolvedmsz_mergestate_base.unresolvedcCrA)z8return all extras information stored with the mergestater^r;rrr allextraswsz_mergestate_base.allextrascCs |j|S)z?return extras stored with the mergestate for the given filenamer)r7filenamerrrextras{s z_mergestate_base.extrasc Cs||ttfvr dS|j|}|\}}}}}} } } |j|j} ||} | d}|r1|j|}nd}t|||}t| | | }|jj|||d}| }| }d| ||vr|d| ||vr|| t krv| |krv|jj td|n| |kr||} ||jjjkr||||| n||jdd ||s|j|=d |j|<d|_dStj|j||j|||||jd \}}|s||td}|r|rt}nt}n|rt}n|r||jvrt}nt }||f|j|<|S) zHrun merge process for dfile Returns the exit code of the merge.rrN)fileid changectxxr"sQwarning: cannot merge flags for %s without common ancestor - keeping local flags T) ignoremissing)NN)rg)!MERGE_RECORD_RESOLVEDLEGACY_RECORD_DRIVER_RESOLVEDrZrYr`rgetrfilectxrrevruiwarnrrrrremovecmprbrcr r_rarr ACTION_FORGET ACTION_REMOVE ACTION_GETrpACTION_ADD_MODIFIED ACTION_ADD)r7rwctx stateentryrrlfileafileanodeofileonoderoctxr anccommitnodeactxfcdrrflofla merge_retdeletedactionrrrresolves|             z_mergestate_base.resolvecCs^d\}}}t|jD]\}}|dur|d7}q |dkr)|tkr%|d7}q |d7}q |||fS)zKreturn counts for updated, merged and removed files in this session)rrrNrr)r itervaluesrbr)r7updatedmergedremovedrrrrrcountss    z_mergestate_base.countscCstt|S)z0get unresolved count for this merge (persistent))lenlistrr;rrrunresolvedcountsz _mergestate_base.unresolvedcountc CsRtgtgtgtgtgi}t|jD]\}\}}|dur&|||ddfq|S)z2return lists of actions to perform on the dirstateNs merge result) rrrrrr rrbappend)r7actionsrrrrrrrsz_mergestate_base.actionsr)"rKrLrMrNr9rerhr propertycachermrprHrrrtru staticmethodryrrr2rrrrrrrrrrrrrrrrrrrXsD"        U rXc@seZdZdZdZeddZeddZddZd d Z d d Z d dZ ddZ ddZ ddZddZddZddZddZddZdd Zd!S)"rs merge/states merge/state2cCt|}||S)zPInitialize a brand new merge state, removing any existing state on disk.)rrermsrrrcleanszmergestate.cleancCr)z1Initialize the merge state, reading it from disk.)r_readrrrrreadszmergestate.readc CsVt}|}|D]\}}|tkrt||_q |tkr!t||_q |tkr&q |tt t t t fvrP| d}|dtkrDd|j|dd<q |dd|j|d<q |tkr| dd\}}| d}i} d} | t|kr|| d| || <| d7} | t|ksk| |j|<q |tkr| dd} dd | D|_q |s||q |rt|dS) zAnalyse each record content to restore a serialized state from disk This function process "record" entry produced by the de-serialization of on disk file. r rsotherrsfilenode-sourceNcSsg|] }t|dkr|qS)r)r).0lrrr 3sz$mergestate._read..)set _readrecords RECORD_LOCALrr_ RECORD_OTHERr`LEGACY_MERGE_DRIVER_STATE RECORD_MERGEDRECORD_CHANGEDELETE_CONFLICTRECORD_PATH_CONFLICTLEGACY_MERGE_DRIVER_MERGELEGACY_RECORD_RESOLVED_OTHERrMERGE_RECORD_MERGED_OTHERr^rZRECORD_FILE_VALUESr RECORD_LABELSraislowerr2rUnsupportedMergeRecords) r7 unsupportedrecordsrtyperecordrr rawextras extrapartsrirgrrrr sN           zmergestate._readcCs|}|}|||r|S|jdd}|t|ft|D]"\}}|dt krH|d d}| dd|dd |f||<q&|S)aRead merge state from disk and return a list of record (TYPE, data) We read data from both v1 and v2 files and decide which one to use. V1 has been used by version prior to 2.9.1 and contains less data than v2. We read both versions and check if no data in v2 contradicts v1. If there is not contradiction we can safely assume that both v1 and v2 were written at the same time and use the extract data in v2. If there is contradiction we ignore v2 content as we assume an old version of Mercurial has overwritten the mergestate file and left an old v2 file around. returns list of record [(TYPE, data), ...]Nrrrr r) _readrecordsv1_readrecordsv2 _v1v2matchrYparentsrrr enumeraterrinsertr)r7 v1records v2recordsmctxidxrrrrrr:s   zmergestate._readrecordscCsft}|D]}|dtkr||q|dtkr$|tt|dfq|D] }||vr0dSq'dS)NrrFT)rrr2rr)r7rroldv2recrrrr\s   zmergestate._v1v2matchc Csg}z2|j|j}t|D]\}}|dkr"|t|ddfq|t|ddfq|W|StyN}z|j t j krCWYd}~|Sd}~ww)zread on disk merge state for version 1 file returns list of record [(TYPE, data), ...] Note: the "F" data from this file are one entry short (no "other file node" entry) rNr) rYvfs statepathv1rrrrcloseIOErrorerrnoENOENT)r7rrrrerrrrrrjs    zmergestate._readrecordsv1c Csg}za|j|j}|}d}t|}||kr]|||d}|d7}td|||dd}|d7}||||}||7}|tkrR|dd|dd}}|||f||ks|W|St y}} z| j t j krrWYd} ~ |Sd} ~ ww)aread on disk merge state for version 2 file This format is a list of arbitrary records of the form: [type][length][content] `type` is a single character, `length` is a 4 byte integer, and `content` is an arbitrary byte sequence of length `length`. Mercurial versions prior to 3.7 have a bug where if there are unsupported mandatory merge records, attempting to clear out the merge state with hg update --clean or similar aborts. The 't' record type works around that by writing out what those versions treat as an advisory record, but later versions interpret as special: the first character is the 'real' record type and everything onwards is the data. Returns list of records [(TYPE, data), ...].rrs>IN) rYr statepathv2rr_unpackRECORD_OVERRIDErrrrr ) r7rrroffendrlengthrr rrrrs4   zmergestate._readrecordsv2cCs&|jr|}||d|_dSdSrE)rc _makerecords _writerecordsr7rrrrrus   zmergestate.commitcCs:g}|tt|jf|tt|jft|jD]G\}}|dt t fvr6|t d |g|fq|d|j jjksH|d|j jjkrV|td |g|fq|td |g|fqtt|jD]\}}d ddt|D}|td||ffql|jdurd |j}|t|f|S)Nrr rcss |] \}}d||fVqdS)%s%sNr)rkvrrr s z*mergestate._makerecords..r)rrrr_rr`r rrZrMERGE_RECORD_RESOLVED_PATHrrrYrrrrrr^rrar)r7rrrrrrgrrrrs8   zmergestate._makerecordscCs||||dS)z,Write current state on disk (both v1 and v2)N)_writerecordsv1_writerecordsv2rrrrrs zmergestate._writerecordscCsx|j|jd}t|}t|}|dtksJ|t|jd|D]\}}|t kr5|dt |q$| dS)z/Write current state on disk in a version 1 filewbr s%s N) rYrrrnextrwriterr_rrr)r7rrirecordslrecordsrrrrrrs  zmergestate._writerecordsv1cCstttf}|j|jd}|D]+\}}t|dksJ||vr(td||f}}dt|}|t ||t||q| dS)zqWrite current state on disk in a version 2 file See the docstring for _readrecordsv2 for why we use 't'.rrs%s%ss>sI%isN) rrrrYrr rrr _packr)r7r allowlistrkeyrformatrrrrs    zmergestate._writerecordsv2cCs|jjd||dSNsmerge/)rYrr rr}rrrrszmergestate._make_backupcCsF|jd|}|||WddS1swYdSr')rYrr r)r7r~rrrrrrrs"zmergestate._restore_backupcCst|jjdddS)NsmergeT)shutilrmtreerYrrr;rrrreszmergestate.resetN)rKrLrMrr rrrrrrrrrurrrrrrrerrrrrs(  1"(-  rcs,eZdZfddZddZddZZS) memmergestatecstt||i|_dSr)superr*r9_backupsrd __class__rrr9s zmemmergestate.__init__cCs||j|<dSr)rr,r}rrrr szmemmergestate._make_backupcCs||j||dSr)r r,rrrrrszmemmergestate._restore_backup)rKrLrMr9rr __classcell__rrr-rr*s r*cCs|tgD]\}}}|r|jj|dddq|jj|dddq|tgD]\}}}|jj|dddq'|tgD]0\}}}|\}}|jj|ddd|j||||krc|jj|dddq<|jj|dddq<|tgD]\}}}|jj|dddqs|tgD]\}}}|r|jj|ddddq|jj|dddq|t gD]\}}}|jj|ddddq|t gD]\}}}q|t gD]\}}}q|t gD]\}}}q|t gD]3\}}}|r|j|} | jo| j } |jj|| dddq|r ||nd} |jj|dd| dq|tgD]a\}}}|\} } }}}|rc| |k} |jj|| ddd| | kra|rL|jj| ddd| |krZ|j| |q|j| |q| |krr|jj|dddd|r~|jj| dddq|tgD]:\}}}|\}}|r|jj|ddd|jj|ddd|j||q|jj|ddd|jj|dddq|tgD](\}}}|\}}|r|jj|ddd|j||q|jj|dddqdS)z$record merge actions to the dirstateTF) p1_tracked wc_tracked)r0r1possibly_dirty)r0r1p2_infoN)r0r1parentfiledata)rrdirstate update_filerACTION_PATH_CONFLICT_RESOLVEcopyrr ACTION_EXEC ACTION_KEEPACTION_KEEP_ABSENTACTION_KEEP_NEWr get_entry any_trackedadded ACTION_MERGEACTION_DIR_RENAME_MOVE_LOCALACTION_LOCAL_DIR_RENAME_GET)rr branchmerge getfiledatarargsrlf0origf0 old_entryr0r4f1f2famoveancflagrrr recordupdatess    rO)G __future__rr[rr(structrOi18nrrfrrrrr r r utilsr packr#unpackr rrrrrrrrrrrrrrrrrrr CHANGE_ADDEDCHANGE_REMOVEDCHANGE_MODIFIEDobjectr/rrrrACTION_PATH_CONFLICTr7rACTION_CREATEDACTION_DELETED_CHANGEDACTION_CHANGED_DELETEDr@rBrAr:r;r<r9ACTION_CREATED_MERGECONVERT_MERGE_ACTIONSrXrr*rOrrrrs    7   /