##// END OF EJS Templates
rewriteutil: add devel warning if precheck is called with contexts...
Martin von Zweigbergk -
r47780:8ad2f43f default
parent child Browse files
Show More
@@ -1,138 +1,143
1 # rewriteutil.py - utility functions for rewriting changesets
1 # rewriteutil.py - utility functions for rewriting changesets
2 #
2 #
3 # Copyright 2017 Octobus <contact@octobus.net>
3 # Copyright 2017 Octobus <contact@octobus.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import re
10 import re
11
11
12 from .i18n import _
12 from .i18n import _
13 from .node import (
13 from .node import (
14 hex,
14 hex,
15 nullrev,
15 nullrev,
16 )
16 )
17
17
18 from . import (
18 from . import (
19 error,
19 error,
20 obsolete,
20 obsolete,
21 obsutil,
21 obsutil,
22 revset,
22 revset,
23 scmutil,
23 scmutil,
24 util,
24 )
25 )
25
26
26
27
27 NODE_RE = re.compile(br'\b[0-9a-f]{6,64}\b')
28 NODE_RE = re.compile(br'\b[0-9a-f]{6,64}\b')
28
29
29
30
30 def precheck(repo, revs, action=b'rewrite'):
31 def precheck(repo, revs, action=b'rewrite'):
31 """check if revs can be rewritten
32 """check if revs can be rewritten
32 action is used to control the error message.
33 action is used to control the error message.
33
34
34 Make sure this function is called after taking the lock.
35 Make sure this function is called after taking the lock.
35 """
36 """
36 if nullrev in revs:
37 if nullrev in revs:
37 msg = _(b"cannot %s the null revision") % action
38 msg = _(b"cannot %s the null revision") % action
38 hint = _(b"no changeset checked out")
39 hint = _(b"no changeset checked out")
39 raise error.InputError(msg, hint=hint)
40 raise error.InputError(msg, hint=hint)
40
41
42 if any(util.safehasattr(r, 'rev') for r in revs):
43 repo.ui.develwarn(b"rewriteutil.precheck called with ctx not revs")
44 revs = (r.rev() for r in revs)
45
41 if len(repo[None].parents()) > 1:
46 if len(repo[None].parents()) > 1:
42 raise error.StateError(_(b"cannot %s while merging") % action)
47 raise error.StateError(_(b"cannot %s while merging") % action)
43
48
44 publicrevs = repo.revs(b'%ld and public()', revs)
49 publicrevs = repo.revs(b'%ld and public()', revs)
45 if publicrevs:
50 if publicrevs:
46 msg = _(b"cannot %s public changesets") % action
51 msg = _(b"cannot %s public changesets") % action
47 hint = _(b"see 'hg help phases' for details")
52 hint = _(b"see 'hg help phases' for details")
48 raise error.InputError(msg, hint=hint)
53 raise error.InputError(msg, hint=hint)
49
54
50 newunstable = disallowednewunstable(repo, revs)
55 newunstable = disallowednewunstable(repo, revs)
51 if newunstable:
56 if newunstable:
52 raise error.InputError(_(b"cannot %s changeset with children") % action)
57 raise error.InputError(_(b"cannot %s changeset with children") % action)
53
58
54
59
55 def disallowednewunstable(repo, revs):
60 def disallowednewunstable(repo, revs):
56 """Checks whether editing the revs will create new unstable changesets and
61 """Checks whether editing the revs will create new unstable changesets and
57 are we allowed to create them.
62 are we allowed to create them.
58
63
59 To allow new unstable changesets, set the config:
64 To allow new unstable changesets, set the config:
60 `experimental.evolution.allowunstable=True`
65 `experimental.evolution.allowunstable=True`
61 """
66 """
62 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
67 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
63 if allowunstable:
68 if allowunstable:
64 return revset.baseset()
69 return revset.baseset()
65 return repo.revs(b"(%ld::) - %ld", revs, revs)
70 return repo.revs(b"(%ld::) - %ld", revs, revs)
66
71
67
72
68 def skip_empty_successor(ui, command):
73 def skip_empty_successor(ui, command):
69 empty_successor = ui.config(b'rewrite', b'empty-successor')
74 empty_successor = ui.config(b'rewrite', b'empty-successor')
70 if empty_successor == b'skip':
75 if empty_successor == b'skip':
71 return True
76 return True
72 elif empty_successor == b'keep':
77 elif empty_successor == b'keep':
73 return False
78 return False
74 else:
79 else:
75 raise error.ConfigError(
80 raise error.ConfigError(
76 _(
81 _(
77 b"%s doesn't know how to handle config "
82 b"%s doesn't know how to handle config "
78 b"rewrite.empty-successor=%s (only 'skip' and 'keep' are "
83 b"rewrite.empty-successor=%s (only 'skip' and 'keep' are "
79 b"supported)"
84 b"supported)"
80 )
85 )
81 % (command, empty_successor)
86 % (command, empty_successor)
82 )
87 )
83
88
84
89
85 def update_hash_refs(repo, commitmsg, pending=None):
90 def update_hash_refs(repo, commitmsg, pending=None):
86 """Replace all obsolete commit hashes in the message with the current hash.
91 """Replace all obsolete commit hashes in the message with the current hash.
87
92
88 If the obsolete commit was split or is divergent, the hash is not replaced
93 If the obsolete commit was split or is divergent, the hash is not replaced
89 as there's no way to know which successor to choose.
94 as there's no way to know which successor to choose.
90
95
91 For commands that update a series of commits in the current transaction, the
96 For commands that update a series of commits in the current transaction, the
92 new obsolete markers can be considered by setting ``pending`` to a mapping
97 new obsolete markers can be considered by setting ``pending`` to a mapping
93 of ``pending[oldnode] = [successor_node1, successor_node2,..]``.
98 of ``pending[oldnode] = [successor_node1, successor_node2,..]``.
94 """
99 """
95 if not pending:
100 if not pending:
96 pending = {}
101 pending = {}
97 cache = {}
102 cache = {}
98 hashes = re.findall(NODE_RE, commitmsg)
103 hashes = re.findall(NODE_RE, commitmsg)
99 unfi = repo.unfiltered()
104 unfi = repo.unfiltered()
100 for h in hashes:
105 for h in hashes:
101 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
106 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
102 if fullnode is None:
107 if fullnode is None:
103 continue
108 continue
104 ctx = unfi[fullnode]
109 ctx = unfi[fullnode]
105 if not ctx.obsolete():
110 if not ctx.obsolete():
106 successors = pending.get(fullnode)
111 successors = pending.get(fullnode)
107 if successors is None:
112 if successors is None:
108 continue
113 continue
109 # obsutil.successorssets() returns a list of list of nodes
114 # obsutil.successorssets() returns a list of list of nodes
110 successors = [successors]
115 successors = [successors]
111 else:
116 else:
112 successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
117 successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
113
118
114 # We can't make any assumptions about how to update the hash if the
119 # We can't make any assumptions about how to update the hash if the
115 # cset in question was split or diverged.
120 # cset in question was split or diverged.
116 if len(successors) == 1 and len(successors[0]) == 1:
121 if len(successors) == 1 and len(successors[0]) == 1:
117 successor = successors[0][0]
122 successor = successors[0][0]
118 if successor is not None:
123 if successor is not None:
119 newhash = hex(successor)
124 newhash = hex(successor)
120 commitmsg = commitmsg.replace(h, newhash[: len(h)])
125 commitmsg = commitmsg.replace(h, newhash[: len(h)])
121 else:
126 else:
122 repo.ui.note(
127 repo.ui.note(
123 _(
128 _(
124 b'The stale commit message reference to %s could '
129 b'The stale commit message reference to %s could '
125 b'not be updated\n(The referenced commit was dropped)\n'
130 b'not be updated\n(The referenced commit was dropped)\n'
126 )
131 )
127 % h
132 % h
128 )
133 )
129 else:
134 else:
130 repo.ui.note(
135 repo.ui.note(
131 _(
136 _(
132 b'The stale commit message reference to %s could '
137 b'The stale commit message reference to %s could '
133 b'not be updated\n'
138 b'not be updated\n'
134 )
139 )
135 % h
140 % h
136 )
141 )
137
142
138 return commitmsg
143 return commitmsg
General Comments 0
You need to be logged in to leave comments. Login now