hgext3rd/evolve/rewind.py
author Anton Shestakov <av6@dwimlabs.net>
Thu, 25 Jul 2019 18:37:16 +0800
changeset 4821 d8e36e60aea0
parent 4814 48b30ff742cb
child 4894 f9743b13de6d
child 4899 c982e7fb5e7a
permissions -rw-r--r--
rewind: add --keep flag that "doesn't modify working directory" The actual logic is more complicated than the flag description, but it's sufficiently similar to other --keep flags in action. Unlike strip (or prune), rewind always needs to modify the working directory to commit new revisions that "revive" old ones [1], see _revive_revision() (and rewriteutil.rewrite()). Because of that we don't prevent rewind from modifying wdir, but instead use hg.updaterepo() to update to the old changeset after the "revival" process is complete. Then we rebuild the dirstate based on the commit that rewind would update to without --keep. Since dirstate.rebuild() doesn't restore status of some files (added, removed, also copies and renames), we rely on cmdutil.revert(). It's a fairly crude solution and needs to be removed when implementing the missing copy tracing between oldctx and newctx (which are related only by obsolescence). [1] IOW this means that --keep doesn't allow rewinding if wdir is dirty (unlike e.g. strip).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     1
from __future__ import absolute_import
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     2
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
     3
import collections
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     4
import hashlib
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     5
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     6
from mercurial import (
3873
b81fd1487e04 rewing: prevent rewind in case of uncommitted changes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3872
diff changeset
     7
    cmdutil,
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     8
    error,
3863
c31be22d1d90 rewind: update the working copy if it gets obsoleted
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3862
diff changeset
     9
    hg,
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    10
    obsolete,
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    11
    obsutil,
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    12
    scmutil,
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    13
)
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    14
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    15
from mercurial.i18n import _
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    16
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    17
from . import (
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    18
    exthelper,
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    19
    rewriteutil,
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    20
    compat,
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    21
)
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    22
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    23
eh = exthelper.exthelper()
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    24
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    25
# flag in obsolescence markers to link to identical version
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    26
identicalflag = 4
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    27
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    28
@eh.command(
4715
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    29
    b'rewind|undo',
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    30
    [(b'', b'to', [], _(b"rewind to these revisions"), _(b'REV')),
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    31
     (b'', b'as-divergence', None, _(b"preserve current latest successors")),
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    32
     (b'', b'exact', None, _(b"only rewind explicitly selected revisions")),
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    33
     (b'', b'from', [],
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    34
      _(b"rewind these revisions to their predecessors"), _(b'REV')),
4821
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
    35
     (b'k', b'keep', None,
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
    36
      _(b"do not modify working directory during rewind")),
4715
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    37
     ],
4821
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
    38
    _(b'[--as-divergence] [--exact] [--keep] [--to REV]... [--from REV]...'),
4191
5c734be63c3e evolve: adapt for changed @command decorator
Martin von Zweigbergk <martinvonz@google.com>
parents: 4158
diff changeset
    39
    helpbasic=True)
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    40
def rewind(ui, repo, **opts):
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    41
    """rewind a stack of changesets to a previous state
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    42
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    43
    This command can be used to restore stacks of changesets to an obsolete
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    44
    state, creating identical copies.
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    45
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    46
    There are two main ways to select the rewind target. Rewinding "from"
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    47
    changesets will restore the direct predecessors of these changesets (and
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
    48
    obsolete the changeset you rewind from). Rewinding "to" will restore the
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
    49
    changeset you have selected (and obsolete their latest successors).
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
    50
4794
7b5d08e84c4d rewind: working directory is the preferred term
Anton Shestakov <av6@dwimlabs.net>
parents: 4793
diff changeset
    51
    By default, we rewind from the working directory parents, restoring its
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    52
    predecessor.
3872
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
    53
3868
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    54
    When we rewind to an obsolete version, we also rewind to all its obsolete
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    55
    ancestors. To only rewind to the explicitly selected changesets use the
3868
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    56
    `--exact` flag. Using the `--exact` flag can restore some changesets as
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    57
    orphan.
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    58
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    59
    The latest successors of the obsolete changesets will be superseded by
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    60
    these new copies. This behavior can be disabled using `--as-divergence`,
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    61
    the current latest successors won't be affected and content-divergence will
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    62
    appear between them and the restored version of the obsolete changesets.
3865
b945f2dae587 rewind: add a test for rewinding a fold
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3863
diff changeset
    63
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    64
    Current rough edges:
3865
b945f2dae587 rewind: add a test for rewinding a fold
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3863
diff changeset
    65
b945f2dae587 rewind: add a test for rewinding a fold
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3863
diff changeset
    66
      * fold: rewinding to only some of the initially folded changesets will be
b945f2dae587 rewind: add a test for rewinding a fold
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3863
diff changeset
    67
              problematic. The fold result is marked obsolete and the part not
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    68
              rewinded to are "lost".  Please use --as-divergence when you
3865
b945f2dae587 rewind: add a test for rewinding a fold
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3863
diff changeset
    69
              need to perform such operation.
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
    70
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    71
      * :hg:`rewind` might affect changesets outside the current stack. Without
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    72
              --exact, we also restore ancestors of the rewind target,
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    73
              obsoleting their latest successors (unless --as-divergent is
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    74
              provided). In some case, these latest successors will be on
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    75
              branches unrelated to the changeset you rewind from.
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    76
              (We plan to automatically detect this case in the future)
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
    77
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    78
    """
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    79
    unfi = repo.unfiltered()
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    80
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    81
    successorsmap = collections.defaultdict(set)
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    82
    rewindmap = {}
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    83
    sscache = {}
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    84
    with repo.wlock(), repo.lock():
