hgext/histedit.py
author Sune Foldager <cryo@cyanite.org>
Fri, 13 Jul 2012 21:46:53 +0200
changeset 17191 5884812686f7
parent 17147 80e861511e2b
child 17241 c2f13180001f
permissions -rw-r--r--
peer: introduce peer methods to prepare for peer classes This introduces a peer method into all repository classes, which currently simply returns self. It also changes hg.repository so it now raises an exception if the supplied paths does not resolve to a localrepo or descendant. Finally, all call sites are changed to use the peer and local methods as appropriate, where peer is used whenever the code is dealing with a remote repository (even if it's on local disk).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
     1
# histedit.py - interactive history editing for mercurial
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
     2
#
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
     3
# Copyright 2009 Augie Fackler <raf@durin42.com>
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
     4
#
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
17131
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
     7
"""interactive history editing
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
     8
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
     9
With this extension installed, Mercurial gains one new command: histedit. Usage
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    10
is as follows, assuming the following history::
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    11
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    12
 @  3[tip]   7c2fd3b9020c   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    13
 |    Add delta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    14
 |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    15
 o  2   030b686bedc4   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    16
 |    Add gamma
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    17
 |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    18
 o  1   c561b4e977df   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    19
 |    Add beta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    20
 |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    21
 o  0   d8d2fcd0e319   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    22
      Add alpha
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    23
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    24
If you were to run ``hg histedit c561b4e977df``, you would see the following
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    25
file open in your editor::
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    26
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    27
 pick c561b4e977df Add beta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    28
 pick 030b686bedc4 Add gamma
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    29
 pick 7c2fd3b9020c Add delta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    30
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    31
 # Edit history between 633536316234 and 7c2fd3b9020c
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    32
 #
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    33
 # Commands:
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    34
 #  p, pick = use commit
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    35
 #  e, edit = use commit, but stop for amending
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    36
 #  f, fold = use commit, but fold into previous commit
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    37
 #  d, drop = remove commit from history
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    38
 #  m, mess = edit message without changing commit content
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    39
 #
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    40
 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    41
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    42
In this file, lines beginning with ``#`` are ignored. You must specify a rule
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    43
for each revision in your history. For example, if you had meant to add gamma
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    44
before beta, and then wanted to add delta in the same revision as beta, you
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    45
would reorganize the file to look like this::
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    46
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    47
 pick 030b686bedc4 Add gamma
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    48
 pick c561b4e977df Add beta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    49
 fold 7c2fd3b9020c Add delta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    50
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    51
 # Edit history between 633536316234 and 7c2fd3b9020c
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    52
 #
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    53
 # Commands:
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    54
 #  p, pick = use commit
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    55
 #  e, edit = use commit, but stop for amending
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    56
 #  f, fold = use commit, but fold into previous commit
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    57
 #  d, drop = remove commit from history
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    58
 #  m, mess = edit message without changing commit content
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    59
 #
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    60
 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    61
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    62
At which point you close the editor and ``histedit`` starts working. When you
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    63
specify a ``fold`` operation, ``histedit`` will open an editor when it folds
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    64
those revisions together, offering you a chance to clean up the commit message::
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    65
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    66
 Add beta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    67
 ***
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    68
 Add delta
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
    69
17131
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    70
Edit the commit message to your liking, then close the editor. For
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    71
this example, let's assume that the commit message was changed to
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    72
``Add beta and delta.`` After histedit has run and had a chance to
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    73
remove any old or temporary revisions it needed, the history looks
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    74
like this::
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    75
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    76
 @  2[tip]   989b4d060121   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    77
 |    Add beta and delta.
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    78
 |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    79
 o  1   081603921c3f   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    80
 |    Add gamma
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    81
 |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    82
 o  0   d8d2fcd0e319   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    83
      Add alpha
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    84
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    85
Note that ``histedit`` does *not* remove any revisions (even its own temporary
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    86
ones) until after it has completed all the editing operations, so it will
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    87
probably perform several strip operations when it's done. For the above example,
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    88
it had to run strip twice. Strip can be slow depending on a variety of factors,
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    89
so you might need to be a little patient. You can choose to keep the original
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    90
revisions by passing the ``--keep`` flag.
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    91
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    92
The ``edit`` operation will drop you back to a command prompt,
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    93
allowing you to edit files freely, or even use ``hg record`` to commit
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    94
some changes as a separate commit. When you're done, any remaining
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    95
uncommitted changes will be committed as well. When done, run ``hg
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    96
histedit --continue`` to finish this step. You'll be prompted for a
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    97
new commit message, but the default commit message will be the
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    98
original message for the ``edit`` ed revision.
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
    99
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   100
The ``message`` operation will give you a chance to revise a commit
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   101
message without changing the contents. It's a shortcut for doing
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   102
``edit`` immediately followed by `hg histedit --continue``.
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   103
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   104
If ``histedit`` encounters a conflict when moving a revision (while
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   105
handling ``pick`` or ``fold``), it'll stop in a similar manner to
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   106
``edit`` with the difference that it won't prompt you for a commit
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   107
message when done. If you decide at this point that you don't like how
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   108
much work it will be to rearrange history, or that you made a mistake,
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   109
you can use ``hg histedit --abort`` to abandon the new changes you
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   110
have made and return to the state before you attempted to edit your
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   111
history.
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   112
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   113
If we clone the example repository above and add three more changes, such that
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   114
we have the following history::
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   115
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   116
   @  6[tip]   038383181893   2009-04-27 18:04 -0500   stefan
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   117
   |    Add theta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   118
   |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   119
   o  5   140988835471   2009-04-27 18:04 -0500   stefan
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   120
   |    Add eta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   121
   |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   122
   o  4   122930637314   2009-04-27 18:04 -0500   stefan
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   123
   |    Add zeta
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   124
   |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   125
   o  3   836302820282   2009-04-27 18:04 -0500   stefan
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   126
   |    Add epsilon
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   127
   |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   128
   o  2   989b4d060121   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   129
   |    Add beta and delta.
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   130
   |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   131
   o  1   081603921c3f   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   132
   |    Add gamma
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   133
   |
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   134
   o  0   d8d2fcd0e319   2009-04-27 18:04 -0500   durin42
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   135
        Add alpha
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   136
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   137
If you run ``hg histedit --outgoing`` on the clone then it is the same
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   138
as running ``hg histedit 836302820282``. If you need plan to push to a
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   139
repository that Mercurial does not detect to be related to the source
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   140
repo, you can add a ``--force`` option.
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   141
"""
17131
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   142
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   143
try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   144
    import cPickle as pickle
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   145
except ImportError:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   146
    import pickle
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   147
import tempfile
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   148
import os
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   149
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   150
from mercurial import bookmarks
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   151
from mercurial import cmdutil
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   152
from mercurial import discovery
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   153
from mercurial import error
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   154
from mercurial import hg
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   155
from mercurial import node
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   156
from mercurial import patch
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   157
from mercurial import repair
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   158
from mercurial import scmutil
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   159
from mercurial import util
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   160
from mercurial.i18n import _
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   161
17147
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   162
cmdtable = {}
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   163
command = cmdutil.command(cmdtable)
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   164
17069
2b1c78674230 histedit: mark as a first party extension
Augie Fackler <raf@durin42.com>
parents: 17068
diff changeset
   165
testedwith = 'internal'
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   166
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   167
editcomment = """
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   168
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   169
# Edit history between %s and %s
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   170
#
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   171
# Commands:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   172
#  p, pick = use commit
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   173
#  e, edit = use commit, but stop for amending
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   174
#  f, fold = use commit, but fold into previous commit (combines N and N-1)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   175
#  d, drop = remove commit from history
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   176
#  m, mess = edit message without changing commit content
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   177
#
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   178
"""
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   179
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   180
def between(repo, old, new, keep):
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   181
    revs = [old]
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   182
    current = old
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   183
    while current != new:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   184
        ctx = repo[current]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   185
        if not keep and len(ctx.children()) > 1:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   186
            raise util.Abort(_('cannot edit history that would orphan nodes'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   187
        if len(ctx.parents()) != 1 and ctx.parents()[1] != node.nullid:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   188
            raise util.Abort(_("can't edit history with merges"))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   189
        if not ctx.children():
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   190
            current = new
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   191
        else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   192
            current = ctx.children()[0].node()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   193
            revs.append(current)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   194
    if len(repo[current].children()) and not keep:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   195
        raise util.Abort(_('cannot edit history that would orphan nodes'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   196
    return revs
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   197
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   198
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   199
def pick(ui, repo, ctx, ha, opts):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   200
    oldctx = repo[ha]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   201
    if oldctx.parents()[0] == ctx:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   202
        ui.debug('node %s unchanged\n' % ha)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   203
        return oldctx, [], [], []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   204
    hg.update(repo, ctx.node())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   205
    fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   206
    fp = os.fdopen(fd, 'w')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   207
    diffopts = patch.diffopts(ui, opts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   208
    diffopts.git = True
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   209
    diffopts.ignorews = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   210
    diffopts.ignorewsamount = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   211
    diffopts.ignoreblanklines = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   212
    gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   213
    for chunk in gen:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   214
        fp.write(chunk)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   215
    fp.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   216
    try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   217
        files = set()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   218
        try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   219
            patch.patch(ui, repo, patchfile, files=files, eolmode=None)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   220
            if not files:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   221
                ui.warn(_('%s: empty changeset')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   222
                             % node.hex(ha))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   223
                return ctx, [], [], []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   224
        finally:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   225
            os.unlink(patchfile)
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   226
    except Exception:
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   227
        raise util.Abort(_('Fix up the change and run '
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   228
                           'hg histedit --continue'))
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   229
    n = repo.commit(text=oldctx.description(), user=oldctx.user(),
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   230
                    date=oldctx.date(), extra=oldctx.extra())
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   231
    return repo[n], [n], [oldctx.node()], []
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   232
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   233
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   234
def edit(ui, repo, ctx, ha, opts):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   235
    oldctx = repo[ha]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   236
    hg.update(repo, ctx.node())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   237
    fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   238
    fp = os.fdopen(fd, 'w')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   239
    diffopts = patch.diffopts(ui, opts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   240
    diffopts.git = True
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   241
    diffopts.ignorews = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   242
    diffopts.ignorewsamount = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   243
    diffopts.ignoreblanklines = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   244
    gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   245
    for chunk in gen:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   246
        fp.write(chunk)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   247
    fp.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   248
    try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   249
        files = set()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   250
        try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   251
            patch.patch(ui, repo, patchfile, files=files, eolmode=None)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   252
        finally:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   253
            os.unlink(patchfile)
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   254
    except Exception:
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   255
        pass
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   256
    raise util.Abort(_('Make changes as needed, you may commit or record as '
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   257
                       'needed now.\nWhen you are finished, run hg'
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   258
                       ' histedit --continue to resume.'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   259
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   260
def fold(ui, repo, ctx, ha, opts):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   261
    oldctx = repo[ha]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   262
    hg.update(repo, ctx.node())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   263
    fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   264
    fp = os.fdopen(fd, 'w')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   265
    diffopts = patch.diffopts(ui, opts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   266
    diffopts.git = True
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   267
    diffopts.ignorews = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   268
    diffopts.ignorewsamount = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   269
    diffopts.ignoreblanklines = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   270
    gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   271
    for chunk in gen:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   272
        fp.write(chunk)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   273
    fp.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   274
    try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   275
        files = set()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   276
        try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   277
            patch.patch(ui, repo, patchfile, files=files, eolmode=None)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   278
            if not files:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   279
                ui.warn(_('%s: empty changeset')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   280
                             % node.hex(ha))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   281
                return ctx, [], [], []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   282
        finally:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   283
            os.unlink(patchfile)
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   284
    except Exception:
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   285
        raise util.Abort(_('Fix up the change and run '
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   286
                           'hg histedit --continue'))
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   287
    n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   288
                    date=oldctx.date(), extra=oldctx.extra())
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   289
    return finishfold(ui, repo, ctx, oldctx, n, opts, [])
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   290
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   291
def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   292
    parent = ctx.parents()[0].node()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   293
    hg.update(repo, parent)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   294
    fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   295
    fp = os.fdopen(fd, 'w')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   296
    diffopts = patch.diffopts(ui, opts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   297
    diffopts.git = True
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   298
    diffopts.ignorews = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   299
    diffopts.ignorewsamount = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   300
    diffopts.ignoreblanklines = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   301
    gen = patch.diff(repo, parent, newnode, opts=diffopts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   302
    for chunk in gen:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   303
        fp.write(chunk)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   304
    fp.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   305
    files = set()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   306
    try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   307
        patch.patch(ui, repo, patchfile, files=files, eolmode=None)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   308
    finally:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   309
        os.unlink(patchfile)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   310
    newmessage = '\n***\n'.join(
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   311
        [ctx.description()] +
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   312
        [repo[r].description() for r in internalchanges] +
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   313
        [oldctx.description()])
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   314
    # If the changesets are from the same author, keep it.
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   315
    if ctx.user() == oldctx.user():
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   316
        username = ctx.user()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   317
    else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   318
        username = ui.username()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   319
    newmessage = ui.edit(newmessage, username)
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   320
    n = repo.commit(text=newmessage, user=username,
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   321
                    date=max(ctx.date(), oldctx.date()), extra=oldctx.extra())
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   322
    return repo[n], [n], [oldctx.node(), ctx.node()], [newnode]
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   323
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   324
def drop(ui, repo, ctx, ha, opts):
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   325
    return ctx, [], [repo[ha].node()], []
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   326
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   327
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   328
def message(ui, repo, ctx, ha, opts):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   329
    oldctx = repo[ha]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   330
    hg.update(repo, ctx.node())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   331
    fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   332
    fp = os.fdopen(fd, 'w')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   333
    diffopts = patch.diffopts(ui, opts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   334
    diffopts.git = True
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   335
    diffopts.ignorews = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   336
    diffopts.ignorewsamount = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   337
    diffopts.ignoreblanklines = False
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   338
    gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   339
    for chunk in gen:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   340
        fp.write(chunk)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   341
    fp.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   342
    try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   343
        files = set()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   344
        try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   345
            patch.patch(ui, repo, patchfile, files=files, eolmode=None)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   346
        finally:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   347
            os.unlink(patchfile)
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   348
    except Exception:
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   349
        raise util.Abort(_('Fix up the change and run '
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   350
                           'hg histedit --continue'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   351
    message = oldctx.description()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   352
    message = ui.edit(message, ui.username())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   353
    new = repo.commit(text=message, user=oldctx.user(), date=oldctx.date(),
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   354
                      extra=oldctx.extra())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   355
    newctx = repo[new]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   356
    if oldctx.node() != newctx.node():
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   357
        return newctx, [new], [oldctx.node()], []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   358
    # We didn't make an edit, so just indicate no replaced nodes
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   359
    return newctx, [new], [], []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   360
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   361
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   362
def makedesc(c):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   363
    summary = ''
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   364
    if c.description():
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   365
        summary = c.description().splitlines()[0]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   366
    line = 'pick %s %d %s' % (c.hex()[:12], c.rev(), summary)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   367
    return line[:80]  # trim to 80 chars so it's not stupidly wide in my editor
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   368
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   369
actiontable = {'p': pick,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   370
               'pick': pick,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   371
               'e': edit,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   372
               'edit': edit,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   373
               'f': fold,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   374
               'fold': fold,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   375
               'd': drop,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   376
               'drop': drop,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   377
               'm': message,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   378
               'mess': message,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   379
               }
17147
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   380
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   381
@command('histedit',
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   382
    [('', 'commands', '',
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   383
      _('Read history edits from the specified file.')),
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   384
     ('c', 'continue', False, _('continue an edit already in progress')),
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   385
     ('k', 'keep', False,
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   386
      _("don't strip old nodes after edit is complete")),
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   387
     ('', 'abort', False, _('abort an edit in progress')),
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   388
     ('o', 'outgoing', False, _('changesets not found in destination')),
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   389
     ('f', 'force', False,
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   390
      _('force outgoing even for unrelated repositories')),
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   391
     ('r', 'rev', [], _('first revision to be edited'))],
80e861511e2b histedit: use cmdutil.command decorator
Adrian Buehlmann <adrian@cadifra.com>
parents: 17131
diff changeset
   392
     _("[PARENT]"))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   393
def histedit(ui, repo, *parent, **opts):
17131
4fb2d3d16743 histedit: add extension docstring from external README
Augie Fackler <raf@durin42.com>
parents: 17130
diff changeset
   394
    """interactively edit changeset history
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   395
    """
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   396
    # TODO only abort if we try and histedit mq patches, not just
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   397
    # blanket if mq patches are applied somewhere
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   398
    mq = getattr(repo, 'mq', None)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   399
    if mq and mq.applied:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   400
        raise util.Abort(_('source has mq patches applied'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   401
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   402
    parent = list(parent) + opts.get('rev', [])
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   403
    if opts.get('outgoing'):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   404
        if len(parent) > 1:
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   405
            raise util.Abort(
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   406
                _('only one repo argument allowed with --outgoing'))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   407
        elif parent:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   408
            parent = parent[0]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   409
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   410
        dest = ui.expandpath(parent or 'default-push', parent or 'default')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   411
        dest, revs = hg.parseurl(dest, None)[:2]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   412
        ui.status(_('comparing with %s\n') % util.hidepassword(dest))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   413
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   414
        revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
17191
5884812686f7 peer: introduce peer methods to prepare for peer classes
Sune Foldager <cryo@cyanite.org>
parents: 17147
diff changeset
   415
        other = hg.peer(repo, opts, dest)
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   416
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   417
        if revs:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   418
            revs = [repo.lookup(rev) for rev in revs]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   419
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   420
        parent = discovery.findcommonoutgoing(
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   421
            repo, other, [], force=opts.get('force')).missing[0:1]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   422
    else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   423
        if opts.get('force'):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   424
            raise util.Abort(_('--force only allowed with --outgoing'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   425
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   426
    if opts.get('continue', False):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   427
        if len(parent) != 0:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   428
            raise util.Abort(_('no arguments allowed with --continue'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   429
        (parentctxnode, created, replaced,
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   430
         tmpnodes, existing, rules, keep, tip, replacemap) = readstate(repo)
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   431
        currentparent, wantnull = repo.dirstate.parents()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   432
        parentctx = repo[parentctxnode]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   433
        # discover any nodes the user has added in the interim
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   434
        newchildren = [c for c in parentctx.children()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   435
                       if c.node() not in existing]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   436
        action, currentnode = rules.pop(0)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   437
        while newchildren:
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   438
            if action in ('f', 'fold'):
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   439
                tmpnodes.extend([n.node() for n in newchildren])
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   440
            else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   441
                created.extend([n.node() for n in newchildren])
17068
a86e110430f6 histedit: remove use of reduce() builtin spotted by check-code
Augie Fackler <raf@durin42.com>
parents: 17066
diff changeset
   442
            filtered = []
a86e110430f6 histedit: remove use of reduce() builtin spotted by check-code
Augie Fackler <raf@durin42.com>
parents: 17066
diff changeset
   443
            for r in newchildren:
a86e110430f6 histedit: remove use of reduce() builtin spotted by check-code
Augie Fackler <raf@durin42.com>
parents: 17066
diff changeset
   444
                filtered += [c for c in r.children() if c.node not in existing]
a86e110430f6 histedit: remove use of reduce() builtin spotted by check-code
Augie Fackler <raf@durin42.com>
parents: 17066
diff changeset
   445
            newchildren = filtered
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   446
        m, a, r, d = repo.status()[:4]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   447
        oldctx = repo[currentnode]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   448
        message = oldctx.description()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   449
        if action in ('e', 'edit', 'm', 'mess'):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   450
            message = ui.edit(message, ui.username())
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   451
        elif action in ('f', 'fold'):
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   452
            message = 'fold-temp-revision %s' % currentnode
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   453
        new = None
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   454
        if m or a or r or d:
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   455
            new = repo.commit(text=message, user=oldctx.user(),
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   456
                              date=oldctx.date(), extra=oldctx.extra())
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   457
17130
0a48f3d54543 histedit: don't crash if the result of fixing up a fold is empty
Augie Fackler <raf@durin42.com>
parents: 17129
diff changeset
   458
        # If we're resuming a fold and we have new changes, mark the
0a48f3d54543 histedit: don't crash if the result of fixing up a fold is empty
Augie Fackler <raf@durin42.com>
parents: 17129
diff changeset
   459
        # replacements and finish the fold. If not, it's more like a
0a48f3d54543 histedit: don't crash if the result of fixing up a fold is empty
Augie Fackler <raf@durin42.com>
parents: 17129
diff changeset
   460
        # drop of the changesets that disappeared, and we can skip
0a48f3d54543 histedit: don't crash if the result of fixing up a fold is empty
Augie Fackler <raf@durin42.com>
parents: 17129
diff changeset
   461
        # this step.
0a48f3d54543 histedit: don't crash if the result of fixing up a fold is empty
Augie Fackler <raf@durin42.com>
parents: 17129
diff changeset
   462
        if action in ('f', 'fold') and (new or newchildren):
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   463
            if new:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   464
                tmpnodes.append(new)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   465
            else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   466
                new = newchildren[-1]
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   467
            (parentctx, created_, replaced_, tmpnodes_) = finishfold(
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   468
                ui, repo, parentctx, oldctx, new, opts, newchildren)
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   469
            replaced.extend(replaced_)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   470
            created.extend(created_)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   471
            tmpnodes.extend(tmpnodes_)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   472
        elif action not in ('d', 'drop'):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   473
            if new != oldctx.node():
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   474
                replaced.append(oldctx.node())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   475
            if new:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   476
                if new != oldctx.node():
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   477
                    created.append(new)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   478
                parentctx = repo[new]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   479
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   480
    elif opts.get('abort', False):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   481
        if len(parent) != 0:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   482
            raise util.Abort(_('no arguments allowed with --abort'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   483
        (parentctxnode, created, replaced, tmpnodes,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   484
         existing, rules, keep, tip, replacemap) = readstate(repo)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   485
        ui.debug('restore wc to old tip %s\n' % node.hex(tip))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   486
        hg.clean(repo, tip)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   487
        ui.debug('should strip created nodes %s\n' %
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   488
                 ', '.join([node.hex(n)[:12] for n in created]))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   489
        ui.debug('should strip temp nodes %s\n' %
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   490
                 ', '.join([node.hex(n)[:12] for n in tmpnodes]))
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   491
        for nodes in (created, tmpnodes):
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   492
            for n in reversed(nodes):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   493
                try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   494
                    repair.strip(ui, repo, n)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   495
                except error.LookupError:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   496
                    pass
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   497
        os.unlink(os.path.join(repo.path, 'histedit-state'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   498
        return
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   499
    else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   500
        cmdutil.bailifchanged(repo)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   501
        if os.path.exists(os.path.join(repo.path, 'histedit-state')):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   502
            raise util.Abort(_('history edit already in progress, try '
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   503
                               '--continue or --abort'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   504
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   505
        tip, empty = repo.dirstate.parents()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   506
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   507
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   508
        if len(parent) != 1:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   509
            raise util.Abort(_('histedit requires exactly one parent revision'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   510
        parent = scmutil.revsingle(repo, parent[0]).node()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   511
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   512
        keep = opts.get('keep', False)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   513
        revs = between(repo, parent, tip, keep)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   514
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   515
        ctxs = [repo[r] for r in revs]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   516
        existing = [r.node() for r in ctxs]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   517
        rules = opts.get('commands', '')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   518
        if not rules:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   519
            rules = '\n'.join([makedesc(c) for c in ctxs])
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   520
            rules += editcomment % (node.hex(parent)[:12], node.hex(tip)[:12])
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   521
            rules = ui.edit(rules, ui.username())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   522
            # Save edit rules in .hg/histedit-last-edit.txt in case
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   523
            # the user needs to ask for help after something
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   524
            # surprising happens.
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   525
            f = open(repo.join('histedit-last-edit.txt'), 'w')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   526
            f.write(rules)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   527
            f.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   528
        else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   529
            f = open(rules)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   530
            rules = f.read()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   531
            f.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   532
        rules = [l for l in (r.strip() for r in rules.splitlines())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   533
                 if l and not l[0] == '#']
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   534
        rules = verifyrules(rules, repo, ctxs)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   535
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   536
        parentctx = repo[parent].parents()[0]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   537
        keep = opts.get('keep', False)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   538
        replaced = []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   539
        replacemap = {}
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   540
        tmpnodes = []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   541
        created = []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   542
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   543
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   544
    while rules:
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   545
        writestate(repo, parentctx.node(), created, replaced,
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   546
                   tmpnodes, existing, rules, keep, tip, replacemap)
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   547
        action, ha = rules.pop(0)
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   548
        (parentctx, created_, replaced_, tmpnodes_) = actiontable[action](
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   549
            ui, repo, parentctx, ha, opts)
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   550
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   551
        if replaced_:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   552
            clen, rlen = len(created_), len(replaced_)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   553
            if clen == rlen == 1:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   554
                ui.debug('histedit: exact replacement of %s with %s\n' % (
17129
ead4eb5b03c9 histedit: replace hexshort lambda with node.short
Augie Fackler <raf@durin42.com>
parents: 17084
diff changeset
   555
                    node.short(replaced_[0]), node.short(created_[0])))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   556
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   557
                replacemap[replaced_[0]] = created_[0]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   558
            elif clen > rlen:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   559
                assert rlen == 1, ('unexpected replacement of '
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   560
                                   '%d changes with %d changes' % (rlen, clen))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   561
                # made more changesets than we're replacing
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   562
                # TODO synthesize patch names for created patches
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   563
                replacemap[replaced_[0]] = created_[-1]
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   564
                ui.debug('histedit: created many, assuming %s replaced by %s' %
17129
ead4eb5b03c9 histedit: replace hexshort lambda with node.short
Augie Fackler <raf@durin42.com>
parents: 17084
diff changeset
   565
                         (node.short(replaced_[0]), node.short(created_[-1])))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   566
            elif rlen > clen:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   567
                if not created_:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   568
                    # This must be a drop. Try and put our metadata on
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   569
                    # the parent change.
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   570
                    assert rlen == 1
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   571
                    r = replaced_[0]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   572
                    ui.debug('histedit: %s seems replaced with nothing, '
17129
ead4eb5b03c9 histedit: replace hexshort lambda with node.short
Augie Fackler <raf@durin42.com>
parents: 17084
diff changeset
   573
                            'finding a parent\n' % (node.short(r)))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   574
                    pctx = repo[r].parents()[0]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   575
                    if pctx.node() in replacemap:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   576
                        ui.debug('histedit: parent is already replaced\n')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   577
                        replacemap[r] = replacemap[pctx.node()]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   578
                    else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   579
                        replacemap[r] = pctx.node()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   580
                    ui.debug('histedit: %s best replaced by %s\n' % (
17129
ead4eb5b03c9 histedit: replace hexshort lambda with node.short
Augie Fackler <raf@durin42.com>
parents: 17084
diff changeset
   581
                        node.short(r), node.short(replacemap[r])))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   582
                else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   583
                    assert len(created_) == 1
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   584
                    for r in replaced_:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   585
                        ui.debug('histedit: %s replaced by %s\n' % (
17129
ead4eb5b03c9 histedit: replace hexshort lambda with node.short
Augie Fackler <raf@durin42.com>
parents: 17084
diff changeset
   586
                            node.short(r), node.short(created_[0])))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   587
                        replacemap[r] = created_[0]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   588
            else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   589
                assert False, (
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   590
                    'Unhandled case in replacement mapping! '
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   591
                    'replacing %d changes with %d changes' % (rlen, clen))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   592
        created.extend(created_)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   593
        replaced.extend(replaced_)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   594
        tmpnodes.extend(tmpnodes_)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   595
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   596
    hg.update(repo, parentctx.node())
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   597
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   598
    if not keep:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   599
        if replacemap:
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   600
            ui.note(_('histedit: Should update metadata for the following '
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   601
                      'changes:\n'))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   602
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   603
            def copybms(old, new):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   604
                if old in tmpnodes or old in created:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   605
                    # can't have any metadata we'd want to update
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   606
                    return
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   607
                while new in replacemap:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   608
                    new = replacemap[new]
17129
ead4eb5b03c9 histedit: replace hexshort lambda with node.short
Augie Fackler <raf@durin42.com>
parents: 17084
diff changeset
   609
                ui.note(_('histedit:  %s to %s\n') % (node.short(old),
ead4eb5b03c9 histedit: replace hexshort lambda with node.short
Augie Fackler <raf@durin42.com>
parents: 17084
diff changeset
   610
                                                      node.short(new)))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   611
                octx = repo[old]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   612
                marks = octx.bookmarks()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   613
                if marks:
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   614
                    ui.note(_('histedit:     moving bookmarks %s\n') %
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   615
                              ', '.join(marks))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   616
                    for mark in marks:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   617
                        repo._bookmarks[mark] = new
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   618
                    bookmarks.write(repo)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   619
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   620
            # We assume that bookmarks on the tip should remain
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   621
            # tipmost, but bookmarks on non-tip changesets should go
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   622
            # to their most reasonable successor. As a result, find
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   623
            # the old tip and new tip and copy those bookmarks first,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   624
            # then do the rest of the bookmark copies.
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   625
            oldtip = sorted(replacemap.keys(), key=repo.changelog.rev)[-1]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   626
            newtip = sorted(replacemap.values(), key=repo.changelog.rev)[-1]
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   627
            copybms(oldtip, newtip)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   628
17084
69dae7982c85 histedit: use stable iteration order for processing bookmarks
Mads Kiilerich <mads@kiilerich.com>
parents: 17069
diff changeset
   629
            for old, new in sorted(replacemap.iteritems()):
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   630
                copybms(old, new)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   631
                # TODO update mq state
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   632
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   633
        ui.debug('should strip replaced nodes %s\n' %
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   634
                 ', '.join([node.hex(n)[:12] for n in replaced]))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   635
        for n in sorted(replaced, key=lambda x: repo[x].rev()):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   636
            try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   637
                repair.strip(ui, repo, n)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   638
            except error.LookupError:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   639
                pass
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   640
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   641
    ui.debug('should strip temp nodes %s\n' %
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   642
             ', '.join([node.hex(n)[:12] for n in tmpnodes]))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   643
    for n in reversed(tmpnodes):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   644
        try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   645
            repair.strip(ui, repo, n)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   646
        except error.LookupError:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   647
            pass
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   648
    os.unlink(os.path.join(repo.path, 'histedit-state'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   649
    if os.path.exists(repo.sjoin('undo')):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   650
        os.unlink(repo.sjoin('undo'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   651
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   652
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   653
def writestate(repo, parentctxnode, created, replaced,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   654
               tmpnodes, existing, rules, keep, oldtip, replacemap):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   655
    fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   656
    pickle.dump((parentctxnode, created, replaced,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   657
                 tmpnodes, existing, rules, keep, oldtip, replacemap),
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   658
                fp)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   659
    fp.close()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   660
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   661
def readstate(repo):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   662
    """Returns a tuple of (parentnode, created, replaced, tmp, existing, rules,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   663
                           keep, oldtip, replacemap ).
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   664
    """
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   665
    fp = open(os.path.join(repo.path, 'histedit-state'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   666
    return pickle.load(fp)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   667
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   668
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   669
def verifyrules(rules, repo, ctxs):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   670
    """Verify that there exists exactly one edit rule per given changeset.
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   671
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   672
    Will abort if there are to many or too few rules, a malformed rule,
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   673
    or a rule on a changeset outside of the user-given range.
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   674
    """
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   675
    parsed = []
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   676
    if len(rules) != len(ctxs):
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   677
        raise util.Abort(_('must specify a rule for each changeset once'))
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   678
    for r in rules:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   679
        if ' ' not in r:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   680
            raise util.Abort(_('malformed line "%s"') % r)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   681
        action, rest = r.split(' ', 1)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   682
        if ' ' in rest.strip():
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   683
            ha, rest = rest.split(' ', 1)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   684
        else:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   685
            ha = r.strip()
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   686
        try:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   687
            if repo[ha] not in ctxs:
17066
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   688
                raise util.Abort(
baf8887d40e2 histedit: fix most check-code violations
Augie Fackler <raf@durin42.com>
parents: 17064
diff changeset
   689
                    _('may not use changesets other than the ones listed'))
17064
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   690
        except error.RepoError:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   691
            raise util.Abort(_('unknown changeset %s listed') % ha)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   692
        if action not in actiontable:
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   693
            raise util.Abort(_('unknown action "%s"') % action)
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   694
        parsed.append([action, ha])
168cc52ad7c2 histedit: new extension for interactive history editing
Augie Fackler <raf@durin42.com>
parents:
diff changeset
   695
    return parsed