mercurial/rewriteutil.py
changeset 47020 ba6881c6a178
parent 47019 c4dbbaecaad3
child 47069 5b6dd0d9171b
equal deleted inserted replaced
47019:c4dbbaecaad3 47020:ba6881c6a178
    42     if any(util.safehasattr(r, 'rev') for r in revs):
    42     if any(util.safehasattr(r, 'rev') for r in revs):
    43         repo.ui.develwarn(b"rewriteutil.precheck called with ctx not revs")
    43         repo.ui.develwarn(b"rewriteutil.precheck called with ctx not revs")
    44         revs = (r.rev() for r in revs)
    44         revs = (r.rev() for r in revs)
    45 
    45 
    46     if len(repo[None].parents()) > 1:
    46     if len(repo[None].parents()) > 1:
    47         raise error.StateError(_(b"cannot %s changesets while merging") % action)
    47         raise error.StateError(
       
    48             _(b"cannot %s changesets while merging") % action
       
    49         )
    48 
    50 
    49     publicrevs = repo.revs(b'%ld and public()', revs)
    51     publicrevs = repo.revs(b'%ld and public()', revs)
    50     if publicrevs:
    52     if publicrevs:
    51         msg = _(b"cannot %s public changesets") % action
    53         msg = _(b"cannot %s public changesets") % action
    52         hint = _(b"see 'hg help phases' for details")
    54         hint = _(b"see 'hg help phases' for details")
    57         hint = _(b"see 'hg help evolution.instability'")
    59         hint = _(b"see 'hg help evolution.instability'")
    58         raise error.InputError(
    60         raise error.InputError(
    59             _(b"cannot %s changeset with children") % action, hint=hint
    61             _(b"cannot %s changeset with children") % action, hint=hint
    60         )
    62         )
    61 
    63 
       
    64     if not obsolete.isenabled(repo, obsolete.allowdivergenceopt):
       
    65         new_divergence = _find_new_divergence(repo, revs)
       
    66         if new_divergence:
       
    67             local_ctx, other_ctx, base_ctx = new_divergence
       
    68             msg = _(
       
    69                 b'cannot %s %s, as that creates content-divergence with %s'
       
    70             ) % (
       
    71                 action,
       
    72                 local_ctx,
       
    73                 other_ctx,
       
    74             )
       
    75             if local_ctx.rev() != base_ctx.rev():
       
    76                 msg += _(b', from %s') % base_ctx
       
    77             if repo.ui.verbose:
       
    78                 if local_ctx.rev() != base_ctx.rev():
       
    79                     msg += _(
       
    80                         b'\n    changeset %s is a successor of ' b'changeset %s'
       
    81                     ) % (local_ctx, base_ctx)
       
    82                 msg += _(
       
    83                     b'\n    changeset %s already has a successor in '
       
    84                     b'changeset %s\n'
       
    85                     b'    rewriting changeset %s would create '
       
    86                     b'"content-divergence"\n'
       
    87                     b'    set experimental.evolution.allowdivergence=True to '
       
    88                     b'skip this check'
       
    89                 ) % (base_ctx, other_ctx, local_ctx)
       
    90                 raise error.InputError(msg)
       
    91             else:
       
    92                 raise error.InputError(
       
    93                     msg, hint=_(b"add --verbose for details")
       
    94                 )
       
    95 
    62 
    96 
    63 def disallowednewunstable(repo, revs):
    97 def disallowednewunstable(repo, revs):
    64     """Checks whether editing the revs will create new unstable changesets and
    98     """Checks whether editing the revs will create new unstable changesets and
    65     are we allowed to create them.
    99     are we allowed to create them.
    66 
   100 
    69     """
   103     """
    70     allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
   104     allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
    71     if allowunstable:
   105     if allowunstable:
    72         return revset.baseset()
   106         return revset.baseset()
    73     return repo.revs(b"(%ld::) - %ld", revs, revs)
   107     return repo.revs(b"(%ld::) - %ld", revs, revs)
       
   108 
       
   109 
       
   110 def _find_new_divergence(repo, revs):
       
   111     obsrevs = repo.revs(b'%ld and obsolete()', revs)
       
   112     for r in obsrevs:
       
   113         div = find_new_divergence_from(repo, repo[r])
       
   114         if div:
       
   115             return (repo[r], repo[div[0]], repo[div[1]])
       
   116     return None
       
   117 
       
   118 
       
   119 def find_new_divergence_from(repo, ctx):
       
   120     """return divergent revision if rewriting an obsolete cset (ctx) will
       
   121     create divergence
       
   122 
       
   123     Returns (<other node>, <common ancestor node>) or None
       
   124     """
       
   125     if not ctx.obsolete():
       
   126         return None
       
   127     # We need to check two cases that can cause divergence:
       
   128     # case 1: the rev being rewritten has a non-obsolete successor (easily
       
   129     #     detected by successorssets)
       
   130     sset = obsutil.successorssets(repo, ctx.node())
       
   131     if sset:
       
   132         return (sset[0][0], ctx.node())
       
   133     else:
       
   134         # case 2: one of the precursors of the rev being revived has a
       
   135         #     non-obsolete successor (we need divergentsets for this)
       
   136         divsets = obsutil.divergentsets(repo, ctx)
       
   137         if divsets:
       
   138             nsuccset = divsets[0][b'divergentnodes']
       
   139             prec = divsets[0][b'commonpredecessor']
       
   140             return (nsuccset[0], prec)
       
   141         return None
    74 
   142 
    75 
   143 
    76 def skip_empty_successor(ui, command):
   144 def skip_empty_successor(ui, command):
    77     empty_successor = ui.config(b'rewrite', b'empty-successor')
   145     empty_successor = ui.config(b'rewrite', b'empty-successor')
    78     if empty_successor == b'skip':
   146     if empty_successor == b'skip':