3873
b81fd1487e04 rewing: prevent rewind in case of uncommitted changes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3872
diff changeset
    85
        # stay on the safe side: prevent local case in case we need to upgrade
b81fd1487e04 rewing: prevent rewind in case of uncommitted changes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3872
diff changeset
    86
        cmdutil.bailifchanged(repo)
3868
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    87
3869
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
    88
        rewinded = _select_rewinded(repo, opts)
3868
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    89
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    90
        if not opts['as_divergence']:
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    91
            for rev in rewinded:
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    92
                ctx = unfi[rev]
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    93
                ssets = obsutil.successorssets(repo, ctx.node(), sscache)
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    94
                if 1 < len(ssets):
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
    95
                    msg = _(b'rewind confused by divergence on %s') % ctx
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
    96
                    hint = _(b'solve divergence first or use "--as-divergence"')
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    97
                    raise error.Abort(msg, hint=hint)
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    98
                if ssets and ssets[0]:
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    99
                    for succ in ssets[0]:
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   100
                        successorsmap[succ].add(ctx.node())
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   101
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   102
        # Check that we can rewind these changesets
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   103
        with repo.transaction(b'rewind'):
4821
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   104
            oldctx = repo[b'.']
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   105
3866
de42d00d6ee2 rewind: use rewinded parent when creating multiple changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3865
diff changeset
   106
            for rev in sorted(rewinded):
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   107
                ctx = unfi[rev]
3866
de42d00d6ee2 rewind: use rewinded parent when creating multiple changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3865
diff changeset
   108
                rewindmap[ctx.node()] = _revive_revision(unfi, rev, rewindmap)
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   109
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   110
            relationships = []
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   111
            cl = unfi.changelog
3863
c31be22d1d90 rewind: update the working copy if it gets obsoleted
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3862
diff changeset
   112
            wctxp = repo[None].p1()
c31be22d1d90 rewind: update the working copy if it gets obsoleted
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3862
diff changeset
   113
            update_target = None
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   114
            for (source, dest) in sorted(successorsmap.items()):
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   115
                newdest = [rewindmap[d] for d in sorted(dest, key=cl.rev)]
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   116
                rel = (unfi[source], tuple(unfi[d] for d in newdest))
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   117
                relationships.append(rel)
3863
c31be22d1d90 rewind: update the working copy if it gets obsoleted
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3862
diff changeset
   118
                if wctxp.node() == source:
c31be22d1d90 rewind: update the working copy if it gets obsoleted
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3862
diff changeset
   119
                    update_target = newdest[-1]
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   120
            obsolete.createmarkers(unfi, relationships, operation=b'rewind')
3863
c31be22d1d90 rewind: update the working copy if it gets obsoleted
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3862
diff changeset
   121
            if update_target is not None:
4821
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   122
                if opts.get('keep'):
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   123
                    hg.updaterepo(repo, oldctx, True)
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   124
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   125
                    # This is largely the same as the implementation in
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   126
                    # strip.stripcmd() and cmdrewrite.cmdprune().
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   127
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   128
                    # only reset the dirstate for files that would actually
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   129
                    # change between the working context and the revived cset
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   130
                    newctx = repo[update_target]
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   131
                    changedfiles = []
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   132
                    for ctx in [oldctx, newctx]:
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   133
                        # blindly reset the files, regardless of what actually
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   134
                        # changed
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   135
                        changedfiles.extend(ctx.files())
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   136
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   137
                    # reset files that only changed in the dirstate too
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   138
                    dirstate = repo.dirstate
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   139
                    dirchanges = [f for f in dirstate if dirstate[f] != 'n']
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   140
                    changedfiles.extend(dirchanges)
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   141
                    repo.dirstate.rebuild(newctx.node(), newctx.manifest(),
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   142
                                          changedfiles)
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   143
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   144
                    # TODO: implement restoration of copies/renames
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   145
                    # Ideally this step should be handled by dirstate.rebuild
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   146
                    # or scmutil.movedirstate, but right now there's no copy
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   147
                    # tracing across obsolescence relation (oldctx <-> newctx).
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   148
                    revertopts = {'no_backup': True, 'all': True,
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   149
                                  'rev': oldctx.node()}
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   150
                    with ui.configoverride({(b'ui', b'quiet'): True}):
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   151
                        cmdutil.revert(repo.ui, repo, oldctx,
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   152
                                       repo.dirstate.parents(), **revertopts)
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   153
                else:
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   154
                    hg.updaterepo(repo, update_target, False)
