\x89\x50\x4E\x47\x0D\x0A\x1A\x0A PNG  \x89\x50\x4E\x47\x0D\x0A\x1A\x0A  13\c@@sdZddlmZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z ddl mZddlmZmZmZmZmZmZmZmZmZmZmZmZd ZiZejeZiZej eZ d6Z!x+e!D]#Z"e d de"ddde$q!We d ddddde%e dfZ&ddge de dfZ'ddge de dfZ(dde%e dfZ)dde%e d fZ*e d!Z+ed e&e'e(e)e*ge+d"ej,d#Z-d$Z.d%Z/d&Z0d'Z1d(Z2d)Z3d*Z4d+Z5d,Z6d-Z7d.Z8d/Z9d0Z:d1Z;d2Z<d3Z=d4e>fd5YZ?dS(7srewrite file content in changesets or working copy (EXPERIMENTAL) Provides a command that runs configured tools on the contents of modified files, writing back any fixes to the working copy or replacing changesets. Here is an example configuration that causes :hg:`fix` to apply automatic formatting fixes to modified lines in C++ code:: [fix] clang-format:command=clang-format --assume-filename={rootpath} clang-format:linerange=--lines={first}:{last} clang-format:fileset=set:**.cpp or **.hpp The :command suboption forms the first part of the shell command that will be used to fix a file. The content of the file is passed on standard input, and the fixed file content is expected on standard output. If there is any output on standard error, the file will not be affected. Some values may be substituted into the command:: {rootpath} The path of the file being fixed, relative to the repo root {basename} The name of the file being fixed, without the directory path If the :linerange suboption is set, the tool will only be run if there are changed lines in a file. The value of this suboption is appended to the shell command once for every range of changed lines in the file. Some values may be substituted into the command:: {first} The 1-based line number of the first line in the modified range {last} The 1-based line number of the last line in the modified range The :fileset suboption determines which files will be passed through each configured tool. See :hg:`help fileset` for possible values. If there are file arguments to :hg:`fix`, the intersection of these filesets is used. There is also a configurable limit for the maximum size of file that will be processed by :hg:`fix`:: [fix] maxfilesize=2MB i(tabsolute_importN(t_(tnullrev(twdirrev(tprocutil( tcmdutiltcontexttcopiesterrortmdifftmergetobsoletetpycompatt registrartscmutiltutiltworkersships-with-hg-coretcommandt linerangetfilesettfixs.*(:%s)?tdefaulttgenerict maxfilesizet2MBttalls)fix all non-public non-obsolete revisionstbasesdrevisions to diff against (overrides automatic selection, and applies to every revision being fixed)tREVtrtrevsrevisions to fixtws working-dirsfix the working directorytwholesalways fix every line of a files[OPTION]... [FILE]...t helpcategoryc@stjdrUdr;tjtdndgds RtfixphaseN(t iteritemsRt cleanupnodesR;(R.RXRY((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRQs c C@s#g}tjt}|jdd}xt|D]} || } tj| ||} xt||||| || | D]} | | krq|n| | } | jrq|n| j |kr|j t dt j || fq|n|j| | f|| cd7Aborts if the revision shouldn't be replaced with a fixed one.s can't fix immutable changeset %st experimentalsevolution.allowdivergences/fixing obsolete revision could cause divergenceN(tmutableRR:RtformatchangeidR t configbool(R/R.R(tallowdivergence((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRps     c C@s|t}xl|D]d}|j|d|dt|dt|} |jttj| j| j| j| j qW|S(sReturns the set of files that should be fixed in a context The result depends on the base contexts; we include any file that has changed relative to any of the base contexts. Base contexts should be ancestors of the context being fixed. Rdt listcleant listunknown( RntstatusROtupdatet itertoolstchaintaddedtmodifiedtcleantunknown( R/R.RRR-RdR+RkR6tbasectxtstat((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRes  c C@s|jdrtd|Sg}xg|D]_}tj||j||}||krl||j}nd}|jt||q)Wt|S(sReturns the set of line ranges that should be fixed in a file Of the form [(10, 20), (30, 40)]. This depends on the given base contexts; we must consider lines that have changed versus any of the base contexts, and whether the file has been renamed versus any of them. Another way to understand this is that we exclude line ranges that are common to the file in all base contexts. R R(RstdifflinerangesRt pathcopiesR#textendt unionranges( R-R'R+Rktcontent2t rangeslistRtbasepathtcontent1((s//usr/lib64/python2.7/site-packages/hgext/fix.pyt lineranges-s    cC@stt|}g}|r9|dg|d}}nxc|D][\}}|d\}}||dkr|j||fq@|t||f|d>> unionranges([]) [] >>> unionranges([(1, 100)]) [(1, 100)] >>> unionranges([(1, 100), (1, 100)]) [(1, 100)] >>> unionranges([(1, 100), (2, 100)]) [(1, 100)] >>> unionranges([(1, 99), (1, 100)]) [(1, 100)] >>> unionranges([(1, 100), (40, 60)]) [(1, 100)] >>> unionranges([(1, 49), (50, 100)]) [(1, 100)] >>> unionranges([(1, 48), (50, 100)]) [(1, 48), (50, 100)] >>> unionranges([(1, 2), (3, 4), (5, 6)]) [(1, 6)] iii(RHRnRjtmax(Rtunionedtatbtctd((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRHscC@srg}xetj||D]Q\}}|dd!\}}|dkr||kr|j|d|fqqW|S(sReturn list of line number ranges in content2 that differ from content1. Line numbers are 1-based. The numbers are the first and last line contained in the range. Single-line ranges have the same line number for the first and last line. Excludes any empty ranges that result from lines that are only present in content1. Relies on mdiff's idea of where the line endings are in the string. >>> from mercurial import pycompat >>> lines = lambda s: b'\n'.join([c for c in pycompat.iterbytestr(s)]) >>> difflineranges2 = lambda a, b: difflineranges(lines(a), lines(b)) >>> difflineranges2(b'', b'') [] >>> difflineranges2(b'a', b'') [] >>> difflineranges2(b'', b'A') [(1, 1)] >>> difflineranges2(b'a', b'a') [] >>> difflineranges2(b'a', b'A') [(1, 1)] >>> difflineranges2(b'ab', b'') [] >>> difflineranges2(b'', b'AB') [(1, 2)] >>> difflineranges2(b'abc', b'ac') [] >>> difflineranges2(b'ab', b'aCb') [(2, 2)] >>> difflineranges2(b'abc', b'aBc') [(2, 2)] >>> difflineranges2(b'ab', b'AB') [(1, 2)] >>> difflineranges2(b'abcde', b'aBcDe') [(2, 2), (4, 4)] >>> difflineranges2(b'abcde', b'aBCDe') [(2, 4)] iit!i(R t allblocksRj(RRtrangestlinestkindt firstlinetlastline((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRjs 'c@s|jdrlttj|jd}|sBth}nfd|Dfd|DStjtxvt|D]h}|}xU|jD]G}|j kr|j |j q|j |qWqWS(s4Returns a map of the base contexts for each revision The base contexts determine which lines are considered modified when we attempt to fix just the modified lines in a file. It also determines which files we attempt to fix, so it is important to compute this even when --whole is used. Rc@sh|]}|qS(((R\R(R.(s//usr/lib64/python2.7/site-packages/hgext/fix.pys s c@si|]}|qS(((R\R(R+(s//usr/lib64/python2.7/site-packages/hgext/fix.pys s ( RsRnRRoRRERFRHtparentsRRRt(R.R-RStbaserevsRR(tpctx((R+R.s//usr/lib64/python2.7/site-packages/hgext/fix.pyR@s !  c @shjxQ|jD]C\}}|jrfd}|j||} | d krqn|jd| ftjtj | dt dtj ddtj dtj dtj } | j \} } | rt |j|| n| jd kr+| q`| s`t |j|td | jfq`qqWS( sRun any configured fixers that should affect the file in this context Returns the file content that results from applying the fixers in some order starting with the file's content in the fixctx. Fixers that support line ranges will affect lines that have changed relative to any of the basectxs (i.e. they will only avoid lines that are common to all basectxs). A fixer tool's stdout will become the file's new content if and only if it exits with code zero. c@stS(N(R((R+RkR*R-R'(s//usr/lib64/python2.7/site-packages/hgext/fix.pytsssubprocess: %s tshelltcwdt/tstdintstdouttstderrisexited with status %d N(R#R`taffectsRR%tdebugt subprocesstPopenRt tonativestrR;tPIPEt communicatet showstderrRt returncodeR( R/R-R,RkR'R+t fixernametfixertrangesfnRtproct newerdataR((R+RkR*R-R's//usr/lib64/python2.7/site-packages/hgext/fix.pyR$s0      !cC@sxtjd|D]t}|r|jd|dkrT|jtdddn|jt|dd|jd||fqqWdS(s9Writes the lines of the stderr string as warnings on the ui Uses the revision number and fixername to give more context to each line of the error message. Doesn't include file names, since those take up a lot of space and would tend to be included in the error message if they were relevant. s[ ]+t[twdirtlabels evolve.revs ] %s: %s N(tretsplitRhR%Rtstr(R/RRRtline((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRs  c C@sx`|jD]R\}}||}|j||j|j|dkr |jj|q q W|jj}g|D]}|j||^qy} | |kr|j| ndS(sWrite new content to the working copy and check out the new p1 if any We check out a new revision if and only if we fixed something in both the working directory and its parent revision. This avoids the need for a full update/merge, and means that the working directory simply isn't affected unless the --working-dir flag is given. Directly updates the dirstate for the affected files. tnN(R`twritetflagstdirstatet normallookupRRst setparents( R.R(RWRXR'R#RltoldparentnodesRtnewparentnodes((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRNs  % c@sX|jjj\}}||||}}|j|j|j} |j|j|j} fd} tj|d| | fdjdtj tj Bd| dj dj dj d jd d  } | j} j}|| krD|jd jn| |jReturns the names of [fix] config options that have suboptionsRt:ii(Rnt configitemsRtR(R/tnamestktv((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRIs   $RcB@s eZdZdZdZRS(s4Wraps the raw config values for a fixer with methodscC@stj||jg||S(s@Should this fixer run on the file at the given path and context?(RRdt_fileset(tselfR-RkR'((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRTsc C@stj}|||ji|d6tjj|d6g}|jr|}|sWdSxA|D]6\}}|j|||ji|d6|d6q^Wndj |S(sA shell command to use to invoke this fixer on the given file/lines May return None if there is no appropriate command to run for the given parameters. trootpathtbasenametfirsttlastt N( Rtrendercommandtemplatet_commandtosR'Rt _linerangeR%Rjtjoin( RR/R'RtexpandtpartsRRR((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRXs  &  (t__name__t __module__t__doc__RR(((s//usr/lib64/python2.7/site-packages/hgext/fix.pyRQs (RRR(@Rt __future__RRERRRRtmercurial.i18nRtmercurial.nodeRRtmercurial.utilsRt mercurialRRRRR R R R R RRRt testedwithtcmdtableRt configtablet configitemRRR%R;RDtallopttbaseopttrevopttwdiropttwholeopttusagetCATEGORY_FILE_CONTENTSRRQRAR?RrRpReRRRR@R$RRNRPRBRtobjectR(((s//usr/lib64/python2.7/site-packages/hgext/fix.pyt/s\     R !! S  &     " .  $   ;