##// END OF EJS Templates
rewriteutil: check for divergence...
Martin von Zweigbergk -
r47784:ba6881c6 default
parent child Browse files
Show More
@@ -446,8 +446,15 b' class rebaseruntime(object):'
446 rebaseset = set(destmap.keys())
446 rebaseset = set(destmap.keys())
447 rebaseset -= set(self.obsolete_with_successor_in_destination)
447 rebaseset -= set(self.obsolete_with_successor_in_destination)
448 rebaseset -= self.obsolete_with_successor_in_rebase_set
448 rebaseset -= self.obsolete_with_successor_in_rebase_set
449 # We have our own divergence-checking in the rebase extension
450 overrides = {}
451 if obsolete.isenabled(self.repo, obsolete.createmarkersopt):
452 overrides = {
453 (b'experimental', b'evolution.allowdivergence'): b'true'
454 }
449 try:
455 try:
450 rewriteutil.precheck(self.repo, rebaseset, action=b'rebase')
456 with self.ui.configoverride(overrides):
457 rewriteutil.precheck(self.repo, rebaseset, action=b'rebase')
451 except error.Abort as e:
458 except error.Abort as e:
452 if e.hint is None:
459 if e.hint is None:
453 e.hint = _(b'use --keep to keep original changesets')
460 e.hint = _(b'use --keep to keep original changesets')
@@ -106,6 +106,7 b' propertycache = util.propertycache'
106 # Options for obsolescence
106 # Options for obsolescence
107 createmarkersopt = b'createmarkers'
107 createmarkersopt = b'createmarkers'
108 allowunstableopt = b'allowunstable'
108 allowunstableopt = b'allowunstable'
109 allowdivergenceopt = b'allowdivergence'
109 exchangeopt = b'exchange'
110 exchangeopt = b'exchange'
110
111
111
112
@@ -144,10 +145,13 b' def getoptions(repo):'
144
145
145 createmarkersvalue = _getoptionvalue(repo, createmarkersopt)
146 createmarkersvalue = _getoptionvalue(repo, createmarkersopt)
146 unstablevalue = _getoptionvalue(repo, allowunstableopt)
147 unstablevalue = _getoptionvalue(repo, allowunstableopt)
148 divergencevalue = _getoptionvalue(repo, allowdivergenceopt)
147 exchangevalue = _getoptionvalue(repo, exchangeopt)
149 exchangevalue = _getoptionvalue(repo, exchangeopt)
148
150
149 # createmarkers must be enabled if other options are enabled
151 # createmarkers must be enabled if other options are enabled
150 if (unstablevalue or exchangevalue) and not createmarkersvalue:
152 if (
153 unstablevalue or divergencevalue or exchangevalue
154 ) and not createmarkersvalue:
151 raise error.Abort(
155 raise error.Abort(
152 _(
156 _(
153 b"'createmarkers' obsolete option must be enabled "
157 b"'createmarkers' obsolete option must be enabled "
@@ -158,6 +162,7 b' def getoptions(repo):'
158 return {
162 return {
159 createmarkersopt: createmarkersvalue,
163 createmarkersopt: createmarkersvalue,
160 allowunstableopt: unstablevalue,
164 allowunstableopt: unstablevalue,
165 allowdivergenceopt: divergencevalue,
161 exchangeopt: exchangevalue,
166 exchangeopt: exchangevalue,
162 }
167 }
163
168
@@ -44,7 +44,9 b" def precheck(repo, revs, action=b'rewrit"
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:
@@ -59,6 +61,38 b" def precheck(repo, revs, action=b'rewrit"
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
@@ -73,6 +107,40 b' def disallowednewunstable(repo, revs):'
73 return repo.revs(b"(%ld::) - %ld", revs, revs)
107 return repo.revs(b"(%ld::) - %ld", revs, revs)
74
108
75
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
142
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':
@@ -232,6 +232,17 b' Checking the note stored in the obsmarke'
232 $ hg debugobsolete -r .
232 $ hg debugobsolete -r .
233 112478962961147124edd43549aedd1a335e44bf be169c7e8dbe21cd10b3d79691cbe7f241e3c21c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
233 112478962961147124edd43549aedd1a335e44bf be169c7e8dbe21cd10b3d79691cbe7f241e3c21c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
234 be169c7e8dbe21cd10b3d79691cbe7f241e3c21c 16084da537dd8f84cfdb3055c633772269d62e1b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'note': 'adding bar', 'operation': 'amend', 'user': 'test'}
234 be169c7e8dbe21cd10b3d79691cbe7f241e3c21c 16084da537dd8f84cfdb3055c633772269d62e1b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'note': 'adding bar', 'operation': 'amend', 'user': 'test'}
235
236 Cannot cause divergence by default
237
238 $ hg co --hidden 1
239 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
240 $ hg amend -m divergent
241 abort: cannot amend 112478962961, as that creates content-divergence with 16084da537dd
242 (add --verbose for details)
243 [10]
244 $ hg amend -m divergent --config experimental.evolution.allowdivergence=true
245 2 new content-divergent changesets
235 #endif
246 #endif
236
247
237 Cannot amend public changeset
248 Cannot amend public changeset
@@ -150,7 +150,8 b' Changing branch of an obsoleted changese'
150 [255]
150 [255]
151
151
152 $ hg branch -r 4 --hidden foobar
152 $ hg branch -r 4 --hidden foobar
153 abort: cannot change branch of a obsolete changeset
153 abort: cannot change branch of 3938acfb5c0f, as that creates content-divergence with 7c1991464886
154 (add --verbose for details)
154 [10]
155 [10]
155
156
156 Make sure bookmark movement is correct
157 Make sure bookmark movement is correct
@@ -13,6 +13,7 b' Global setup'
13 > [experimental]
13 > [experimental]
14 > evolution.createmarkers = yes
14 > evolution.createmarkers = yes
15 > evolution.effect-flags = yes
15 > evolution.effect-flags = yes
16 > evolution.allowdivergence=true
16 > EOF
17 > EOF
17
18
18 Test output on amended commit
19 Test output on amended commit
@@ -11,6 +11,7 b' Global setup'
11 > publish=False
11 > publish=False
12 > [experimental]
12 > [experimental]
13 > evolution=true
13 > evolution=true
14 > evolution.allowdivergence=true
14 > [templates]
15 > [templates]
15 > obsfatesuccessors = "{if(successors, " as ")}{join(successors, ", ")}"
16 > obsfatesuccessors = "{if(successors, " as ")}{join(successors, ", ")}"
16 > obsfateverb = "{obsfateverb(successors, markers)}"
17 > obsfateverb = "{obsfateverb(successors, markers)}"
@@ -6,6 +6,7 b' Test for command `hg unamend` which live'
6 > glog = log -G -T '{rev}:{node|short} {desc}'
6 > glog = log -G -T '{rev}:{node|short} {desc}'
7 > [experimental]
7 > [experimental]
8 > evolution = createmarkers, allowunstable
8 > evolution = createmarkers, allowunstable
9 > evolution.allowdivergence = true
9 > [extensions]
10 > [extensions]
10 > rebase =
11 > rebase =
11 > amend =
12 > amend =
General Comments 0
You need to be logged in to leave comments. Login now