##// END OF EJS Templates
rewriteutil: look up common predecessor on unfiltered repo...
Martin von Zweigbergk -
r48348:debc2990 default
parent child Browse files
Show More
@@ -1,247 +1,247 b''
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 node,
20 node,
21 obsolete,
21 obsolete,
22 obsutil,
22 obsutil,
23 revset,
23 revset,
24 scmutil,
24 scmutil,
25 util,
25 util,
26 )
26 )
27
27
28
28
29 NODE_RE = re.compile(br'\b[0-9a-f]{6,64}\b')
29 NODE_RE = re.compile(br'\b[0-9a-f]{6,64}\b')
30
30
31
31
32 def _formatrevs(repo, revs, maxrevs=4):
32 def _formatrevs(repo, revs, maxrevs=4):
33 """returns a string summarizing revisions in a decent size
33 """returns a string summarizing revisions in a decent size
34
34
35 If there are few enough revisions, we list them all. Otherwise we display a
35 If there are few enough revisions, we list them all. Otherwise we display a
36 summary of the form:
36 summary of the form:
37
37
38 1ea73414a91b and 5 others
38 1ea73414a91b and 5 others
39 """
39 """
40 tonode = repo.changelog.node
40 tonode = repo.changelog.node
41 numrevs = len(revs)
41 numrevs = len(revs)
42 if numrevs < maxrevs:
42 if numrevs < maxrevs:
43 shorts = [node.short(tonode(r)) for r in revs]
43 shorts = [node.short(tonode(r)) for r in revs]
44 summary = b', '.join(shorts)
44 summary = b', '.join(shorts)
45 else:
45 else:
46 first = revs.first()
46 first = revs.first()
47 summary = _(b'%s and %d others')
47 summary = _(b'%s and %d others')
48 summary %= (node.short(tonode(first)), numrevs - 1)
48 summary %= (node.short(tonode(first)), numrevs - 1)
49 return summary
49 return summary
50
50
51
51
52 def precheck(repo, revs, action=b'rewrite'):
52 def precheck(repo, revs, action=b'rewrite'):
53 """check if revs can be rewritten
53 """check if revs can be rewritten
54 action is used to control the error message.
54 action is used to control the error message.
55
55
56 Make sure this function is called after taking the lock.
56 Make sure this function is called after taking the lock.
57 """
57 """
58 if nullrev in revs:
58 if nullrev in revs:
59 msg = _(b"cannot %s the null revision") % action
59 msg = _(b"cannot %s the null revision") % action
60 hint = _(b"no changeset checked out")
60 hint = _(b"no changeset checked out")
61 raise error.InputError(msg, hint=hint)
61 raise error.InputError(msg, hint=hint)
62
62
63 if any(util.safehasattr(r, 'rev') for r in revs):
63 if any(util.safehasattr(r, 'rev') for r in revs):
64 repo.ui.develwarn(b"rewriteutil.precheck called with ctx not revs")
64 repo.ui.develwarn(b"rewriteutil.precheck called with ctx not revs")
65 revs = (r.rev() for r in revs)
65 revs = (r.rev() for r in revs)
66
66
67 if len(repo[None].parents()) > 1:
67 if len(repo[None].parents()) > 1:
68 raise error.StateError(
68 raise error.StateError(
69 _(b"cannot %s changesets while merging") % action
69 _(b"cannot %s changesets while merging") % action
70 )
70 )
71
71
72 publicrevs = repo.revs(b'%ld and public()', revs)
72 publicrevs = repo.revs(b'%ld and public()', revs)
73 if publicrevs:
73 if publicrevs:
74 summary = _formatrevs(repo, publicrevs)
74 summary = _formatrevs(repo, publicrevs)
75 msg = _(b"cannot %s public changesets: %s") % (action, summary)
75 msg = _(b"cannot %s public changesets: %s") % (action, summary)
76 hint = _(b"see 'hg help phases' for details")
76 hint = _(b"see 'hg help phases' for details")
77 raise error.InputError(msg, hint=hint)
77 raise error.InputError(msg, hint=hint)
78
78
79 newunstable = disallowednewunstable(repo, revs)
79 newunstable = disallowednewunstable(repo, revs)
80 if newunstable:
80 if newunstable:
81 hint = _(b"see 'hg help evolution.instability'")
81 hint = _(b"see 'hg help evolution.instability'")
82 raise error.InputError(
82 raise error.InputError(
83 _(b"cannot %s changeset, as that will orphan %d descendants")
83 _(b"cannot %s changeset, as that will orphan %d descendants")
84 % (action, len(newunstable)),
84 % (action, len(newunstable)),
85 hint=hint,
85 hint=hint,
86 )
86 )
87
87
88 if not obsolete.isenabled(repo, obsolete.allowdivergenceopt):
88 if not obsolete.isenabled(repo, obsolete.allowdivergenceopt):
89 new_divergence = _find_new_divergence(repo, revs)
89 new_divergence = _find_new_divergence(repo, revs)
90 if new_divergence:
90 if new_divergence:
91 local_ctx, other_ctx, base_ctx = new_divergence
91 local_ctx, other_ctx, base_ctx = new_divergence
92 msg = _(
92 msg = _(
93 b'cannot %s %s, as that creates content-divergence with %s'
93 b'cannot %s %s, as that creates content-divergence with %s'
94 ) % (
94 ) % (
95 action,
95 action,
96 local_ctx,
96 local_ctx,
97 other_ctx,
97 other_ctx,
98 )
98 )
99 if local_ctx.rev() != base_ctx.rev():
99 if local_ctx.rev() != base_ctx.rev():
100 msg += _(b', from %s') % base_ctx
100 msg += _(b', from %s') % base_ctx
101 if repo.ui.verbose:
101 if repo.ui.verbose:
102 if local_ctx.rev() != base_ctx.rev():
102 if local_ctx.rev() != base_ctx.rev():
103 msg += _(
103 msg += _(
104 b'\n changeset %s is a successor of ' b'changeset %s'
104 b'\n changeset %s is a successor of ' b'changeset %s'
105 ) % (local_ctx, base_ctx)
105 ) % (local_ctx, base_ctx)
106 msg += _(
106 msg += _(
107 b'\n changeset %s already has a successor in '
107 b'\n changeset %s already has a successor in '
108 b'changeset %s\n'
108 b'changeset %s\n'
109 b' rewriting changeset %s would create '
109 b' rewriting changeset %s would create '
110 b'"content-divergence"\n'
110 b'"content-divergence"\n'
111 b' set experimental.evolution.allowdivergence=True to '
111 b' set experimental.evolution.allowdivergence=True to '
112 b'skip this check'
112 b'skip this check'
113 ) % (base_ctx, other_ctx, local_ctx)
113 ) % (base_ctx, other_ctx, local_ctx)
114 raise error.InputError(
114 raise error.InputError(
115 msg,
115 msg,
116 hint=_(
116 hint=_(
117 b"see 'hg help evolution.instability' for details on content-divergence"
117 b"see 'hg help evolution.instability' for details on content-divergence"
118 ),
118 ),
119 )
119 )
120 else:
120 else:
121 raise error.InputError(
121 raise error.InputError(
122 msg,
122 msg,
123 hint=_(
123 hint=_(
124 b"add --verbose for details or see "
124 b"add --verbose for details or see "
125 b"'hg help evolution.instability'"
125 b"'hg help evolution.instability'"
126 ),
126 ),
127 )
127 )
128
128
129
129
130 def disallowednewunstable(repo, revs):
130 def disallowednewunstable(repo, revs):
131 """Checks whether editing the revs will create new unstable changesets and
131 """Checks whether editing the revs will create new unstable changesets and
132 are we allowed to create them.
132 are we allowed to create them.
133
133
134 To allow new unstable changesets, set the config:
134 To allow new unstable changesets, set the config:
135 `experimental.evolution.allowunstable=True`
135 `experimental.evolution.allowunstable=True`
136 """
136 """
137 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
137 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
138 if allowunstable:
138 if allowunstable:
139 return revset.baseset()
139 return revset.baseset()
140 return repo.revs(b"(%ld::) - %ld", revs, revs)
140 return repo.revs(b"(%ld::) - %ld", revs, revs)
141
141
142
142
143 def _find_new_divergence(repo, revs):
143 def _find_new_divergence(repo, revs):
144 obsrevs = repo.revs(b'%ld and obsolete()', revs)
144 obsrevs = repo.revs(b'%ld and obsolete()', revs)
145 for r in obsrevs:
145 for r in obsrevs:
146 div = find_new_divergence_from(repo, repo[r])
146 div = find_new_divergence_from(repo, repo[r])
147 if div:
147 if div:
148 return (repo[r], repo[div[0]], repo[div[1]])
148 return (repo[r], repo[div[0]], repo.unfiltered()[div[1]])
149 return None
149 return None
150
150
151
151
152 def find_new_divergence_from(repo, ctx):
152 def find_new_divergence_from(repo, ctx):
153 """return divergent revision if rewriting an obsolete cset (ctx) will
153 """return divergent revision if rewriting an obsolete cset (ctx) will
154 create divergence
154 create divergence
155
155
156 Returns (<other node>, <common ancestor node>) or None
156 Returns (<other node>, <common ancestor node>) or None
157 """
157 """
158 if not ctx.obsolete():
158 if not ctx.obsolete():
159 return None
159 return None
160 # We need to check two cases that can cause divergence:
160 # We need to check two cases that can cause divergence:
161 # case 1: the rev being rewritten has a non-obsolete successor (easily
161 # case 1: the rev being rewritten has a non-obsolete successor (easily
162 # detected by successorssets)
162 # detected by successorssets)
163 sset = obsutil.successorssets(repo, ctx.node())
163 sset = obsutil.successorssets(repo, ctx.node())
164 if sset:
164 if sset:
165 return (sset[0][0], ctx.node())
165 return (sset[0][0], ctx.node())
166 else:
166 else:
167 # case 2: one of the precursors of the rev being revived has a
167 # case 2: one of the precursors of the rev being revived has a
168 # non-obsolete successor (we need divergentsets for this)
168 # non-obsolete successor (we need divergentsets for this)
169 divsets = obsutil.divergentsets(repo, ctx)
169 divsets = obsutil.divergentsets(repo, ctx)
170 if divsets:
170 if divsets:
171 nsuccset = divsets[0][b'divergentnodes']
171 nsuccset = divsets[0][b'divergentnodes']
172 prec = divsets[0][b'commonpredecessor']
172 prec = divsets[0][b'commonpredecessor']
173 return (nsuccset[0], prec)
173 return (nsuccset[0], prec)
174 return None
174 return None
175
175
176
176
177 def skip_empty_successor(ui, command):
177 def skip_empty_successor(ui, command):
178 empty_successor = ui.config(b'rewrite', b'empty-successor')
178 empty_successor = ui.config(b'rewrite', b'empty-successor')
179 if empty_successor == b'skip':
179 if empty_successor == b'skip':
180 return True
180 return True
181 elif empty_successor == b'keep':
181 elif empty_successor == b'keep':
182 return False
182 return False
183 else:
183 else:
184 raise error.ConfigError(
184 raise error.ConfigError(
185 _(
185 _(
186 b"%s doesn't know how to handle config "
186 b"%s doesn't know how to handle config "
187 b"rewrite.empty-successor=%s (only 'skip' and 'keep' are "
187 b"rewrite.empty-successor=%s (only 'skip' and 'keep' are "
188 b"supported)"
188 b"supported)"
189 )
189 )
190 % (command, empty_successor)
190 % (command, empty_successor)
191 )
191 )
192
192
193
193
194 def update_hash_refs(repo, commitmsg, pending=None):
194 def update_hash_refs(repo, commitmsg, pending=None):
195 """Replace all obsolete commit hashes in the message with the current hash.
195 """Replace all obsolete commit hashes in the message with the current hash.
196
196
197 If the obsolete commit was split or is divergent, the hash is not replaced
197 If the obsolete commit was split or is divergent, the hash is not replaced
198 as there's no way to know which successor to choose.
198 as there's no way to know which successor to choose.
199
199
200 For commands that update a series of commits in the current transaction, the
200 For commands that update a series of commits in the current transaction, the
201 new obsolete markers can be considered by setting ``pending`` to a mapping
201 new obsolete markers can be considered by setting ``pending`` to a mapping
202 of ``pending[oldnode] = [successor_node1, successor_node2,..]``.
202 of ``pending[oldnode] = [successor_node1, successor_node2,..]``.
203 """
203 """
204 if not pending:
204 if not pending:
205 pending = {}
205 pending = {}
206 cache = {}
206 cache = {}
207 hashes = re.findall(NODE_RE, commitmsg)
207 hashes = re.findall(NODE_RE, commitmsg)
208 unfi = repo.unfiltered()
208 unfi = repo.unfiltered()
209 for h in hashes:
209 for h in hashes:
210 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
210 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
211 if fullnode is None:
211 if fullnode is None:
212 continue
212 continue
213 ctx = unfi[fullnode]
213 ctx = unfi[fullnode]
214 if not ctx.obsolete():
214 if not ctx.obsolete():
215 successors = pending.get(fullnode)
215 successors = pending.get(fullnode)
216 if successors is None:
216 if successors is None:
217 continue
217 continue
218 # obsutil.successorssets() returns a list of list of nodes
218 # obsutil.successorssets() returns a list of list of nodes
219 successors = [successors]
219 successors = [successors]
220 else:
220 else:
221 successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
221 successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
222
222
223 # We can't make any assumptions about how to update the hash if the
223 # We can't make any assumptions about how to update the hash if the
224 # cset in question was split or diverged.
224 # cset in question was split or diverged.
225 if len(successors) == 1 and len(successors[0]) == 1:
225 if len(successors) == 1 and len(successors[0]) == 1:
226 successor = successors[0][0]
226 successor = successors[0][0]
227 if successor is not None:
227 if successor is not None:
228 newhash = hex(successor)
228 newhash = hex(successor)
229 commitmsg = commitmsg.replace(h, newhash[: len(h)])
229 commitmsg = commitmsg.replace(h, newhash[: len(h)])
230 else:
230 else:
231 repo.ui.note(
231 repo.ui.note(
232 _(
232 _(
233 b'The stale commit message reference to %s could '
233 b'The stale commit message reference to %s could '
234 b'not be updated\n(The referenced commit was dropped)\n'
234 b'not be updated\n(The referenced commit was dropped)\n'
235 )
235 )
236 % h
236 % h
237 )
237 )
238 else:
238 else:
239 repo.ui.note(
239 repo.ui.note(
240 _(
240 _(
241 b'The stale commit message reference to %s could '
241 b'The stale commit message reference to %s could '
242 b'not be updated\n'
242 b'not be updated\n'
243 )
243 )
244 % h
244 % h
245 )
245 )
246
246
247 return commitmsg
247 return commitmsg
@@ -1,576 +1,576 b''
1 #testcases obsstore-off obsstore-on
1 #testcases obsstore-off obsstore-on
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [extensions]
4 > [extensions]
5 > amend=
5 > amend=
6 > debugdrawdag=$TESTDIR/drawdag.py
6 > debugdrawdag=$TESTDIR/drawdag.py
7 > [diff]
7 > [diff]
8 > git=1
8 > git=1
9 > EOF
9 > EOF
10
10
11 #if obsstore-on
11 #if obsstore-on
12 $ cat << EOF >> $HGRCPATH
12 $ cat << EOF >> $HGRCPATH
13 > [experimental]
13 > [experimental]
14 > evolution.createmarkers=True
14 > evolution.createmarkers=True
15 > EOF
15 > EOF
16 #endif
16 #endif
17
17
18 Basic amend
18 Basic amend
19
19
20 $ hg init repo1
20 $ hg init repo1
21 $ cd repo1
21 $ cd repo1
22 $ hg debugdrawdag <<'EOS'
22 $ hg debugdrawdag <<'EOS'
23 > B
23 > B
24 > |
24 > |
25 > A
25 > A
26 > EOS
26 > EOS
27
27
28 $ hg update B -q
28 $ hg update B -q
29 $ echo 2 >> B
29 $ echo 2 >> B
30
30
31 $ hg amend
31 $ hg amend
32 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/112478962961-7e959a55-amend.hg (obsstore-off !)
32 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/112478962961-7e959a55-amend.hg (obsstore-off !)
33 #if obsstore-off
33 #if obsstore-off
34 $ hg log -p -G --hidden -T '{rev} {node|short} {desc}\n'
34 $ hg log -p -G --hidden -T '{rev} {node|short} {desc}\n'
35 @ 1 be169c7e8dbe B
35 @ 1 be169c7e8dbe B
36 | diff --git a/B b/B
36 | diff --git a/B b/B
37 | new file mode 100644
37 | new file mode 100644
38 | --- /dev/null
38 | --- /dev/null
39 | +++ b/B
39 | +++ b/B
40 | @@ -0,0 +1,1 @@
40 | @@ -0,0 +1,1 @@
41 | +B2
41 | +B2
42 |
42 |
43 o 0 426bada5c675 A
43 o 0 426bada5c675 A
44 diff --git a/A b/A
44 diff --git a/A b/A
45 new file mode 100644
45 new file mode 100644
46 --- /dev/null
46 --- /dev/null
47 +++ b/A
47 +++ b/A
48 @@ -0,0 +1,1 @@
48 @@ -0,0 +1,1 @@
49 +A
49 +A
50 \ No newline at end of file
50 \ No newline at end of file
51
51
52 #else
52 #else
53 $ hg log -p -G --hidden -T '{rev} {node|short} {desc}\n'
53 $ hg log -p -G --hidden -T '{rev} {node|short} {desc}\n'
54 @ 2 be169c7e8dbe B
54 @ 2 be169c7e8dbe B
55 | diff --git a/B b/B
55 | diff --git a/B b/B
56 | new file mode 100644
56 | new file mode 100644
57 | --- /dev/null
57 | --- /dev/null
58 | +++ b/B
58 | +++ b/B
59 | @@ -0,0 +1,1 @@
59 | @@ -0,0 +1,1 @@
60 | +B2
60 | +B2
61 |
61 |
62 | x 1 112478962961 B
62 | x 1 112478962961 B
63 |/ diff --git a/B b/B
63 |/ diff --git a/B b/B
64 | new file mode 100644
64 | new file mode 100644
65 | --- /dev/null
65 | --- /dev/null
66 | +++ b/B
66 | +++ b/B
67 | @@ -0,0 +1,1 @@
67 | @@ -0,0 +1,1 @@
68 | +B
68 | +B
69 | \ No newline at end of file
69 | \ No newline at end of file
70 |
70 |
71 o 0 426bada5c675 A
71 o 0 426bada5c675 A
72 diff --git a/A b/A
72 diff --git a/A b/A
73 new file mode 100644
73 new file mode 100644
74 --- /dev/null
74 --- /dev/null
75 +++ b/A
75 +++ b/A
76 @@ -0,0 +1,1 @@
76 @@ -0,0 +1,1 @@
77 +A
77 +A
78 \ No newline at end of file
78 \ No newline at end of file
79
79
80 #endif
80 #endif
81
81
82 Nothing changed
82 Nothing changed
83
83
84 $ hg amend
84 $ hg amend
85 nothing changed
85 nothing changed
86 [1]
86 [1]
87
87
88 $ hg amend -d "0 0"
88 $ hg amend -d "0 0"
89 nothing changed
89 nothing changed
90 [1]
90 [1]
91
91
92 $ hg amend -d "Thu Jan 01 00:00:00 1970 UTC"
92 $ hg amend -d "Thu Jan 01 00:00:00 1970 UTC"
93 nothing changed
93 nothing changed
94 [1]
94 [1]
95
95
96 #if obsstore-on
96 #if obsstore-on
97 $ hg init repo-merge-state
97 $ hg init repo-merge-state
98 $ cd repo-merge-state
98 $ cd repo-merge-state
99 $ echo a > f
99 $ echo a > f
100 $ hg ci -Aqm a
100 $ hg ci -Aqm a
101 $ echo b > f
101 $ echo b > f
102 $ hg ci -Aqm b
102 $ hg ci -Aqm b
103 $ echo c > f
103 $ echo c > f
104 $ hg co -m '.^'
104 $ hg co -m '.^'
105 merging f
105 merging f
106 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
106 warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
107 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
107 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
108 use 'hg resolve' to retry unresolved file merges
108 use 'hg resolve' to retry unresolved file merges
109 [1]
109 [1]
110 $ echo d > f
110 $ echo d > f
111 $ hg resolve -m f
111 $ hg resolve -m f
112 (no more unresolved files)
112 (no more unresolved files)
113 $ hg ci --amend --config experimental.evolution.allowunstable=True
113 $ hg ci --amend --config experimental.evolution.allowunstable=True
114 1 new orphan changesets
114 1 new orphan changesets
115 $ hg resolve -l
115 $ hg resolve -l
116 $ cd ..
116 $ cd ..
117 #endif
117 #endif
118
118
119 Matcher and metadata options
119 Matcher and metadata options
120
120
121 $ echo 3 > C
121 $ echo 3 > C
122 $ echo 4 > D
122 $ echo 4 > D
123 $ hg add C D
123 $ hg add C D
124 $ hg amend -m NEWMESSAGE -I C
124 $ hg amend -m NEWMESSAGE -I C
125 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/be169c7e8dbe-7684ddc5-amend.hg (obsstore-off !)
125 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/be169c7e8dbe-7684ddc5-amend.hg (obsstore-off !)
126 $ hg log -r . -T '{node|short} {desc} {files}\n'
126 $ hg log -r . -T '{node|short} {desc} {files}\n'
127 c7ba14d9075b NEWMESSAGE B C
127 c7ba14d9075b NEWMESSAGE B C
128 $ echo 5 > E
128 $ echo 5 > E
129 $ rm C
129 $ rm C
130 $ hg amend -d '2000 1000' -u 'Foo <foo@example.com>' -A C D
130 $ hg amend -d '2000 1000' -u 'Foo <foo@example.com>' -A C D
131 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/c7ba14d9075b-b3e76daa-amend.hg (obsstore-off !)
131 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/c7ba14d9075b-b3e76daa-amend.hg (obsstore-off !)
132 $ hg log -r . -T '{node|short} {desc} {files} {author} {date}\n'
132 $ hg log -r . -T '{node|short} {desc} {files} {author} {date}\n'
133 14f6c4bcc865 NEWMESSAGE B D Foo <foo@example.com> 2000.01000
133 14f6c4bcc865 NEWMESSAGE B D Foo <foo@example.com> 2000.01000
134
134
135 Amend with editor
135 Amend with editor
136
136
137 $ cat > $TESTTMP/prefix.sh <<'EOF'
137 $ cat > $TESTTMP/prefix.sh <<'EOF'
138 > printf 'EDITED: ' > $TESTTMP/msg
138 > printf 'EDITED: ' > $TESTTMP/msg
139 > cat "$1" >> $TESTTMP/msg
139 > cat "$1" >> $TESTTMP/msg
140 > mv $TESTTMP/msg "$1"
140 > mv $TESTTMP/msg "$1"
141 > EOF
141 > EOF
142 $ chmod +x $TESTTMP/prefix.sh
142 $ chmod +x $TESTTMP/prefix.sh
143
143
144 $ HGEDITOR="sh $TESTTMP/prefix.sh" hg amend --edit
144 $ HGEDITOR="sh $TESTTMP/prefix.sh" hg amend --edit
145 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/14f6c4bcc865-6591f15d-amend.hg (obsstore-off !)
145 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/14f6c4bcc865-6591f15d-amend.hg (obsstore-off !)
146 $ hg log -r . -T '{node|short} {desc}\n'
146 $ hg log -r . -T '{node|short} {desc}\n'
147 298f085230c3 EDITED: NEWMESSAGE
147 298f085230c3 EDITED: NEWMESSAGE
148 $ HGEDITOR="sh $TESTTMP/prefix.sh" hg amend -e -m MSG
148 $ HGEDITOR="sh $TESTTMP/prefix.sh" hg amend -e -m MSG
149 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/298f085230c3-d81a6ad3-amend.hg (obsstore-off !)
149 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/298f085230c3-d81a6ad3-amend.hg (obsstore-off !)
150 $ hg log -r . -T '{node|short} {desc}\n'
150 $ hg log -r . -T '{node|short} {desc}\n'
151 974f07f28537 EDITED: MSG
151 974f07f28537 EDITED: MSG
152
152
153 $ echo FOO > $TESTTMP/msg
153 $ echo FOO > $TESTTMP/msg
154 $ hg amend -l $TESTTMP/msg -m BAR
154 $ hg amend -l $TESTTMP/msg -m BAR
155 abort: cannot specify both --message and --logfile
155 abort: cannot specify both --message and --logfile
156 [10]
156 [10]
157 $ hg amend -l $TESTTMP/msg
157 $ hg amend -l $TESTTMP/msg
158 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/974f07f28537-edb6470a-amend.hg (obsstore-off !)
158 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/974f07f28537-edb6470a-amend.hg (obsstore-off !)
159 $ hg log -r . -T '{node|short} {desc}\n'
159 $ hg log -r . -T '{node|short} {desc}\n'
160 507be9bdac71 FOO
160 507be9bdac71 FOO
161
161
162 Interactive mode
162 Interactive mode
163
163
164 $ touch F G
164 $ touch F G
165 $ hg add F G
165 $ hg add F G
166 $ cat <<EOS | hg amend -i --config ui.interactive=1
166 $ cat <<EOS | hg amend -i --config ui.interactive=1
167 > y
167 > y
168 > n
168 > n
169 > EOS
169 > EOS
170 diff --git a/F b/F
170 diff --git a/F b/F
171 new file mode 100644
171 new file mode 100644
172 examine changes to 'F'?
172 examine changes to 'F'?
173 (enter ? for help) [Ynesfdaq?] y
173 (enter ? for help) [Ynesfdaq?] y
174
174
175 diff --git a/G b/G
175 diff --git a/G b/G
176 new file mode 100644
176 new file mode 100644
177 examine changes to 'G'?
177 examine changes to 'G'?
178 (enter ? for help) [Ynesfdaq?] n
178 (enter ? for help) [Ynesfdaq?] n
179
179
180 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/507be9bdac71-c8077452-amend.hg (obsstore-off !)
180 saved backup bundle to $TESTTMP/repo1/.hg/strip-backup/507be9bdac71-c8077452-amend.hg (obsstore-off !)
181 $ hg log -r . -T '{files}\n'
181 $ hg log -r . -T '{files}\n'
182 B D F
182 B D F
183
183
184 Amend in the middle of a stack
184 Amend in the middle of a stack
185
185
186 $ hg init $TESTTMP/repo2
186 $ hg init $TESTTMP/repo2
187 $ cd $TESTTMP/repo2
187 $ cd $TESTTMP/repo2
188 $ hg debugdrawdag <<'EOS'
188 $ hg debugdrawdag <<'EOS'
189 > C
189 > C
190 > |
190 > |
191 > B
191 > B
192 > |
192 > |
193 > A
193 > A
194 > EOS
194 > EOS
195
195
196 $ hg update -q B
196 $ hg update -q B
197 $ echo 2 >> B
197 $ echo 2 >> B
198 $ hg amend
198 $ hg amend
199 abort: cannot amend changeset, as that will orphan 1 descendants
199 abort: cannot amend changeset, as that will orphan 1 descendants
200 (see 'hg help evolution.instability')
200 (see 'hg help evolution.instability')
201 [10]
201 [10]
202
202
203 #if obsstore-on
203 #if obsstore-on
204
204
205 With allowunstable, amend could work in the middle of a stack
205 With allowunstable, amend could work in the middle of a stack
206
206
207 $ cat >> $HGRCPATH <<EOF
207 $ cat >> $HGRCPATH <<EOF
208 > [experimental]
208 > [experimental]
209 > evolution.createmarkers=True
209 > evolution.createmarkers=True
210 > evolution.allowunstable=True
210 > evolution.allowunstable=True
211 > EOF
211 > EOF
212
212
213 $ hg amend
213 $ hg amend
214 1 new orphan changesets
214 1 new orphan changesets
215 $ hg log -T '{rev} {node|short} {desc}\n' -G
215 $ hg log -T '{rev} {node|short} {desc}\n' -G
216 @ 3 be169c7e8dbe B
216 @ 3 be169c7e8dbe B
217 |
217 |
218 | * 2 26805aba1e60 C
218 | * 2 26805aba1e60 C
219 | |
219 | |
220 | x 1 112478962961 B
220 | x 1 112478962961 B
221 |/
221 |/
222 o 0 426bada5c675 A
222 o 0 426bada5c675 A
223
223
224 Checking the note stored in the obsmarker
224 Checking the note stored in the obsmarker
225
225
226 $ echo foo > bar
226 $ echo foo > bar
227 $ hg add bar
227 $ hg add bar
228 $ hg amend --note 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
228 $ hg amend --note 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
229 abort: cannot store a note of more than 255 bytes
229 abort: cannot store a note of more than 255 bytes
230 [10]
230 [10]
231 $ hg amend --note "adding bar"
231 $ hg amend --note "adding bar"
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
235
236 Cannot cause divergence by default
236 Cannot cause divergence by default
237
237
238 $ hg co --hidden 1
238 $ hg co --hidden 1
239 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
239 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
240 $ hg amend -m divergent
240 $ hg amend -m divergent
241 abort: cannot amend 112478962961, as that creates content-divergence with 16084da537dd
241 abort: cannot amend 112478962961, as that creates content-divergence with 16084da537dd
242 (add --verbose for details or see 'hg help evolution.instability')
242 (add --verbose for details or see 'hg help evolution.instability')
243 [10]
243 [10]
244 $ hg amend -m divergent --verbose
244 $ hg amend -m divergent --verbose
245 abort: cannot amend 112478962961, as that creates content-divergence with 16084da537dd
245 abort: cannot amend 112478962961, as that creates content-divergence with 16084da537dd
246 changeset 112478962961 already has a successor in changeset 16084da537dd
246 changeset 112478962961 already has a successor in changeset 16084da537dd
247 rewriting changeset 112478962961 would create "content-divergence"
247 rewriting changeset 112478962961 would create "content-divergence"
248 set experimental.evolution.allowdivergence=True to skip this check
248 set experimental.evolution.allowdivergence=True to skip this check
249 (see 'hg help evolution.instability' for details on content-divergence)
249 (see 'hg help evolution.instability' for details on content-divergence)
250 [10]
250 [10]
251 $ hg amend -m divergent --config experimental.evolution.allowdivergence=true
251 $ hg amend -m divergent --config experimental.evolution.allowdivergence=true
252 2 new content-divergent changesets
252 2 new content-divergent changesets
253
253
254 Hidden common predecessor of divergence does not cause crash
254 Hidden common predecessor of divergence does not cause crash
255
255
256 First create C1 as a pruned successor of C
256 First create C1 as a pruned successor of C
257 $ hg co C
257 $ hg co C
258 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
259 $ hg amend -m C1
259 $ hg amend -m C1
260 $ hg tag --local C1
260 $ hg tag --local C1
261 $ hg debugobsolete $(hg log -T '{node}' -r C1)
261 $ hg debugobsolete $(hg log -T '{node}' -r C1)
262 1 new obsolescence markers
262 1 new obsolescence markers
263 obsoleted 1 changesets
263 obsoleted 1 changesets
264 Now create C2 as other side of divergence (not actually divergent because C1 is
264 Now create C2 as other side of divergence (not actually divergent because C1 is
265 pruned)
265 pruned)
266 $ hg co C
266 $ hg co C
267 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 $ hg amend -m C2
268 $ hg amend -m C2
269 1 new orphan changesets
269 1 new orphan changesets
270 Make the common predecessor (C) pruned
270 Make the common predecessor (C) pruned
271 $ hg tag --local --remove C
271 $ hg tag --local --remove C
272 $ hg co C1
272 $ hg co C1
273 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
273 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
274 Try to cause divergence
274 Try to cause divergence
275 $ hg amend -m C11
275 $ hg amend -m C11
276 abort: filtered revision '26805aba1e600a82e93661149f2313866a221a7b' (known-bad-output !)
276 abort: cannot amend 2758767f5d17, as that creates content-divergence with bfcb433a0dea, from 26805aba1e60
277 [255]
277 (add --verbose for details or see 'hg help evolution.instability')
278 [10]
278 [10]
279 #endif
279 #endif
280
280
281 Cannot amend public changeset
281 Cannot amend public changeset
282
282
283 $ hg phase -r A --public
283 $ hg phase -r A --public
284 $ hg update -C -q A
284 $ hg update -C -q A
285 $ hg amend -m AMEND
285 $ hg amend -m AMEND
286 abort: cannot amend public changesets: 426bada5c675
286 abort: cannot amend public changesets: 426bada5c675
287 (see 'hg help phases' for details)
287 (see 'hg help phases' for details)
288 [10]
288 [10]
289
289
290 Amend a merge changeset
290 Amend a merge changeset
291
291
292 $ hg init $TESTTMP/repo3
292 $ hg init $TESTTMP/repo3
293 $ cd $TESTTMP/repo3
293 $ cd $TESTTMP/repo3
294 $ hg debugdrawdag <<'EOS'
294 $ hg debugdrawdag <<'EOS'
295 > C
295 > C
296 > /|
296 > /|
297 > A B
297 > A B
298 > EOS
298 > EOS
299 $ hg update -q C
299 $ hg update -q C
300 $ hg amend -m FOO
300 $ hg amend -m FOO
301 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/a35c07e8a2a4-15ff4612-amend.hg (obsstore-off !)
301 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/a35c07e8a2a4-15ff4612-amend.hg (obsstore-off !)
302 $ rm .hg/localtags
302 $ rm .hg/localtags
303 $ hg log -G -T '{desc}\n'
303 $ hg log -G -T '{desc}\n'
304 @ FOO
304 @ FOO
305 |\
305 |\
306 | o B
306 | o B
307 |
307 |
308 o A
308 o A
309
309
310
310
311 More complete test for status changes (issue5732)
311 More complete test for status changes (issue5732)
312 -------------------------------------------------
312 -------------------------------------------------
313
313
314 Generates history of files having 3 states, r0_r1_wc:
314 Generates history of files having 3 states, r0_r1_wc:
315
315
316 r0: ground (content/missing)
316 r0: ground (content/missing)
317 r1: old state to be amended (content/missing, where missing means removed)
317 r1: old state to be amended (content/missing, where missing means removed)
318 wc: changes to be included in r1 (content/missing-tracked/untracked)
318 wc: changes to be included in r1 (content/missing-tracked/untracked)
319
319
320 $ hg init $TESTTMP/wcstates
320 $ hg init $TESTTMP/wcstates
321 $ cd $TESTTMP/wcstates
321 $ cd $TESTTMP/wcstates
322
322
323 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
323 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
324 $ hg addremove -q --similarity 0
324 $ hg addremove -q --similarity 0
325 $ hg commit -m0
325 $ hg commit -m0
326
326
327 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
327 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
328 $ hg addremove -q --similarity 0
328 $ hg addremove -q --similarity 0
329 $ hg commit -m1
329 $ hg commit -m1
330
330
331 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
331 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
332 $ hg addremove -q --similarity 0
332 $ hg addremove -q --similarity 0
333 $ hg forget *_*_*-untracked
333 $ hg forget *_*_*-untracked
334 $ rm *_*_missing-*
334 $ rm *_*_missing-*
335
335
336 amend r1 to include wc changes
336 amend r1 to include wc changes
337
337
338 $ hg amend
338 $ hg amend
339 saved backup bundle to * (glob) (obsstore-off !)
339 saved backup bundle to * (glob) (obsstore-off !)
340
340
341 clean/modified/removed/added states of the amended revision
341 clean/modified/removed/added states of the amended revision
342
342
343 $ hg status --all --change . 'glob:content1_*_content1-tracked'
343 $ hg status --all --change . 'glob:content1_*_content1-tracked'
344 C content1_content1_content1-tracked
344 C content1_content1_content1-tracked
345 C content1_content2_content1-tracked
345 C content1_content2_content1-tracked
346 C content1_missing_content1-tracked
346 C content1_missing_content1-tracked
347 $ hg status --all --change . 'glob:content1_*_content[23]-tracked'
347 $ hg status --all --change . 'glob:content1_*_content[23]-tracked'
348 M content1_content1_content3-tracked
348 M content1_content1_content3-tracked
349 M content1_content2_content2-tracked
349 M content1_content2_content2-tracked
350 M content1_content2_content3-tracked
350 M content1_content2_content3-tracked
351 M content1_missing_content3-tracked
351 M content1_missing_content3-tracked
352 $ hg status --all --change . 'glob:content1_*_missing-tracked'
352 $ hg status --all --change . 'glob:content1_*_missing-tracked'
353 M content1_content2_missing-tracked
353 M content1_content2_missing-tracked
354 R content1_missing_missing-tracked
354 R content1_missing_missing-tracked
355 C content1_content1_missing-tracked
355 C content1_content1_missing-tracked
356 $ hg status --all --change . 'glob:content1_*_*-untracked'
356 $ hg status --all --change . 'glob:content1_*_*-untracked'
357 R content1_content1_content1-untracked
357 R content1_content1_content1-untracked
358 R content1_content1_content3-untracked
358 R content1_content1_content3-untracked
359 R content1_content1_missing-untracked
359 R content1_content1_missing-untracked
360 R content1_content2_content1-untracked
360 R content1_content2_content1-untracked
361 R content1_content2_content2-untracked
361 R content1_content2_content2-untracked
362 R content1_content2_content3-untracked
362 R content1_content2_content3-untracked
363 R content1_content2_missing-untracked
363 R content1_content2_missing-untracked
364 R content1_missing_content1-untracked
364 R content1_missing_content1-untracked
365 R content1_missing_content3-untracked
365 R content1_missing_content3-untracked
366 R content1_missing_missing-untracked
366 R content1_missing_missing-untracked
367 $ hg status --all --change . 'glob:missing_content2_*'
367 $ hg status --all --change . 'glob:missing_content2_*'
368 A missing_content2_content2-tracked
368 A missing_content2_content2-tracked
369 A missing_content2_content3-tracked
369 A missing_content2_content3-tracked
370 A missing_content2_missing-tracked
370 A missing_content2_missing-tracked
371 $ hg status --all --change . 'glob:missing_missing_*'
371 $ hg status --all --change . 'glob:missing_missing_*'
372 A missing_missing_content3-tracked
372 A missing_missing_content3-tracked
373
373
374 working directory should be all clean (with some missing/untracked files)
374 working directory should be all clean (with some missing/untracked files)
375
375
376 $ hg status --all 'glob:*_content?-tracked'
376 $ hg status --all 'glob:*_content?-tracked'
377 C content1_content1_content1-tracked
377 C content1_content1_content1-tracked
378 C content1_content1_content3-tracked
378 C content1_content1_content3-tracked
379 C content1_content2_content1-tracked
379 C content1_content2_content1-tracked
380 C content1_content2_content2-tracked
380 C content1_content2_content2-tracked
381 C content1_content2_content3-tracked
381 C content1_content2_content3-tracked
382 C content1_missing_content1-tracked
382 C content1_missing_content1-tracked
383 C content1_missing_content3-tracked
383 C content1_missing_content3-tracked
384 C missing_content2_content2-tracked
384 C missing_content2_content2-tracked
385 C missing_content2_content3-tracked
385 C missing_content2_content3-tracked
386 C missing_missing_content3-tracked
386 C missing_missing_content3-tracked
387 $ hg status --all 'glob:*_missing-tracked'
387 $ hg status --all 'glob:*_missing-tracked'
388 ! content1_content1_missing-tracked
388 ! content1_content1_missing-tracked
389 ! content1_content2_missing-tracked
389 ! content1_content2_missing-tracked
390 ! content1_missing_missing-tracked
390 ! content1_missing_missing-tracked
391 ! missing_content2_missing-tracked
391 ! missing_content2_missing-tracked
392 ! missing_missing_missing-tracked
392 ! missing_missing_missing-tracked
393 $ hg status --all 'glob:*-untracked'
393 $ hg status --all 'glob:*-untracked'
394 ? content1_content1_content1-untracked
394 ? content1_content1_content1-untracked
395 ? content1_content1_content3-untracked
395 ? content1_content1_content3-untracked
396 ? content1_content2_content1-untracked
396 ? content1_content2_content1-untracked
397 ? content1_content2_content2-untracked
397 ? content1_content2_content2-untracked
398 ? content1_content2_content3-untracked
398 ? content1_content2_content3-untracked
399 ? content1_missing_content1-untracked
399 ? content1_missing_content1-untracked
400 ? content1_missing_content3-untracked
400 ? content1_missing_content3-untracked
401 ? missing_content2_content2-untracked
401 ? missing_content2_content2-untracked
402 ? missing_content2_content3-untracked
402 ? missing_content2_content3-untracked
403 ? missing_missing_content3-untracked
403 ? missing_missing_content3-untracked
404
404
405 =================================
405 =================================
406 Test backup-bundle config option|
406 Test backup-bundle config option|
407 =================================
407 =================================
408 $ hg init $TESTTMP/repo4
408 $ hg init $TESTTMP/repo4
409 $ cd $TESTTMP/repo4
409 $ cd $TESTTMP/repo4
410 $ echo a>a
410 $ echo a>a
411 $ hg ci -Aqma
411 $ hg ci -Aqma
412 $ echo oops>b
412 $ echo oops>b
413 $ hg ci -Aqm "b"
413 $ hg ci -Aqm "b"
414 $ echo partiallyfixed > b
414 $ echo partiallyfixed > b
415
415
416 #if obsstore-off
416 #if obsstore-off
417 $ hg amend
417 $ hg amend
418 saved backup bundle to $TESTTMP/repo4/.hg/strip-backup/95e899acf2ce-f11cb050-amend.hg
418 saved backup bundle to $TESTTMP/repo4/.hg/strip-backup/95e899acf2ce-f11cb050-amend.hg
419 When backup-bundle config option is set:
419 When backup-bundle config option is set:
420 $ cat << EOF >> $HGRCPATH
420 $ cat << EOF >> $HGRCPATH
421 > [rewrite]
421 > [rewrite]
422 > backup-bundle = False
422 > backup-bundle = False
423 > EOF
423 > EOF
424 $ echo fixed > b
424 $ echo fixed > b
425 $ hg amend
425 $ hg amend
426
426
427 #else
427 #else
428 $ hg amend
428 $ hg amend
429 When backup-bundle config option is set:
429 When backup-bundle config option is set:
430 $ cat << EOF >> $HGRCPATH
430 $ cat << EOF >> $HGRCPATH
431 > [rewrite]
431 > [rewrite]
432 > backup-bundle = False
432 > backup-bundle = False
433 > EOF
433 > EOF
434 $ echo fixed > b
434 $ echo fixed > b
435 $ hg amend
435 $ hg amend
436
436
437 #endif
437 #endif
438 ==========================================
438 ==========================================
439 Test update-timestamp config option|
439 Test update-timestamp config option|
440 ==========================================
440 ==========================================
441
441
442 $ cat >> $HGRCPATH << EOF
442 $ cat >> $HGRCPATH << EOF
443 > [extensions]
443 > [extensions]
444 > amend=
444 > amend=
445 > mockmakedate = $TESTDIR/mockmakedate.py
445 > mockmakedate = $TESTDIR/mockmakedate.py
446 > EOF
446 > EOF
447
447
448 $ hg init $TESTTMP/repo5
448 $ hg init $TESTTMP/repo5
449 $ cd $TESTTMP/repo5
449 $ cd $TESTTMP/repo5
450 $ cat <<'EOF' >> .hg/hgrc
450 $ cat <<'EOF' >> .hg/hgrc
451 > [command-templates]
451 > [command-templates]
452 > log = 'user: {user}
452 > log = 'user: {user}
453 > date: {date|date}
453 > date: {date|date}
454 > summary: {desc|firstline}\n'
454 > summary: {desc|firstline}\n'
455 > EOF
455 > EOF
456
456
457 $ echo a>a
457 $ echo a>a
458 $ hg ci -Am 'commit 1'
458 $ hg ci -Am 'commit 1'
459 adding a
459 adding a
460
460
461 When updatetimestamp is False
461 When updatetimestamp is False
462
462
463 $ hg amend --date '1997-1-1 0:1'
463 $ hg amend --date '1997-1-1 0:1'
464 $ hg log --limit 1
464 $ hg log --limit 1
465 user: test
465 user: test
466 date: Wed Jan 01 00:01:00 1997 +0000
466 date: Wed Jan 01 00:01:00 1997 +0000
467 summary: commit 1
467 summary: commit 1
468
468
469 When update-timestamp is True and no other change than the date
469 When update-timestamp is True and no other change than the date
470
470
471 $ hg amend --config rewrite.update-timestamp=True
471 $ hg amend --config rewrite.update-timestamp=True
472 nothing changed
472 nothing changed
473 [1]
473 [1]
474 $ hg log --limit 1
474 $ hg log --limit 1
475 user: test
475 user: test
476 date: Wed Jan 01 00:01:00 1997 +0000
476 date: Wed Jan 01 00:01:00 1997 +0000
477 summary: commit 1
477 summary: commit 1
478
478
479 When update-timestamp is True and there is other change than the date
479 When update-timestamp is True and there is other change than the date
480 $ hg amend --user foobar --config rewrite.update-timestamp=True
480 $ hg amend --user foobar --config rewrite.update-timestamp=True
481 $ hg log --limit 1
481 $ hg log --limit 1
482 user: foobar
482 user: foobar
483 date: Thu Jan 01 00:00:02 1970 +0000
483 date: Thu Jan 01 00:00:02 1970 +0000
484 summary: commit 1
484 summary: commit 1
485
485
486 When date option is applicable and update-timestamp is True
486 When date option is applicable and update-timestamp is True
487 $ hg amend --date '1998-1-1 0:1' --config rewrite.update-timestamp=True
487 $ hg amend --date '1998-1-1 0:1' --config rewrite.update-timestamp=True
488 $ hg log --limit 1
488 $ hg log --limit 1
489 user: foobar
489 user: foobar
490 date: Thu Jan 01 00:01:00 1998 +0000
490 date: Thu Jan 01 00:01:00 1998 +0000
491 summary: commit 1
491 summary: commit 1
492
492
493 Unlike rewrite.update-timestamp, -D/--currentdate always updates the timestamp
493 Unlike rewrite.update-timestamp, -D/--currentdate always updates the timestamp
494
494
495 $ hg amend -D
495 $ hg amend -D
496 $ hg log --limit 1
496 $ hg log --limit 1
497 user: foobar
497 user: foobar
498 date: Thu Jan 01 00:00:04 1970 +0000
498 date: Thu Jan 01 00:00:04 1970 +0000
499 summary: commit 1
499 summary: commit 1
500
500
501 $ hg amend -D --config rewrite.update-timestamp=True
501 $ hg amend -D --config rewrite.update-timestamp=True
502 $ hg log --limit 1
502 $ hg log --limit 1
503 user: foobar
503 user: foobar
504 date: Thu Jan 01 00:00:05 1970 +0000
504 date: Thu Jan 01 00:00:05 1970 +0000
505 summary: commit 1
505 summary: commit 1
506
506
507 rewrite.update-timestamp can be negated by --no-currentdate
507 rewrite.update-timestamp can be negated by --no-currentdate
508
508
509 $ hg amend --config rewrite.update-timestamp=True --no-currentdate -u baz
509 $ hg amend --config rewrite.update-timestamp=True --no-currentdate -u baz
510 $ hg log --limit 1
510 $ hg log --limit 1
511 user: baz
511 user: baz
512 date: Thu Jan 01 00:00:05 1970 +0000
512 date: Thu Jan 01 00:00:05 1970 +0000
513 summary: commit 1
513 summary: commit 1
514
514
515 Bad combination of date options:
515 Bad combination of date options:
516
516
517 $ hg amend -D --date '0 0'
517 $ hg amend -D --date '0 0'
518 abort: cannot specify both --date and --currentdate
518 abort: cannot specify both --date and --currentdate
519 [10]
519 [10]
520
520
521 Close branch
521 Close branch
522
522
523 $ hg amend --secret --close-branch
523 $ hg amend --secret --close-branch
524 $ hg log --limit 1 -T 'close={get(extras, "close")}\nphase={phase}\n'
524 $ hg log --limit 1 -T 'close={get(extras, "close")}\nphase={phase}\n'
525 close=1
525 close=1
526 phase=secret
526 phase=secret
527
527
528 $ cd ..
528 $ cd ..
529
529
530 Corner case of amend from issue6157:
530 Corner case of amend from issue6157:
531 - working copy parent has a change to file `a`
531 - working copy parent has a change to file `a`
532 - working copy has the inverse change
532 - working copy has the inverse change
533 - we amend the working copy parent for files other than `a`
533 - we amend the working copy parent for files other than `a`
534 hg used to include the changes to `a` anyway.
534 hg used to include the changes to `a` anyway.
535
535
536 $ hg init 6157; cd 6157
536 $ hg init 6157; cd 6157
537 $ echo a > a; echo b > b; hg commit -qAm_
537 $ echo a > a; echo b > b; hg commit -qAm_
538 $ echo a2 > a; hg commit -qm_
538 $ echo a2 > a; hg commit -qm_
539 $ hg diff --stat -c .
539 $ hg diff --stat -c .
540 a | 2 +-
540 a | 2 +-
541 1 files changed, 1 insertions(+), 1 deletions(-)
541 1 files changed, 1 insertions(+), 1 deletions(-)
542 $ echo a > a; echo b2 > b; hg amend -q b
542 $ echo a > a; echo b2 > b; hg amend -q b
543 $ hg diff --stat -c .
543 $ hg diff --stat -c .
544 a | 2 +-
544 a | 2 +-
545 b | 2 +-
545 b | 2 +-
546 2 files changed, 2 insertions(+), 2 deletions(-)
546 2 files changed, 2 insertions(+), 2 deletions(-)
547
547
548 Modifying a file while the editor is open can cause dirstate corruption
548 Modifying a file while the editor is open can cause dirstate corruption
549 (issue6233)
549 (issue6233)
550
550
551 $ cd $TESTTMP
551 $ cd $TESTTMP
552 $ hg init modify-during-amend; cd modify-during-amend
552 $ hg init modify-during-amend; cd modify-during-amend
553 $ echo r0 > foo; hg commit -qAm "r0"
553 $ echo r0 > foo; hg commit -qAm "r0"
554 $ echo alpha > foo; hg commit -qm "alpha"
554 $ echo alpha > foo; hg commit -qm "alpha"
555 $ echo beta >> foo
555 $ echo beta >> foo
556 $ cat > $TESTTMP/touchy_editor.sh <<EOF
556 $ cat > $TESTTMP/touchy_editor.sh <<EOF
557 > sleep 1
557 > sleep 1
558 > echo delta >> "$TESTTMP/modify-during-amend/foo"
558 > echo delta >> "$TESTTMP/modify-during-amend/foo"
559 > sleep 1
559 > sleep 1
560 > echo hi > "\$1"
560 > echo hi > "\$1"
561 > sleep 1
561 > sleep 1
562 > EOF
562 > EOF
563 $ HGEDITOR="sh $TESTTMP/touchy_editor.sh" hg commit --amend
563 $ HGEDITOR="sh $TESTTMP/touchy_editor.sh" hg commit --amend
564 $ if (hg diff -c . | grep 'delta' >/dev/null) || [ -n "$(hg status)" ]; then
564 $ if (hg diff -c . | grep 'delta' >/dev/null) || [ -n "$(hg status)" ]; then
565 > echo "OK."
565 > echo "OK."
566 > else
566 > else
567 > echo "Bug detected. 'delta' is not part of the commit OR the wdir"
567 > echo "Bug detected. 'delta' is not part of the commit OR the wdir"
568 > echo "Diff and status before rebuild:"
568 > echo "Diff and status before rebuild:"
569 > hg diff
569 > hg diff
570 > hg status
570 > hg status
571 > hg debugrebuilddirstate
571 > hg debugrebuilddirstate
572 > echo "Diff and status after rebuild:"
572 > echo "Diff and status after rebuild:"
573 > hg diff
573 > hg diff
574 > hg status
574 > hg status
575 > fi
575 > fi
576 OK.
576 OK.
General Comments 0
You need to be logged in to leave comments. Login now