ó œçƒQc @s dZyddlZWnek r5ddlZnXddlZddlZddlmZddlmZddlm Z ddlm Z ddlm Z ddlm Z dd lm Zdd lmZdd lmZdd lmZdd lmZddlmZddlmZddlmZiZejeƒZdZedƒZd„Zd„Zd„Zd„Zd„Z d„Z!d„Z"d„Z#d„Z$de&id„Z'i ed6ed6e d6e d 6e!d!6e!d"6e#d#6e#d$6e$d%6e$d&6Z(ed'd(d)d(ed*ƒfd+d,e&ed-ƒfd.d/e&ed0ƒfd(d1e&ed2ƒfd3d4e&ed5ƒfd!d6e&ed7ƒfd8d9ged:ƒfged;ƒƒd<„ƒZ)d=„Z*d>„Z+d?„Z,d@„Z-dA„Z.dB„Z/dC„Z0dD„Z1dE„Z2dS(Fs`interactive history editing With this extension installed, Mercurial gains one new command: histedit. Usage is as follows, assuming the following history:: @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42 | Add delta | o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42 | Add gamma | o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42 | Add beta | o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42 Add alpha If you were to run ``hg histedit c561b4e977df``, you would see the following file open in your editor:: pick c561b4e977df Add beta pick 030b686bedc4 Add gamma pick 7c2fd3b9020c Add delta # Edit history between c561b4e977df and 7c2fd3b9020c # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but fold into previous commit (combines N and N-1) # d, drop = remove commit from history # m, mess = edit message without changing commit content # In this file, lines beginning with ``#`` are ignored. You must specify a rule for each revision in your history. For example, if you had meant to add gamma before beta, and then wanted to add delta in the same revision as beta, you would reorganize the file to look like this:: pick 030b686bedc4 Add gamma pick c561b4e977df Add beta fold 7c2fd3b9020c Add delta # Edit history between c561b4e977df and 7c2fd3b9020c # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but fold into previous commit (combines N and N-1) # d, drop = remove commit from history # m, mess = edit message without changing commit content # At which point you close the editor and ``histedit`` starts working. When you specify a ``fold`` operation, ``histedit`` will open an editor when it folds those revisions together, offering you a chance to clean up the commit message:: Add beta *** Add delta Edit the commit message to your liking, then close the editor. For this example, let's assume that the commit message was changed to ``Add beta and delta.`` After histedit has run and had a chance to remove any old or temporary revisions it needed, the history looks like this:: @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42 | Add beta and delta. | o 1 081603921c3f 2009-04-27 18:04 -0500 durin42 | Add gamma | o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42 Add alpha Note that ``histedit`` does *not* remove any revisions (even its own temporary ones) until after it has completed all the editing operations, so it will probably perform several strip operations when it's done. For the above example, it had to run strip twice. Strip can be slow depending on a variety of factors, so you might need to be a little patient. You can choose to keep the original revisions by passing the ``--keep`` flag. The ``edit`` operation will drop you back to a command prompt, allowing you to edit files freely, or even use ``hg record`` to commit some changes as a separate commit. When you're done, any remaining uncommitted changes will be committed as well. When done, run ``hg histedit --continue`` to finish this step. You'll be prompted for a new commit message, but the default commit message will be the original message for the ``edit`` ed revision. The ``message`` operation will give you a chance to revise a commit message without changing the contents. It's a shortcut for doing ``edit`` immediately followed by `hg histedit --continue``. If ``histedit`` encounters a conflict when moving a revision (while handling ``pick`` or ``fold``), it'll stop in a similar manner to ``edit`` with the difference that it won't prompt you for a commit message when done. If you decide at this point that you don't like how much work it will be to rearrange history, or that you made a mistake, you can use ``hg histedit --abort`` to abandon the new changes you have made and return to the state before you attempted to edit your history. If we clone the histedit-ed example repository above and add four more changes, such that we have the following history:: @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan | Add theta | o 5 140988835471 2009-04-27 18:04 -0500 stefan | Add eta | o 4 122930637314 2009-04-27 18:04 -0500 stefan | Add zeta | o 3 836302820282 2009-04-27 18:04 -0500 stefan | Add epsilon | o 2 989b4d060121 2009-04-27 18:04 -0500 durin42 | Add beta and delta. | o 1 081603921c3f 2009-04-27 18:04 -0500 durin42 | Add gamma | o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42 Add alpha If you run ``hg histedit --outgoing`` on the clone then it is the same as running ``hg histedit 836302820282``. If you need plan to push to a repository that Mercurial does not detect to be related to the source repo, you can add a ``--force`` option. iÿÿÿÿN(tcmdutil(t discovery(terror(tcopies(tcontext(thg(tlock(tnode(trepair(tscmutil(tutil(tobsolete(tmerge(t_tinternals&# Edit history between %s and %s # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # f, fold = use commit, but fold into previous commit (combines N and N-1) # d, drop = remove commit from history # m, mess = edit message without changing commit content # cs%ˆjƒ‰‡‡‡fd†}|S(s>Build a commit function for the replacement of This function ensure we apply the same treatment to all changesets. - Add a 'histedit_source' entry in extra. Note that fold have its own separated logic because its handling is a bit different and not easily factored out of the fold method. cs†ˆjjddƒ}zYˆjjddˆƒ|jdiƒjƒ}ˆjƒ|d<||d<ˆj|SWdˆjj|ƒXdS(Ntphasess new-committextrathistedit_source(tuit backupconfigt setconfigtgettcopythextcommitt restoreconfig(tkwargst phasebackupR(tphasemintrepotsrc(s2/sys/lib/python2.7/site-packages/hgext/histedit.pyt commitfunc¿s (tphase(RRR((RRRs2/sys/lib/python2.7/site-packages/hgext/histedit.pyt commitfuncfor´s  cCs|jjƒd}|jƒjƒ|krYtj||||tjfdtƒd}nzV|j j dd|j ddƒƒt j ||jƒttt|jƒjƒƒ}Wd|j j dddƒX|j|tjƒ|jjƒtj||jƒ|jƒjƒƒ|S(s@Merge changeset from ctx (only) in the current working directoryitallRt forcemergettooltN(tdirstatetparentstp1RRtreverttnullidtTruetNoneRRRtmergemodtupdatetFalset setparentstwritetduplicatecopiestrev(RRtctxtoptstwcpartstats((s2/sys/lib/python2.7/site-packages/hgext/histedit.pyt applychangesÍs% " %cs£t|jd|ˆƒƒ}|s%d S|jƒd‰tƒ}x!|D]}|j|jƒƒqEWtj|ˆƒ‰‡‡fd†}g|D]}||ƒs|^q}ˆjƒ‰‡‡‡fd†} |j dƒrè|d} n |j ƒ} |j dƒ} |j dƒ} |j dƒ} |j ƒj ƒ|j ƒj ƒf}tj|d |d | d |d | d| d| d| ƒ}tj||gƒ|_|j|ƒS(sácollapse the set of revisions from first to last as new one. Expected commit options are: - message - date - username Commit message is edited in all cases. This function works in memory.s%d::%dics‹|ˆjƒkrwˆj|ƒ}|ˆjƒkrpˆj|ƒ}|jƒ|jƒkoo|jƒ|jƒkStSn|ˆjƒkSdS(N(tmanifesttfilectxtdatatflagsR/(tftatb(tbasetlast(s2/sys/lib/python2.7/site-packages/hgext/histedit.pytsamefileüsc sx|ˆkrkˆ|}|jƒ}tj|jƒ|jƒdd|kdd|kdˆj|ƒƒ}|Stƒ‚dS(Ntislinktltisexectxtcopied(R<Rt memfilectxtpathR;RtIOError(RR4RItfctxR<tmctx(RGtheadmfRA(s2/sys/lib/python2.7/site-packages/hgext/histedit.pyt filectxfn s     tmessagetusertdateRR'ttexttfilesRNN(tlisttsetR,R'R.RSRt pathcopiesR9Rt descriptionR(Rtp2RtmemctxRtcommitforceeditort_textt commitctx(RtfirstRAt commitoptstctxsRSR4RBR=RNRORPRQRR'tnew((R@RGRMRAs2/sys/lib/python2.7/site-packages/hgext/histedit.pytcollapseãs:    %    $  c Cs8||}|jƒd|kr;|jd|ƒ|gfStj||jƒƒt||||ƒ}|r”|ddkr”tjtdƒƒ‚nt ||ƒ}|d|j ƒd|j ƒd|j ƒd|j ƒƒ}|dkr|jtd ƒtj|ƒƒ|gfS||} | |jƒ|ffgfS( Nisnode %s unchanged is0Fix up the change and run hg histedit --continueRRRPRQRs%s: empty changeset (R'tdebugRR.RR8RtInterventionRequiredR R!RWRPRQRR,twarnR( RRR4thaR5toldctxR7RtnR`((s2/sys/lib/python2.7/site-packages/hgext/histedit.pytpick)s"     cCsL||}tj||jƒƒt||||ƒtjtdƒƒ‚dS(Ns|Make changes as needed, you may commit or record as needed now. When you are finished, run hg histedit --continue to resume.(RR.RR8RRcR (RRR4ReR5Rf((s2/sys/lib/python2.7/site-packages/hgext/histedit.pytedit?s  c Csï||}tj||jƒƒt||||ƒ}|rc|ddkrctjtdƒƒ‚n|jdd|d|jƒd|j ƒd|j ƒƒ}|dkrÓ|j td ƒtj |ƒƒ|gfSt||||||gƒS( Niis0Fix up the change and run hg histedit --continueRRsfold-temp-revision %sRPRQRs%s: empty changeset(RR.RR8RRcR RRPRQRR,RdRt finishfold(RRR4ReR5RfR7Rg((s2/sys/lib/python2.7/site-packages/hgext/histedit.pytfoldGs   cCs&|jƒdjƒ}tj||ƒ|jƒ}|jƒ|jƒkrY|jƒ} n |jƒ} | |d(st#shistedit: processing %s %s shistedit: %s is dropped shistedit: %s is replaced by %s s'histedit: %stkeyc3s|]}ˆ|VqdS(N((RŸts(R(s2/sys/lib/python2.7/site-packages/hgext/histedit.pys Rstreplacedtundo(<tgetattrR,tappliedR R„R RtanytosRItexistsRmtlentextendt readstateR&R'tbootstrapcontinuetprocessreplacementRbRtshortRtcleant cleanupnodetunlinkRt bailifchangedR‹R t revsingleR/tbetweentmakedesct editcommentRiRltopenR1tclosetsyststdintreadt splitlinest verifyrulest writestatetpopt actiontableR.t iteritemst movebookmarksR t_enabledtsortedt changelogR3Rottuplet createmarkerstsjoin(+RRtfreeargsR5R™toutgtcontR—RztrulesR‡tgoalt parentctxnodeR–ttopmostRut currentparenttwantnullt parentctxtrepltmappingttmpnodestleafst_ntmtemptyR…trootRsR_R“R=RDtactionRetactfunct replacement_RštntmtprectsuccsRRgtmarkers((Rs2/sys/lib/python2.7/site-packages/hgext/histedit.pyR‘ºsè   $       ( &       #   $(   $cCs~|jdƒ\}}||}g|jd|ƒD]}|jƒ^q2} |jƒtjkr­| stdƒ} tdƒ|} tj| |d| ƒ‚n| jdƒnd} |jƒd \} }}}| sç|sç|sç|r•|dkrd |}n|j ƒd }|dkr(t j }nt }t ||ƒ}|d|d|jƒd|jƒd|jƒd|ƒ} | dk r•| j| ƒq•ng}|jƒ| krÏ|j|jƒt| ƒfƒn|dkr]| r8| dkrú| d} n | jƒt||||| || ƒ\}}|j|ƒqt|j|jƒ|jƒffƒn| rt|| d}n||fS(Nis(%d::.)s*%s is not an ancestor of working directorysAupdate to %s or descendant and run "hg histedit --continue" againthintiR=Rksfold-temp-revision %ss RRiRRRRRPRQRteditoriÿÿÿÿ(R=sfold(RseditRR(R=sfold(RÀRURR*R R R„R,R}RWRRZR/R!RPRQRRoRÇRjR«(RRRÓRÍR5RÛt currentnodeR4R“t newchildrentmsgRâR`RR>RsRŽRORãRRuRÔ((s2/sys/lib/python2.7/site-packages/hgext/histedit.pyR­^sP +        "    %cCs±t|jd||ƒƒ}|r”| r”tj r_|jd||ƒr_tjtdƒƒ‚n|d}|jƒs”tjtdƒ|ƒ‚q”ng|D]}|j ƒ^q›S(soselect and validate the set of revision to edit When keep is false, the specified set can't have children.s%n::%ns(%ld::) - (%ld)s+cannot edit history that would orphan nodesis#cannot edit immutable changeset: %s( RTRUR RÄR‡R R„R R R(RtoldR`R–R_RÚR“((s2/sys/lib/python2.7/site-packages/hgext/histedit.pyRµ s    cCsNttjj|jdƒdƒ}tj|||||f|ƒ|jƒdS(Nshistedit-stateRœ(R¸R¨RIRmtpickletdumpR¹(Rt parentnodeRÍR–RÐRutfp((s2/sys/lib/python2.7/site-packages/hgext/histedit.pyR¿¯s!cCs+ttjj|jdƒƒ}tj|ƒS(sIReturns a tuple of (parentnode, rules, keep, topmost, replacements). shistedit-state(R¸R¨RIRmRètload(RRë((s2/sys/lib/python2.7/site-packages/hgext/histedit.pyR¬´scCsLd}|jƒr+|jƒjƒd}nd||jƒ|f}|d S(slbuild a initial action line for a ctx `c` line are in the form: pick R%is pick %s %d %siP(RWR½R3(R“tsummarytline((s2/sys/lib/python2.7/site-packages/hgext/histedit.pyR¶»s  c Cs°g}td„|Dƒƒ}tƒ}xB|D]:}d|krZtjtdƒ|ƒ‚n|jddƒ\}}|jƒjddƒd} yt|| ƒ} Wn-tjk rÑtjtdƒ| ƒ‚nX| |krötjtdƒƒ‚n| |krtjtdƒ| ƒ‚n|j | ƒ|t krStjtd ƒ|ƒ‚n|j || gƒq,Wt ||ƒ} | r¬tjtd ƒ| dd td ƒƒ‚n|S( sÏVerify that there exists exactly one edit rule per given changeset. Will abort if there are to many or too few rules, a malformed rule, or a rule on a changeset outside of the user-given range. css|]}t|ƒVqdS(N(tstr(RŸR“((s2/sys/lib/python2.7/site-packages/hgext/histedit.pys Ïst smalformed line "%s"iisunknown changeset %s listeds1may not use changesets other than the ones listeds#duplicated command for changeset %ssunknown action "%s"smissing rules for changeset %sRâs#do you want to use the drop action?( RUR R„R tsplitRžRïRt RepoErrortaddRÁRoRÅ( RÍRR_tparsedtexpectedtseenRsRÛtrestReRƒ((s2/sys/lib/python2.7/site-packages/hgext/histedit.pyR¾Ès4       cCsøtƒ}tƒ}i}xT|D]L}|j|dƒ|j|dƒ|j|dtƒƒj|dƒqW||}||@}t|ƒ}i} x–|r-x‰t|ƒD]{} || } xht| ƒD]C} | |krÞPqÈ| | krÈ| j| ƒ| j| | ƒqÈqÈW| | | <|j| ƒq«Wq˜Wx|D] } | | =q5W|jj}x3| jƒD]%\}} t | d|j ƒ| |‹s„       F    +          ™ B    ! ; "