##// END OF EJS Templates
rewriteutil: add pointer to help text when rewrite would cause divergence...
Martin von Zweigbergk -
r48166:8125bcd2 default
parent child Browse files
Show More
@@ -1,242 +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(msg)
114 raise error.InputError(
115 msg,
116 hint=_(
117 b"see 'hg help evolution.instability' for details on content-divergence"
118 ),
119 )
115 else:
120 else:
116 raise error.InputError(
121 raise error.InputError(
117 msg,
122 msg,
118 hint=_(
123 hint=_(
119 b"add --verbose for details or see "
124 b"add --verbose for details or see "
120 b"'hg help evolution.instability'"
125 b"'hg help evolution.instability'"
121 ),
126 ),
122 )
127 )
123
128
124
129
125 def disallowednewunstable(repo, revs):
130 def disallowednewunstable(repo, revs):
126 """Checks whether editing the revs will create new unstable changesets and
131 """Checks whether editing the revs will create new unstable changesets and
127 are we allowed to create them.
132 are we allowed to create them.
128
133
129 To allow new unstable changesets, set the config:
134 To allow new unstable changesets, set the config:
130 `experimental.evolution.allowunstable=True`
135 `experimental.evolution.allowunstable=True`
131 """
136 """
132 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
137 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
133 if allowunstable:
138 if allowunstable:
134 return revset.baseset()
139 return revset.baseset()
135 return repo.revs(b"(%ld::) - %ld", revs, revs)
140 return repo.revs(b"(%ld::) - %ld", revs, revs)
136
141
137
142
138 def _find_new_divergence(repo, revs):
143 def _find_new_divergence(repo, revs):
139 obsrevs = repo.revs(b'%ld and obsolete()', revs)
144 obsrevs = repo.revs(b'%ld and obsolete()', revs)
140 for r in obsrevs:
145 for r in obsrevs:
141 div = find_new_divergence_from(repo, repo[r])
146 div = find_new_divergence_from(repo, repo[r])
142 if div:
147 if div:
143 return (repo[r], repo[div[0]], repo[div[1]])
148 return (repo[r], repo[div[0]], repo[div[1]])
144 return None
149 return None
145
150
146
151
147 def find_new_divergence_from(repo, ctx):
152 def find_new_divergence_from(repo, ctx):
148 """return divergent revision if rewriting an obsolete cset (ctx) will
153 """return divergent revision if rewriting an obsolete cset (ctx) will
149 create divergence
154 create divergence
150
155
151 Returns (<other node>, <common ancestor node>) or None
156 Returns (<other node>, <common ancestor node>) or None
152 """
157 """
153 if not ctx.obsolete():
158 if not ctx.obsolete():
154 return None
159 return None
155 # We need to check two cases that can cause divergence:
160 # We need to check two cases that can cause divergence:
156 # 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
157 # detected by successorssets)
162 # detected by successorssets)
158 sset = obsutil.successorssets(repo, ctx.node())
163 sset = obsutil.successorssets(repo, ctx.node())
159 if sset:
164 if sset:
160 return (sset[0][0], ctx.node())
165 return (sset[0][0], ctx.node())
161 else:
166 else:
162 # 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
163 # non-obsolete successor (we need divergentsets for this)
168 # non-obsolete successor (we need divergentsets for this)
164 divsets = obsutil.divergentsets(repo, ctx)
169 divsets = obsutil.divergentsets(repo, ctx)
165 if divsets:
170 if divsets:
166 nsuccset = divsets[0][b'divergentnodes']
171 nsuccset = divsets[0][b'divergentnodes']
167 prec = divsets[0][b'commonpredecessor']
172 prec = divsets[0][b'commonpredecessor']
168 return (nsuccset[0], prec)
173 return (nsuccset[0], prec)
169 return None
174 return None
170
175
171
176
172 def skip_empty_successor(ui, command):
177 def skip_empty_successor(ui, command):
173 empty_successor = ui.config(b'rewrite', b'empty-successor')
178 empty_successor = ui.config(b'rewrite', b'empty-successor')
174 if empty_successor == b'skip':
179 if empty_successor == b'skip':
175 return True
180 return True
176 elif empty_successor == b'keep':
181 elif empty_successor == b'keep':
177 return False
182 return False
178 else:
183 else:
179 raise error.ConfigError(
184 raise error.ConfigError(
180 _(
185 _(
181 b"%s doesn't know how to handle config "
186 b"%s doesn't know how to handle config "
182 b"rewrite.empty-successor=%s (only 'skip' and 'keep' are "
187 b"rewrite.empty-successor=%s (only 'skip' and 'keep' are "
183 b"supported)"
188 b"supported)"
184 )
189 )
185 % (command, empty_successor)
190 % (command, empty_successor)
186 )
191 )
187
192
188
193
189 def update_hash_refs(repo, commitmsg, pending=None):
194 def update_hash_refs(repo, commitmsg, pending=None):
190 """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.
191
196
192 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
193 as there's no way to know which successor to choose.
198 as there's no way to know which successor to choose.
194
199
195 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
196 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
197 of ``pending[oldnode] = [successor_node1, successor_node2,..]``.
202 of ``pending[oldnode] = [successor_node1, successor_node2,..]``.
198 """
203 """
199 if not pending:
204 if not pending:
200 pending = {}
205 pending = {}
201 cache = {}
206 cache = {}
202 hashes = re.findall(NODE_RE, commitmsg)
207 hashes = re.findall(NODE_RE, commitmsg)
203 unfi = repo.unfiltered()
208 unfi = repo.unfiltered()
204 for h in hashes:
209 for h in hashes:
205 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
210 fullnode = scmutil.resolvehexnodeidprefix(unfi, h)
206 if fullnode is None:
211 if fullnode is None:
207 continue
212 continue
208 ctx = unfi[fullnode]
213 ctx = unfi[fullnode]
209 if not ctx.obsolete():
214 if not ctx.obsolete():
210 successors = pending.get(fullnode)
215 successors = pending.get(fullnode)
211 if successors is None:
216 if successors is None:
212 continue
217 continue
213 # obsutil.successorssets() returns a list of list of nodes
218 # obsutil.successorssets() returns a list of list of nodes
214 successors = [successors]
219 successors = [successors]
215 else:
220 else:
216 successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
221 successors = obsutil.successorssets(repo, ctx.node(), cache=cache)
217
222
218 # 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
219 # cset in question was split or diverged.
224 # cset in question was split or diverged.
220 if len(successors) == 1 and len(successors[0]) == 1:
225 if len(successors) == 1 and len(successors[0]) == 1:
221 successor = successors[0][0]
226 successor = successors[0][0]
222 if successor is not None:
227 if successor is not None:
223 newhash = hex(successor)
228 newhash = hex(successor)
224 commitmsg = commitmsg.replace(h, newhash[: len(h)])
229 commitmsg = commitmsg.replace(h, newhash[: len(h)])
225 else:
230 else:
226 repo.ui.note(
231 repo.ui.note(
227 _(
232 _(
228 b'The stale commit message reference to %s could '
233 b'The stale commit message reference to %s could '
229 b'not be updated\n(The referenced commit was dropped)\n'
234 b'not be updated\n(The referenced commit was dropped)\n'
230 )
235 )
231 % h
236 % h
232 )
237 )
233 else:
238 else:
234 repo.ui.note(
239 repo.ui.note(
235 _(
240 _(
236 b'The stale commit message reference to %s could '
241 b'The stale commit message reference to %s could '
237 b'not be updated\n'
242 b'not be updated\n'
238 )
243 )
239 % h
244 % h
240 )
245 )
241
246
242 return commitmsg
247 return commitmsg
@@ -1,543 +1,550 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
245 abort: cannot amend 112478962961, as that creates content-divergence with 16084da537dd
246 changeset 112478962961 already has a successor in changeset 16084da537dd
247 rewriting changeset 112478962961 would create "content-divergence"
248 set experimental.evolution.allowdivergence=True to skip this check
249 (see 'hg help evolution.instability' for details on content-divergence)
250 [10]
244 $ hg amend -m divergent --config experimental.evolution.allowdivergence=true
251 $ hg amend -m divergent --config experimental.evolution.allowdivergence=true
245 2 new content-divergent changesets
252 2 new content-divergent changesets
246 #endif
253 #endif
247
254
248 Cannot amend public changeset
255 Cannot amend public changeset
249
256
250 $ hg phase -r A --public
257 $ hg phase -r A --public
251 $ hg update -C -q A
258 $ hg update -C -q A
252 $ hg amend -m AMEND
259 $ hg amend -m AMEND
253 abort: cannot amend public changesets: 426bada5c675
260 abort: cannot amend public changesets: 426bada5c675
254 (see 'hg help phases' for details)
261 (see 'hg help phases' for details)
255 [10]
262 [10]
256
263
257 Amend a merge changeset
264 Amend a merge changeset
258
265
259 $ hg init $TESTTMP/repo3
266 $ hg init $TESTTMP/repo3
260 $ cd $TESTTMP/repo3
267 $ cd $TESTTMP/repo3
261 $ hg debugdrawdag <<'EOS'
268 $ hg debugdrawdag <<'EOS'
262 > C
269 > C
263 > /|
270 > /|
264 > A B
271 > A B
265 > EOS
272 > EOS
266 $ hg update -q C
273 $ hg update -q C
267 $ hg amend -m FOO
274 $ hg amend -m FOO
268 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/a35c07e8a2a4-15ff4612-amend.hg (obsstore-off !)
275 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/a35c07e8a2a4-15ff4612-amend.hg (obsstore-off !)
269 $ rm .hg/localtags
276 $ rm .hg/localtags
270 $ hg log -G -T '{desc}\n'
277 $ hg log -G -T '{desc}\n'
271 @ FOO
278 @ FOO
272 |\
279 |\
273 | o B
280 | o B
274 |
281 |
275 o A
282 o A
276
283
277
284
278 More complete test for status changes (issue5732)
285 More complete test for status changes (issue5732)
279 -------------------------------------------------
286 -------------------------------------------------
280
287
281 Generates history of files having 3 states, r0_r1_wc:
288 Generates history of files having 3 states, r0_r1_wc:
282
289
283 r0: ground (content/missing)
290 r0: ground (content/missing)
284 r1: old state to be amended (content/missing, where missing means removed)
291 r1: old state to be amended (content/missing, where missing means removed)
285 wc: changes to be included in r1 (content/missing-tracked/untracked)
292 wc: changes to be included in r1 (content/missing-tracked/untracked)
286
293
287 $ hg init $TESTTMP/wcstates
294 $ hg init $TESTTMP/wcstates
288 $ cd $TESTTMP/wcstates
295 $ cd $TESTTMP/wcstates
289
296
290 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
297 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
291 $ hg addremove -q --similarity 0
298 $ hg addremove -q --similarity 0
292 $ hg commit -m0
299 $ hg commit -m0
293
300
294 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
301 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
295 $ hg addremove -q --similarity 0
302 $ hg addremove -q --similarity 0
296 $ hg commit -m1
303 $ hg commit -m1
297
304
298 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
305 $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
299 $ hg addremove -q --similarity 0
306 $ hg addremove -q --similarity 0
300 $ hg forget *_*_*-untracked
307 $ hg forget *_*_*-untracked
301 $ rm *_*_missing-*
308 $ rm *_*_missing-*
302
309
303 amend r1 to include wc changes
310 amend r1 to include wc changes
304
311
305 $ hg amend
312 $ hg amend
306 saved backup bundle to * (glob) (obsstore-off !)
313 saved backup bundle to * (glob) (obsstore-off !)
307
314
308 clean/modified/removed/added states of the amended revision
315 clean/modified/removed/added states of the amended revision
309
316
310 $ hg status --all --change . 'glob:content1_*_content1-tracked'
317 $ hg status --all --change . 'glob:content1_*_content1-tracked'
311 C content1_content1_content1-tracked
318 C content1_content1_content1-tracked
312 C content1_content2_content1-tracked
319 C content1_content2_content1-tracked
313 C content1_missing_content1-tracked
320 C content1_missing_content1-tracked
314 $ hg status --all --change . 'glob:content1_*_content[23]-tracked'
321 $ hg status --all --change . 'glob:content1_*_content[23]-tracked'
315 M content1_content1_content3-tracked
322 M content1_content1_content3-tracked
316 M content1_content2_content2-tracked
323 M content1_content2_content2-tracked
317 M content1_content2_content3-tracked
324 M content1_content2_content3-tracked
318 M content1_missing_content3-tracked
325 M content1_missing_content3-tracked
319 $ hg status --all --change . 'glob:content1_*_missing-tracked'
326 $ hg status --all --change . 'glob:content1_*_missing-tracked'
320 M content1_content2_missing-tracked
327 M content1_content2_missing-tracked
321 R content1_missing_missing-tracked
328 R content1_missing_missing-tracked
322 C content1_content1_missing-tracked
329 C content1_content1_missing-tracked
323 $ hg status --all --change . 'glob:content1_*_*-untracked'
330 $ hg status --all --change . 'glob:content1_*_*-untracked'
324 R content1_content1_content1-untracked
331 R content1_content1_content1-untracked
325 R content1_content1_content3-untracked
332 R content1_content1_content3-untracked
326 R content1_content1_missing-untracked
333 R content1_content1_missing-untracked
327 R content1_content2_content1-untracked
334 R content1_content2_content1-untracked
328 R content1_content2_content2-untracked
335 R content1_content2_content2-untracked
329 R content1_content2_content3-untracked
336 R content1_content2_content3-untracked
330 R content1_content2_missing-untracked
337 R content1_content2_missing-untracked
331 R content1_missing_content1-untracked
338 R content1_missing_content1-untracked
332 R content1_missing_content3-untracked
339 R content1_missing_content3-untracked
333 R content1_missing_missing-untracked
340 R content1_missing_missing-untracked
334 $ hg status --all --change . 'glob:missing_content2_*'
341 $ hg status --all --change . 'glob:missing_content2_*'
335 A missing_content2_content2-tracked
342 A missing_content2_content2-tracked
336 A missing_content2_content3-tracked
343 A missing_content2_content3-tracked
337 A missing_content2_missing-tracked
344 A missing_content2_missing-tracked
338 $ hg status --all --change . 'glob:missing_missing_*'
345 $ hg status --all --change . 'glob:missing_missing_*'
339 A missing_missing_content3-tracked
346 A missing_missing_content3-tracked
340
347
341 working directory should be all clean (with some missing/untracked files)
348 working directory should be all clean (with some missing/untracked files)
342
349
343 $ hg status --all 'glob:*_content?-tracked'
350 $ hg status --all 'glob:*_content?-tracked'
344 C content1_content1_content1-tracked
351 C content1_content1_content1-tracked
345 C content1_content1_content3-tracked
352 C content1_content1_content3-tracked
346 C content1_content2_content1-tracked
353 C content1_content2_content1-tracked
347 C content1_content2_content2-tracked
354 C content1_content2_content2-tracked
348 C content1_content2_content3-tracked
355 C content1_content2_content3-tracked
349 C content1_missing_content1-tracked
356 C content1_missing_content1-tracked
350 C content1_missing_content3-tracked
357 C content1_missing_content3-tracked
351 C missing_content2_content2-tracked
358 C missing_content2_content2-tracked
352 C missing_content2_content3-tracked
359 C missing_content2_content3-tracked
353 C missing_missing_content3-tracked
360 C missing_missing_content3-tracked
354 $ hg status --all 'glob:*_missing-tracked'
361 $ hg status --all 'glob:*_missing-tracked'
355 ! content1_content1_missing-tracked
362 ! content1_content1_missing-tracked
356 ! content1_content2_missing-tracked
363 ! content1_content2_missing-tracked
357 ! content1_missing_missing-tracked
364 ! content1_missing_missing-tracked
358 ! missing_content2_missing-tracked
365 ! missing_content2_missing-tracked
359 ! missing_missing_missing-tracked
366 ! missing_missing_missing-tracked
360 $ hg status --all 'glob:*-untracked'
367 $ hg status --all 'glob:*-untracked'
361 ? content1_content1_content1-untracked
368 ? content1_content1_content1-untracked
362 ? content1_content1_content3-untracked
369 ? content1_content1_content3-untracked
363 ? content1_content2_content1-untracked
370 ? content1_content2_content1-untracked
364 ? content1_content2_content2-untracked
371 ? content1_content2_content2-untracked
365 ? content1_content2_content3-untracked
372 ? content1_content2_content3-untracked
366 ? content1_missing_content1-untracked
373 ? content1_missing_content1-untracked
367 ? content1_missing_content3-untracked
374 ? content1_missing_content3-untracked
368 ? missing_content2_content2-untracked
375 ? missing_content2_content2-untracked
369 ? missing_content2_content3-untracked
376 ? missing_content2_content3-untracked
370 ? missing_missing_content3-untracked
377 ? missing_missing_content3-untracked
371
378
372 =================================
379 =================================
373 Test backup-bundle config option|
380 Test backup-bundle config option|
374 =================================
381 =================================
375 $ hg init $TESTTMP/repo4
382 $ hg init $TESTTMP/repo4
376 $ cd $TESTTMP/repo4
383 $ cd $TESTTMP/repo4
377 $ echo a>a
384 $ echo a>a
378 $ hg ci -Aqma
385 $ hg ci -Aqma
379 $ echo oops>b
386 $ echo oops>b
380 $ hg ci -Aqm "b"
387 $ hg ci -Aqm "b"
381 $ echo partiallyfixed > b
388 $ echo partiallyfixed > b
382
389
383 #if obsstore-off
390 #if obsstore-off
384 $ hg amend
391 $ hg amend
385 saved backup bundle to $TESTTMP/repo4/.hg/strip-backup/95e899acf2ce-f11cb050-amend.hg
392 saved backup bundle to $TESTTMP/repo4/.hg/strip-backup/95e899acf2ce-f11cb050-amend.hg
386 When backup-bundle config option is set:
393 When backup-bundle config option is set:
387 $ cat << EOF >> $HGRCPATH
394 $ cat << EOF >> $HGRCPATH
388 > [rewrite]
395 > [rewrite]
389 > backup-bundle = False
396 > backup-bundle = False
390 > EOF
397 > EOF
391 $ echo fixed > b
398 $ echo fixed > b
392 $ hg amend
399 $ hg amend
393
400
394 #else
401 #else
395 $ hg amend
402 $ hg amend
396 When backup-bundle config option is set:
403 When backup-bundle config option is set:
397 $ cat << EOF >> $HGRCPATH
404 $ cat << EOF >> $HGRCPATH
398 > [rewrite]
405 > [rewrite]
399 > backup-bundle = False
406 > backup-bundle = False
400 > EOF
407 > EOF
401 $ echo fixed > b
408 $ echo fixed > b
402 $ hg amend
409 $ hg amend
403
410
404 #endif
411 #endif
405 ==========================================
412 ==========================================
406 Test update-timestamp config option|
413 Test update-timestamp config option|
407 ==========================================
414 ==========================================
408
415
409 $ cat >> $HGRCPATH << EOF
416 $ cat >> $HGRCPATH << EOF
410 > [extensions]
417 > [extensions]
411 > amend=
418 > amend=
412 > mockmakedate = $TESTDIR/mockmakedate.py
419 > mockmakedate = $TESTDIR/mockmakedate.py
413 > EOF
420 > EOF
414
421
415 $ hg init $TESTTMP/repo5
422 $ hg init $TESTTMP/repo5
416 $ cd $TESTTMP/repo5
423 $ cd $TESTTMP/repo5
417 $ cat <<'EOF' >> .hg/hgrc
424 $ cat <<'EOF' >> .hg/hgrc
418 > [command-templates]
425 > [command-templates]
419 > log = 'user: {user}
426 > log = 'user: {user}
420 > date: {date|date}
427 > date: {date|date}
421 > summary: {desc|firstline}\n'
428 > summary: {desc|firstline}\n'
422 > EOF
429 > EOF
423
430
424 $ echo a>a
431 $ echo a>a
425 $ hg ci -Am 'commit 1'
432 $ hg ci -Am 'commit 1'
426 adding a
433 adding a
427
434
428 When updatetimestamp is False
435 When updatetimestamp is False
429
436
430 $ hg amend --date '1997-1-1 0:1'
437 $ hg amend --date '1997-1-1 0:1'
431 $ hg log --limit 1
438 $ hg log --limit 1
432 user: test
439 user: test
433 date: Wed Jan 01 00:01:00 1997 +0000
440 date: Wed Jan 01 00:01:00 1997 +0000
434 summary: commit 1
441 summary: commit 1
435
442
436 When update-timestamp is True and no other change than the date
443 When update-timestamp is True and no other change than the date
437
444
438 $ hg amend --config rewrite.update-timestamp=True
445 $ hg amend --config rewrite.update-timestamp=True
439 nothing changed
446 nothing changed
440 [1]
447 [1]
441 $ hg log --limit 1
448 $ hg log --limit 1
442 user: test
449 user: test
443 date: Wed Jan 01 00:01:00 1997 +0000
450 date: Wed Jan 01 00:01:00 1997 +0000
444 summary: commit 1
451 summary: commit 1
445
452
446 When update-timestamp is True and there is other change than the date
453 When update-timestamp is True and there is other change than the date
447 $ hg amend --user foobar --config rewrite.update-timestamp=True
454 $ hg amend --user foobar --config rewrite.update-timestamp=True
448 $ hg log --limit 1
455 $ hg log --limit 1
449 user: foobar
456 user: foobar
450 date: Thu Jan 01 00:00:02 1970 +0000
457 date: Thu Jan 01 00:00:02 1970 +0000
451 summary: commit 1
458 summary: commit 1
452
459
453 When date option is applicable and update-timestamp is True
460 When date option is applicable and update-timestamp is True
454 $ hg amend --date '1998-1-1 0:1' --config rewrite.update-timestamp=True
461 $ hg amend --date '1998-1-1 0:1' --config rewrite.update-timestamp=True
455 $ hg log --limit 1
462 $ hg log --limit 1
456 user: foobar
463 user: foobar
457 date: Thu Jan 01 00:01:00 1998 +0000
464 date: Thu Jan 01 00:01:00 1998 +0000
458 summary: commit 1
465 summary: commit 1
459
466
460 Unlike rewrite.update-timestamp, -D/--currentdate always updates the timestamp
467 Unlike rewrite.update-timestamp, -D/--currentdate always updates the timestamp
461
468
462 $ hg amend -D
469 $ hg amend -D
463 $ hg log --limit 1
470 $ hg log --limit 1
464 user: foobar
471 user: foobar
465 date: Thu Jan 01 00:00:04 1970 +0000
472 date: Thu Jan 01 00:00:04 1970 +0000
466 summary: commit 1
473 summary: commit 1
467
474
468 $ hg amend -D --config rewrite.update-timestamp=True
475 $ hg amend -D --config rewrite.update-timestamp=True
469 $ hg log --limit 1
476 $ hg log --limit 1
470 user: foobar
477 user: foobar
471 date: Thu Jan 01 00:00:05 1970 +0000
478 date: Thu Jan 01 00:00:05 1970 +0000
472 summary: commit 1
479 summary: commit 1
473
480
474 rewrite.update-timestamp can be negated by --no-currentdate
481 rewrite.update-timestamp can be negated by --no-currentdate
475
482
476 $ hg amend --config rewrite.update-timestamp=True --no-currentdate -u baz
483 $ hg amend --config rewrite.update-timestamp=True --no-currentdate -u baz
477 $ hg log --limit 1
484 $ hg log --limit 1
478 user: baz
485 user: baz
479 date: Thu Jan 01 00:00:05 1970 +0000
486 date: Thu Jan 01 00:00:05 1970 +0000
480 summary: commit 1
487 summary: commit 1
481
488
482 Bad combination of date options:
489 Bad combination of date options:
483
490
484 $ hg amend -D --date '0 0'
491 $ hg amend -D --date '0 0'
485 abort: cannot specify both --date and --currentdate
492 abort: cannot specify both --date and --currentdate
486 [10]
493 [10]
487
494
488 Close branch
495 Close branch
489
496
490 $ hg amend --secret --close-branch
497 $ hg amend --secret --close-branch
491 $ hg log --limit 1 -T 'close={get(extras, "close")}\nphase={phase}\n'
498 $ hg log --limit 1 -T 'close={get(extras, "close")}\nphase={phase}\n'
492 close=1
499 close=1
493 phase=secret
500 phase=secret
494
501
495 $ cd ..
502 $ cd ..
496
503
497 Corner case of amend from issue6157:
504 Corner case of amend from issue6157:
498 - working copy parent has a change to file `a`
505 - working copy parent has a change to file `a`
499 - working copy has the inverse change
506 - working copy has the inverse change
500 - we amend the working copy parent for files other than `a`
507 - we amend the working copy parent for files other than `a`
501 hg used to include the changes to `a` anyway.
508 hg used to include the changes to `a` anyway.
502
509
503 $ hg init 6157; cd 6157
510 $ hg init 6157; cd 6157
504 $ echo a > a; echo b > b; hg commit -qAm_
511 $ echo a > a; echo b > b; hg commit -qAm_
505 $ echo a2 > a; hg commit -qm_
512 $ echo a2 > a; hg commit -qm_
506 $ hg diff --stat -c .
513 $ hg diff --stat -c .
507 a | 2 +-
514 a | 2 +-
508 1 files changed, 1 insertions(+), 1 deletions(-)
515 1 files changed, 1 insertions(+), 1 deletions(-)
509 $ echo a > a; echo b2 > b; hg amend -q b
516 $ echo a > a; echo b2 > b; hg amend -q b
510 $ hg diff --stat -c .
517 $ hg diff --stat -c .
511 a | 2 +-
518 a | 2 +-
512 b | 2 +-
519 b | 2 +-
513 2 files changed, 2 insertions(+), 2 deletions(-)
520 2 files changed, 2 insertions(+), 2 deletions(-)
514
521
515 Modifying a file while the editor is open can cause dirstate corruption
522 Modifying a file while the editor is open can cause dirstate corruption
516 (issue6233)
523 (issue6233)
517
524
518 $ cd $TESTTMP
525 $ cd $TESTTMP
519 $ hg init modify-during-amend; cd modify-during-amend
526 $ hg init modify-during-amend; cd modify-during-amend
520 $ echo r0 > foo; hg commit -qAm "r0"
527 $ echo r0 > foo; hg commit -qAm "r0"
521 $ echo alpha > foo; hg commit -qm "alpha"
528 $ echo alpha > foo; hg commit -qm "alpha"
522 $ echo beta >> foo
529 $ echo beta >> foo
523 $ cat > $TESTTMP/touchy_editor.sh <<EOF
530 $ cat > $TESTTMP/touchy_editor.sh <<EOF
524 > sleep 1
531 > sleep 1
525 > echo delta >> "$TESTTMP/modify-during-amend/foo"
532 > echo delta >> "$TESTTMP/modify-during-amend/foo"
526 > sleep 1
533 > sleep 1
527 > echo hi > "\$1"
534 > echo hi > "\$1"
528 > sleep 1
535 > sleep 1
529 > EOF
536 > EOF
530 $ HGEDITOR="sh $TESTTMP/touchy_editor.sh" hg commit --amend
537 $ HGEDITOR="sh $TESTTMP/touchy_editor.sh" hg commit --amend
531 $ if (hg diff -c . | grep 'delta' >/dev/null) || [ -n "$(hg status)" ]; then
538 $ if (hg diff -c . | grep 'delta' >/dev/null) || [ -n "$(hg status)" ]; then
532 > echo "OK."
539 > echo "OK."
533 > else
540 > else
534 > echo "Bug detected. 'delta' is not part of the commit OR the wdir"
541 > echo "Bug detected. 'delta' is not part of the commit OR the wdir"
535 > echo "Diff and status before rebuild:"
542 > echo "Diff and status before rebuild:"
536 > hg diff
543 > hg diff
537 > hg status
544 > hg status
538 > hg debugrebuilddirstate
545 > hg debugrebuilddirstate
539 > echo "Diff and status after rebuild:"
546 > echo "Diff and status after rebuild:"
540 > hg diff
547 > hg diff
541 > hg status
548 > hg status
542 > fi
549 > fi
543 OK.
550 OK.
General Comments 0
You need to be logged in to leave comments. Login now