hgext3rd/evolve/rewind.py
author Martin von Zweigbergk <martinvonz@google.com>
Thu, 30 Apr 2020 10:05:14 -0700
changeset 5341 13376ca93fa3
parent 5262 678a9223aad3
permissions -rw-r--r--
evolve: always create commit when resolving divergence When resolving content-divergence, the final commit we create may end up empty (which means that Mercurial won't even create it). We've had code for handling that in evolve ever since 41bf6c27a122 (evolve: stabilize now handle conflicting changeset, 2012-08-23). However, that resolved the issue by marking on the divergent commits as successor. As Pierre-Yves has pointed out (in other code reviews), we should instead be creating a new successor. So that's what this patch does. It does that by setting `ui.allowemptycommit` while creating the final commit. However, that is not enough, because we may end up creating the same nodeid as already existed (we'd then end up trying to mark the "new" commit a successor of itself). To solve that, we add some salt to the commit extras. That salt affects lots of tests.
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
5178
61e49d2654cc compat: directly use function from dateutil
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5111
diff changeset
    15
from mercurial.utils import dateutil
61e49d2654cc compat: directly use function from dateutil
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5111
diff changeset
    16
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    17
from mercurial.i18n import _
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    18
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    19
from . import (
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    20
    exthelper,
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    21
    rewriteutil,
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    22
    compat,
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    23
)
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
eh = exthelper.exthelper()
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    26
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    27
# 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
    28