3863
c31be22d1d90 rewind: update the working copy if it gets obsoleted
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3862
diff changeset
   155
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   156
    repo.ui.status(_(b'rewinded to %d changesets\n') % len(rewinded))
3862
8d3eed113b77 rewind: add a message about obsolete changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3861
diff changeset
   157
    if relationships:
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   158
        repo.ui.status(_(b'(%d changesets obsoleted)\n') % len(relationships))
4821
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   159
    if update_target is not None and not opts.get('keep'):
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   160
        ui.status(_(b'working directory is now at %s\n') % repo[b'.'])
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   161
3869
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
   162
def _select_rewinded(repo, opts):
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
   163
    """select the revision we shoudl rewind to
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
   164
    """
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   165
    unfi = repo.unfiltered()
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   166
    rewinded = set()
3872
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   167
    revsto = opts.get('to')
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   168
    revsfrom = opts.get('from')
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   169
    if not (revsto or revsfrom):
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   170
        revsfrom.append(b'.')
3872
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   171
    if revsto:
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   172
        rewinded.update(scmutil.revrange(repo, revsto))
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   173
    if revsfrom:
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   174
        succs = scmutil.revrange(repo, revsfrom)
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   175
        rewinded.update(unfi.revs(b'predecessors(%ld)', succs))
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   176
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   177
    if not rewinded:
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   178
        raise error.Abort(b'no revision to rewind to')
3869
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
   179
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   180
    if not opts['exact']:
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   181
        rewinded = unfi.revs(b'obsolete() and ::%ld', rewinded)
3869
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
   182
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   183
    return sorted(rewinded)
3869
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
   184
3866
de42d00d6ee2 rewind: use rewinded parent when creating multiple changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3865
diff changeset
   185
def _revive_revision(unfi, rev, rewindmap):
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   186
    """rewind a single revision rev.
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   187
    """
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   188
    ctx = unfi[rev]
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   189
    extra = ctx.extra().copy()
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   190
    # rewind hash should be unique over multiple rewind.
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   191
    user = unfi.ui.config(b'devel', b'user.obsmarker')
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   192
    if not user:
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   193
        user = unfi.ui.username()
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   194
    date = unfi.ui.configdate(b'devel', b'default-date')
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   195
    if date is None:
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   196
        date = compat.makedate()
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   197
    noise = b"%s\0%s\0%d\0%d" % (ctx.node(), user, date[0], date[1])
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   198
    extra[b'__rewind-hash__'] = hashlib.sha256(noise).hexdigest()
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   199
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   200
    p1 = ctx.p1().node()
3866
de42d00d6ee2 rewind: use rewinded parent when creating multiple changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3865
diff changeset
   201
    p1 = rewindmap.get(p1, p1)
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   202
    p2 = ctx.p2().node()
3866
de42d00d6ee2 rewind: use rewinded parent when creating multiple changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3865
diff changeset
   203
    p2 = rewindmap.get(p2, p2)
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   204
4722
7839720c7c75 rewind: make sure merge commits include files from p1 and p2
Anton Shestakov <av6@dwimlabs.net>
parents: 4715
diff changeset
   205
    updates = []
7839720c7c75 rewind: make sure merge commits include files from p1 and p2
Anton Shestakov <av6@dwimlabs.net>
parents: 4715
diff changeset
   206
    if len(ctx.parents()) > 1:
7839720c7c75 rewind: make sure merge commits include files from p1 and p2
Anton Shestakov <av6@dwimlabs.net>
parents: 4715
diff changeset
   207
        updates = ctx.parents()
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   208
    extradict = {b'extra': extra}
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   209
4722
7839720c7c75 rewind: make sure merge commits include files from p1 and p2
Anton Shestakov <av6@dwimlabs.net>
parents: 4715
diff changeset
   210
    new, unusedvariable = rewriteutil.rewrite(unfi, ctx, updates, ctx,
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   211
                                              [p1, p2],
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   212
                                              commitopts=extradict)
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   213
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   214
    obsolete.createmarkers(unfi, [(ctx, (unfi[new],))],
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   215
                           flag=identicalflag, operation=b'rewind')
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   216
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   217
    return new