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 |
|
|
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 |
|
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