identicalflag = 4
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    29
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    30
@eh.command(
4715
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    31
    b'rewind|undo',
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    32
    [(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
    33
     (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
    34
     (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
    35
     (b'', b'from', [],
12c8b24757f4 py3: use byte strings for @command registrations
Martin von Zweigbergk <martinvonz@google.com>
parents: 4624
diff changeset
    36
      _(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
    37
     (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
    38
      _(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
    39
     ],
4821
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
    40
    _(b'[--as-divergence] [--exact] [--keep] [--to REV]... [--from REV]...'),
4894
f9743b13de6d help: categorizing evolve and topic commands
Rodrigo Damazio <rdamazio@google.com>
parents: 4821
diff changeset
    41
    helpbasic=True,
f9743b13de6d help: categorizing evolve and topic commands
Rodrigo Damazio <rdamazio@google.com>
parents: 4821
diff changeset
    42
    **compat.helpcategorykwargs('CATEGORY_CHANGE_MANAGEMENT'))
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    43
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
    44
    """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
    45
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    46
    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
    47
    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
    48
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    49
    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
    50
    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
    51
    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
    52
    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
    53
4794
7b5d08e84c4d rewind: working directory is the preferred term
Anton Shestakov <av6@dwimlabs.net>
parents: 4793
diff changeset
    54
    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
    55
    predecessor.
3872
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
    56
3868
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    57
    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
    58
    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
    59
    `--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
    60
    orphan.
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    61
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    62
    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
    63
    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
    64
    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
    65
    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
    66
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    67
    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
    68
b945f2dae587 rewind: add a test for rewinding a fold
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3863
diff changeset
    69
      * 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
    70
              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
    71
              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
    72
              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
    73
4091
2c60ad0d54a9 rewind: fix help text (mostly grammar, but also s/precursor/predecessor)
Martin von Zweigbergk <martinvonz@google.com>
parents: 3873
diff changeset
    74
      * :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
    75
              --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
    76
              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
    77
              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
    78
              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
    79
              (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
    80
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    81
    """
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    82
    unfi = repo.unfiltered()
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    83
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    84
    successorsmap = collections.defaultdict(set)
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    85
    rewindmap = {}
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    86
    sscache = {}
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    87
    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
    88
        # 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
    89
        cmdutil.bailifchanged(repo)
3868
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    90
3869
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
    91
        rewinded = _select_rewinded(repo, opts)
3868
1742254d1190 rewind: automatically rewind entire stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3866
diff changeset
    92
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    93
        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
    94
            for rev in rewinded:
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    95
                ctx = unfi[rev]
5048
3947964a4ce7 evolve: provide cache argument to obsutil.successorssets() correctly
Anton Shestakov <av6@dwimlabs.net>
parents: 4899
diff changeset
    96
                ssets = obsutil.successorssets(repo, ctx.node(), cache=sscache)
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
    97
                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
    98
                    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
    99
                    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
   100
                    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
   101
                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
   102
                    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
   103
                        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
   104
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   105
        # 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
   106
        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
   107
            oldctx = repo[b'.']
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   108
3866
de42d00d6ee2 rewind: use rewinded parent when creating multiple changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3865
diff changeset
   109
            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
   110
                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
   111
                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
   112
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   113
            relationships = []
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   114
            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
   115
            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
   116
            update_target = None
3861
bbe635dfd75c rewind: obsolete latest successors unless instructed otherwise
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3859
diff changeset
   117
            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
   118
                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
   119
                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
   120
                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
   121
                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
   122
                    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
   123
            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
   124
            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
   125
                if opts.get('keep'):
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   126
                    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
   127
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   128
                    # 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
   129
                    # 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
   130
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   131
                    # 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
   132
                    # 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
   133
                    newctx = repo[update_target]
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   134
                    changedfiles = []
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   135
                    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
   136
                        # 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
   137
                        # changed
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   138
                        changedfiles.extend(ctx.files())
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   139
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   140
                    # 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
   141
                    dirstate = repo.dirstate
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   142
                    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
   143
                    changedfiles.extend(dirchanges)
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   144
                    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
   145
                                          changedfiles)
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   146
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   147
                    # 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
   148
                    # 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
   149
                    # 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
   150
                    # 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
   151
                    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
   152
                                  'rev': oldctx.node()}
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   153
                    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
   154
                        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
   155
                                       repo.dirstate.parents(), **revertopts)
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   156
                else:
d8e36e60aea0 rewind: add --keep flag that "doesn't modify working directory"
Anton Shestakov <av6@dwimlabs.net>
parents: 4814
diff changeset
   157
                    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
   158
4814
48b30ff742cb python3: use format-source to run byteify-strings in .py files
Raphaël Gomès <rgomes@octobus.net>
parents: 4794
diff changeset
   159
    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
   160
    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
   161
        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
   162
    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
   163
        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
   164
3869
bbfbaf46f7b0 rewind: move revision selection into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3868
diff changeset
   165
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
   166
    """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
   167
    """
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   168
    unfi = repo.unfiltered()
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   169
    rewinded = set()
3872
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   170
    revsto = opts.get('to')
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   171
    revsfrom = opts.get('from')
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   172
    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
   173
        revsfrom.append(b'.')
3872
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   174
    if revsto:
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   175
        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
   176
    if revsfrom:
bbc3cfdfe42b rewind: default to rewinding the current stack
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3871
diff changeset
   177
        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
   178
        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
   179
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   180
    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
   181
        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
   182
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   183
    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
   184
        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
   185
3871
2e32a1ef0c60 rewing: add the ability to rewind "from" revisions
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3869
diff changeset
   186
    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
   187
3866
de42d00d6ee2 rewind: use rewinded parent when creating multiple changesets
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 3865
diff changeset
   188
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
   189
    """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
   190
    """
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   191
    ctx = unfi[rev]
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   192
    extra = ctx.extra().copy()
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   193
    # 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
   194
    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
   195
    if not user:
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   196
        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
   197
    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
   198
    if date is None:
5178
61e49d2654cc compat: directly use function from dateutil
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5111
diff changeset
   199
        date = dateutil.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
   200
    noise = b"%s\0%s\0%d\0%d" % (ctx.node(), user, date[0], date[1])
5214
d7aed9675db6 rewind: make __rewind-hash__ extra field be bytes
Anton Shestakov <av6@dwimlabs.net>
parents: 5111
diff changeset
   201
    extra[b'__rewind-hash__'] = hashlib.sha256(noise).hexdigest().encode('ascii')
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   202
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   203
    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
   204
    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
   205
    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
   206
    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
   207
4722
7839720c7c75 rewind: make sure merge commits include files from p1 and p2
Anton Shestakov <av6@dwimlabs.net>
parents: 4715
diff changeset
   208
    updates = []
7839720c7c75 rewind: make sure merge commits include files from p1 and p2
Anton Shestakov <av6@dwimlabs.net>
parents: 4715
diff changeset
   209
    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
   210
        updates = ctx.parents()
4899
c982e7fb5e7a rewind: preserve date
Manuel Jacob <me@manueljacob.de>
parents: 4821
diff changeset
   211
    commitopts = {b'extra': extra, b'date': ctx.date()}
3858
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   212
4722
7839720c7c75 rewind: make sure merge commits include files from p1 and p2
Anton Shestakov <av6@dwimlabs.net>
parents: 4715
diff changeset
   213
    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
   214
                                              [p1, p2],
4899
c982e7fb5e7a rewind: preserve date
Manuel Jacob <me@manueljacob.de>
parents: 4821
diff changeset
   215
                                              commitopts=commitopts)
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
    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
   218
                           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
   219
bb4f5ad63877 rewind: add a proto version of the command
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   220
    return new