##// END OF EJS Templates
histedit: make histedit prune when obsolete is enabled...
Durham Goode -
r26763:50fc80e4 default
parent child Browse files
Show More
@@ -1,1230 +1,1236 b''
1 # histedit.py - interactive history editing for mercurial
1 # histedit.py - interactive history editing for mercurial
2 #
2 #
3 # Copyright 2009 Augie Fackler <raf@durin42.com>
3 # Copyright 2009 Augie Fackler <raf@durin42.com>
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 """interactive history editing
7 """interactive history editing
8
8
9 With this extension installed, Mercurial gains one new command: histedit. Usage
9 With this extension installed, Mercurial gains one new command: histedit. Usage
10 is as follows, assuming the following history::
10 is as follows, assuming the following history::
11
11
12 @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42
12 @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42
13 | Add delta
13 | Add delta
14 |
14 |
15 o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42
15 o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42
16 | Add gamma
16 | Add gamma
17 |
17 |
18 o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42
18 o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42
19 | Add beta
19 | Add beta
20 |
20 |
21 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
21 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
22 Add alpha
22 Add alpha
23
23
24 If you were to run ``hg histedit c561b4e977df``, you would see the following
24 If you were to run ``hg histedit c561b4e977df``, you would see the following
25 file open in your editor::
25 file open in your editor::
26
26
27 pick c561b4e977df Add beta
27 pick c561b4e977df Add beta
28 pick 030b686bedc4 Add gamma
28 pick 030b686bedc4 Add gamma
29 pick 7c2fd3b9020c Add delta
29 pick 7c2fd3b9020c Add delta
30
30
31 # Edit history between c561b4e977df and 7c2fd3b9020c
31 # Edit history between c561b4e977df and 7c2fd3b9020c
32 #
32 #
33 # Commits are listed from least to most recent
33 # Commits are listed from least to most recent
34 #
34 #
35 # Commands:
35 # Commands:
36 # p, pick = use commit
36 # p, pick = use commit
37 # e, edit = use commit, but stop for amending
37 # e, edit = use commit, but stop for amending
38 # f, fold = use commit, but combine it with the one above
38 # f, fold = use commit, but combine it with the one above
39 # r, roll = like fold, but discard this commit's description
39 # r, roll = like fold, but discard this commit's description
40 # d, drop = remove commit from history
40 # d, drop = remove commit from history
41 # m, mess = edit commit message without changing commit content
41 # m, mess = edit commit message without changing commit content
42 #
42 #
43
43
44 In this file, lines beginning with ``#`` are ignored. You must specify a rule
44 In this file, lines beginning with ``#`` are ignored. You must specify a rule
45 for each revision in your history. For example, if you had meant to add gamma
45 for each revision in your history. For example, if you had meant to add gamma
46 before beta, and then wanted to add delta in the same revision as beta, you
46 before beta, and then wanted to add delta in the same revision as beta, you
47 would reorganize the file to look like this::
47 would reorganize the file to look like this::
48
48
49 pick 030b686bedc4 Add gamma
49 pick 030b686bedc4 Add gamma
50 pick c561b4e977df Add beta
50 pick c561b4e977df Add beta
51 fold 7c2fd3b9020c Add delta
51 fold 7c2fd3b9020c Add delta
52
52
53 # Edit history between c561b4e977df and 7c2fd3b9020c
53 # Edit history between c561b4e977df and 7c2fd3b9020c
54 #
54 #
55 # Commits are listed from least to most recent
55 # Commits are listed from least to most recent
56 #
56 #
57 # Commands:
57 # Commands:
58 # p, pick = use commit
58 # p, pick = use commit
59 # e, edit = use commit, but stop for amending
59 # e, edit = use commit, but stop for amending
60 # f, fold = use commit, but combine it with the one above
60 # f, fold = use commit, but combine it with the one above
61 # r, roll = like fold, but discard this commit's description
61 # r, roll = like fold, but discard this commit's description
62 # d, drop = remove commit from history
62 # d, drop = remove commit from history
63 # m, mess = edit commit message without changing commit content
63 # m, mess = edit commit message without changing commit content
64 #
64 #
65
65
66 At which point you close the editor and ``histedit`` starts working. When you
66 At which point you close the editor and ``histedit`` starts working. When you
67 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
67 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
68 those revisions together, offering you a chance to clean up the commit message::
68 those revisions together, offering you a chance to clean up the commit message::
69
69
70 Add beta
70 Add beta
71 ***
71 ***
72 Add delta
72 Add delta
73
73
74 Edit the commit message to your liking, then close the editor. For
74 Edit the commit message to your liking, then close the editor. For
75 this example, let's assume that the commit message was changed to
75 this example, let's assume that the commit message was changed to
76 ``Add beta and delta.`` After histedit has run and had a chance to
76 ``Add beta and delta.`` After histedit has run and had a chance to
77 remove any old or temporary revisions it needed, the history looks
77 remove any old or temporary revisions it needed, the history looks
78 like this::
78 like this::
79
79
80 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
80 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
81 | Add beta and delta.
81 | Add beta and delta.
82 |
82 |
83 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
83 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
84 | Add gamma
84 | Add gamma
85 |
85 |
86 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
86 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
87 Add alpha
87 Add alpha
88
88
89 Note that ``histedit`` does *not* remove any revisions (even its own temporary
89 Note that ``histedit`` does *not* remove any revisions (even its own temporary
90 ones) until after it has completed all the editing operations, so it will
90 ones) until after it has completed all the editing operations, so it will
91 probably perform several strip operations when it's done. For the above example,
91 probably perform several strip operations when it's done. For the above example,
92 it had to run strip twice. Strip can be slow depending on a variety of factors,
92 it had to run strip twice. Strip can be slow depending on a variety of factors,
93 so you might need to be a little patient. You can choose to keep the original
93 so you might need to be a little patient. You can choose to keep the original
94 revisions by passing the ``--keep`` flag.
94 revisions by passing the ``--keep`` flag.
95
95
96 The ``edit`` operation will drop you back to a command prompt,
96 The ``edit`` operation will drop you back to a command prompt,
97 allowing you to edit files freely, or even use ``hg record`` to commit
97 allowing you to edit files freely, or even use ``hg record`` to commit
98 some changes as a separate commit. When you're done, any remaining
98 some changes as a separate commit. When you're done, any remaining
99 uncommitted changes will be committed as well. When done, run ``hg
99 uncommitted changes will be committed as well. When done, run ``hg
100 histedit --continue`` to finish this step. You'll be prompted for a
100 histedit --continue`` to finish this step. You'll be prompted for a
101 new commit message, but the default commit message will be the
101 new commit message, but the default commit message will be the
102 original message for the ``edit`` ed revision.
102 original message for the ``edit`` ed revision.
103
103
104 The ``message`` operation will give you a chance to revise a commit
104 The ``message`` operation will give you a chance to revise a commit
105 message without changing the contents. It's a shortcut for doing
105 message without changing the contents. It's a shortcut for doing
106 ``edit`` immediately followed by `hg histedit --continue``.
106 ``edit`` immediately followed by `hg histedit --continue``.
107
107
108 If ``histedit`` encounters a conflict when moving a revision (while
108 If ``histedit`` encounters a conflict when moving a revision (while
109 handling ``pick`` or ``fold``), it'll stop in a similar manner to
109 handling ``pick`` or ``fold``), it'll stop in a similar manner to
110 ``edit`` with the difference that it won't prompt you for a commit
110 ``edit`` with the difference that it won't prompt you for a commit
111 message when done. If you decide at this point that you don't like how
111 message when done. If you decide at this point that you don't like how
112 much work it will be to rearrange history, or that you made a mistake,
112 much work it will be to rearrange history, or that you made a mistake,
113 you can use ``hg histedit --abort`` to abandon the new changes you
113 you can use ``hg histedit --abort`` to abandon the new changes you
114 have made and return to the state before you attempted to edit your
114 have made and return to the state before you attempted to edit your
115 history.
115 history.
116
116
117 If we clone the histedit-ed example repository above and add four more
117 If we clone the histedit-ed example repository above and add four more
118 changes, such that we have the following history::
118 changes, such that we have the following history::
119
119
120 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
120 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
121 | Add theta
121 | Add theta
122 |
122 |
123 o 5 140988835471 2009-04-27 18:04 -0500 stefan
123 o 5 140988835471 2009-04-27 18:04 -0500 stefan
124 | Add eta
124 | Add eta
125 |
125 |
126 o 4 122930637314 2009-04-27 18:04 -0500 stefan
126 o 4 122930637314 2009-04-27 18:04 -0500 stefan
127 | Add zeta
127 | Add zeta
128 |
128 |
129 o 3 836302820282 2009-04-27 18:04 -0500 stefan
129 o 3 836302820282 2009-04-27 18:04 -0500 stefan
130 | Add epsilon
130 | Add epsilon
131 |
131 |
132 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
132 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
133 | Add beta and delta.
133 | Add beta and delta.
134 |
134 |
135 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
135 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
136 | Add gamma
136 | Add gamma
137 |
137 |
138 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
138 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
139 Add alpha
139 Add alpha
140
140
141 If you run ``hg histedit --outgoing`` on the clone then it is the same
141 If you run ``hg histedit --outgoing`` on the clone then it is the same
142 as running ``hg histedit 836302820282``. If you need plan to push to a
142 as running ``hg histedit 836302820282``. If you need plan to push to a
143 repository that Mercurial does not detect to be related to the source
143 repository that Mercurial does not detect to be related to the source
144 repo, you can add a ``--force`` option.
144 repo, you can add a ``--force`` option.
145
145
146 Histedit rule lines are truncated to 80 characters by default. You
146 Histedit rule lines are truncated to 80 characters by default. You
147 can customize this behavior by setting a different length in your
147 can customize this behavior by setting a different length in your
148 configuration file::
148 configuration file::
149
149
150 [histedit]
150 [histedit]
151 linelen = 120 # truncate rule lines at 120 characters
151 linelen = 120 # truncate rule lines at 120 characters
152 """
152 """
153
153
154 try:
154 try:
155 import cPickle as pickle
155 import cPickle as pickle
156 pickle.dump # import now
156 pickle.dump # import now
157 except ImportError:
157 except ImportError:
158 import pickle
158 import pickle
159 import errno
159 import errno
160 import os
160 import os
161 import sys
161 import sys
162
162
163 from mercurial import cmdutil
163 from mercurial import cmdutil
164 from mercurial import discovery
164 from mercurial import discovery
165 from mercurial import error
165 from mercurial import error
166 from mercurial import copies
166 from mercurial import copies
167 from mercurial import context
167 from mercurial import context
168 from mercurial import exchange
168 from mercurial import exchange
169 from mercurial import extensions
169 from mercurial import extensions
170 from mercurial import hg
170 from mercurial import hg
171 from mercurial import node
171 from mercurial import node
172 from mercurial import repair
172 from mercurial import repair
173 from mercurial import scmutil
173 from mercurial import scmutil
174 from mercurial import util
174 from mercurial import util
175 from mercurial import obsolete
175 from mercurial import obsolete
176 from mercurial import merge as mergemod
176 from mercurial import merge as mergemod
177 from mercurial.lock import release
177 from mercurial.lock import release
178 from mercurial.i18n import _
178 from mercurial.i18n import _
179
179
180 cmdtable = {}
180 cmdtable = {}
181 command = cmdutil.command(cmdtable)
181 command = cmdutil.command(cmdtable)
182
182
183 # Note for extension authors: ONLY specify testedwith = 'internal' for
183 # Note for extension authors: ONLY specify testedwith = 'internal' for
184 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
184 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
185 # be specifying the version(s) of Mercurial they are tested with, or
185 # be specifying the version(s) of Mercurial they are tested with, or
186 # leave the attribute unspecified.
186 # leave the attribute unspecified.
187 testedwith = 'internal'
187 testedwith = 'internal'
188
188
189 # i18n: command names and abbreviations must remain untranslated
189 # i18n: command names and abbreviations must remain untranslated
190 editcomment = _("""# Edit history between %s and %s
190 editcomment = _("""# Edit history between %s and %s
191 #
191 #
192 # Commits are listed from least to most recent
192 # Commits are listed from least to most recent
193 #
193 #
194 # Commands:
194 # Commands:
195 # p, pick = use commit
195 # p, pick = use commit
196 # e, edit = use commit, but stop for amending
196 # e, edit = use commit, but stop for amending
197 # f, fold = use commit, but combine it with the one above
197 # f, fold = use commit, but combine it with the one above
198 # r, roll = like fold, but discard this commit's description
198 # r, roll = like fold, but discard this commit's description
199 # d, drop = remove commit from history
199 # d, drop = remove commit from history
200 # m, mess = edit commit message without changing commit content
200 # m, mess = edit commit message without changing commit content
201 #
201 #
202 """)
202 """)
203
203
204 class histeditstate(object):
204 class histeditstate(object):
205 def __init__(self, repo, parentctxnode=None, rules=None, keep=None,
205 def __init__(self, repo, parentctxnode=None, rules=None, keep=None,
206 topmost=None, replacements=None, lock=None, wlock=None):
206 topmost=None, replacements=None, lock=None, wlock=None):
207 self.repo = repo
207 self.repo = repo
208 self.rules = rules
208 self.rules = rules
209 self.keep = keep
209 self.keep = keep
210 self.topmost = topmost
210 self.topmost = topmost
211 self.parentctxnode = parentctxnode
211 self.parentctxnode = parentctxnode
212 self.lock = lock
212 self.lock = lock
213 self.wlock = wlock
213 self.wlock = wlock
214 self.backupfile = None
214 self.backupfile = None
215 if replacements is None:
215 if replacements is None:
216 self.replacements = []
216 self.replacements = []
217 else:
217 else:
218 self.replacements = replacements
218 self.replacements = replacements
219
219
220 def read(self):
220 def read(self):
221 """Load histedit state from disk and set fields appropriately."""
221 """Load histedit state from disk and set fields appropriately."""
222 try:
222 try:
223 fp = self.repo.vfs('histedit-state', 'r')
223 fp = self.repo.vfs('histedit-state', 'r')
224 except IOError as err:
224 except IOError as err:
225 if err.errno != errno.ENOENT:
225 if err.errno != errno.ENOENT:
226 raise
226 raise
227 raise error.Abort(_('no histedit in progress'))
227 raise error.Abort(_('no histedit in progress'))
228
228
229 try:
229 try:
230 data = pickle.load(fp)
230 data = pickle.load(fp)
231 parentctxnode, rules, keep, topmost, replacements = data
231 parentctxnode, rules, keep, topmost, replacements = data
232 backupfile = None
232 backupfile = None
233 except pickle.UnpicklingError:
233 except pickle.UnpicklingError:
234 data = self._load()
234 data = self._load()
235 parentctxnode, rules, keep, topmost, replacements, backupfile = data
235 parentctxnode, rules, keep, topmost, replacements, backupfile = data
236
236
237 self.parentctxnode = parentctxnode
237 self.parentctxnode = parentctxnode
238 self.rules = rules
238 self.rules = rules
239 self.keep = keep
239 self.keep = keep
240 self.topmost = topmost
240 self.topmost = topmost
241 self.replacements = replacements
241 self.replacements = replacements
242 self.backupfile = backupfile
242 self.backupfile = backupfile
243
243
244 def write(self):
244 def write(self):
245 fp = self.repo.vfs('histedit-state', 'w')
245 fp = self.repo.vfs('histedit-state', 'w')
246 fp.write('v1\n')
246 fp.write('v1\n')
247 fp.write('%s\n' % node.hex(self.parentctxnode))
247 fp.write('%s\n' % node.hex(self.parentctxnode))
248 fp.write('%s\n' % node.hex(self.topmost))
248 fp.write('%s\n' % node.hex(self.topmost))
249 fp.write('%s\n' % self.keep)
249 fp.write('%s\n' % self.keep)
250 fp.write('%d\n' % len(self.rules))
250 fp.write('%d\n' % len(self.rules))
251 for rule in self.rules:
251 for rule in self.rules:
252 fp.write('%s\n' % rule[0]) # action
252 fp.write('%s\n' % rule[0]) # action
253 fp.write('%s\n' % rule[1]) # remainder
253 fp.write('%s\n' % rule[1]) # remainder
254 fp.write('%d\n' % len(self.replacements))
254 fp.write('%d\n' % len(self.replacements))
255 for replacement in self.replacements:
255 for replacement in self.replacements:
256 fp.write('%s%s\n' % (node.hex(replacement[0]), ''.join(node.hex(r)
256 fp.write('%s%s\n' % (node.hex(replacement[0]), ''.join(node.hex(r)
257 for r in replacement[1])))
257 for r in replacement[1])))
258 backupfile = self.backupfile
258 backupfile = self.backupfile
259 if not backupfile:
259 if not backupfile:
260 backupfile = ''
260 backupfile = ''
261 fp.write('%s\n' % backupfile)
261 fp.write('%s\n' % backupfile)
262 fp.close()
262 fp.close()
263
263
264 def _load(self):
264 def _load(self):
265 fp = self.repo.vfs('histedit-state', 'r')
265 fp = self.repo.vfs('histedit-state', 'r')
266 lines = [l[:-1] for l in fp.readlines()]
266 lines = [l[:-1] for l in fp.readlines()]
267
267
268 index = 0
268 index = 0
269 lines[index] # version number
269 lines[index] # version number
270 index += 1
270 index += 1
271
271
272 parentctxnode = node.bin(lines[index])
272 parentctxnode = node.bin(lines[index])
273 index += 1
273 index += 1
274
274
275 topmost = node.bin(lines[index])
275 topmost = node.bin(lines[index])
276 index += 1
276 index += 1
277
277
278 keep = lines[index] == 'True'
278 keep = lines[index] == 'True'
279 index += 1
279 index += 1
280
280
281 # Rules
281 # Rules
282 rules = []
282 rules = []
283 rulelen = int(lines[index])
283 rulelen = int(lines[index])
284 index += 1
284 index += 1
285 for i in xrange(rulelen):
285 for i in xrange(rulelen):
286 ruleaction = lines[index]
286 ruleaction = lines[index]
287 index += 1
287 index += 1
288 rule = lines[index]
288 rule = lines[index]
289 index += 1
289 index += 1
290 rules.append((ruleaction, rule))
290 rules.append((ruleaction, rule))
291
291
292 # Replacements
292 # Replacements
293 replacements = []
293 replacements = []
294 replacementlen = int(lines[index])
294 replacementlen = int(lines[index])
295 index += 1
295 index += 1
296 for i in xrange(replacementlen):
296 for i in xrange(replacementlen):
297 replacement = lines[index]
297 replacement = lines[index]
298 original = node.bin(replacement[:40])
298 original = node.bin(replacement[:40])
299 succ = [node.bin(replacement[i:i + 40]) for i in
299 succ = [node.bin(replacement[i:i + 40]) for i in
300 range(40, len(replacement), 40)]
300 range(40, len(replacement), 40)]
301 replacements.append((original, succ))
301 replacements.append((original, succ))
302 index += 1
302 index += 1
303
303
304 backupfile = lines[index]
304 backupfile = lines[index]
305 index += 1
305 index += 1
306
306
307 fp.close()
307 fp.close()
308
308
309 return parentctxnode, rules, keep, topmost, replacements, backupfile
309 return parentctxnode, rules, keep, topmost, replacements, backupfile
310
310
311 def clear(self):
311 def clear(self):
312 if self.inprogress():
312 if self.inprogress():
313 self.repo.vfs.unlink('histedit-state')
313 self.repo.vfs.unlink('histedit-state')
314
314
315 def inprogress(self):
315 def inprogress(self):
316 return self.repo.vfs.exists('histedit-state')
316 return self.repo.vfs.exists('histedit-state')
317
317
318 class histeditaction(object):
318 class histeditaction(object):
319 def __init__(self, state, node):
319 def __init__(self, state, node):
320 self.state = state
320 self.state = state
321 self.repo = state.repo
321 self.repo = state.repo
322 self.node = node
322 self.node = node
323
323
324 @classmethod
324 @classmethod
325 def fromrule(cls, state, rule):
325 def fromrule(cls, state, rule):
326 """Parses the given rule, returning an instance of the histeditaction.
326 """Parses the given rule, returning an instance of the histeditaction.
327 """
327 """
328 repo = state.repo
328 repo = state.repo
329 rulehash = rule.strip().split(' ', 1)[0]
329 rulehash = rule.strip().split(' ', 1)[0]
330 try:
330 try:
331 node = repo[rulehash].node()
331 node = repo[rulehash].node()
332 except error.RepoError:
332 except error.RepoError:
333 raise error.Abort(_('unknown changeset %s listed') % rulehash[:12])
333 raise error.Abort(_('unknown changeset %s listed') % rulehash[:12])
334 return cls(state, node)
334 return cls(state, node)
335
335
336 def run(self):
336 def run(self):
337 """Runs the action. The default behavior is simply apply the action's
337 """Runs the action. The default behavior is simply apply the action's
338 rulectx onto the current parentctx."""
338 rulectx onto the current parentctx."""
339 self.applychange()
339 self.applychange()
340 self.continuedirty()
340 self.continuedirty()
341 return self.continueclean()
341 return self.continueclean()
342
342
343 def applychange(self):
343 def applychange(self):
344 """Applies the changes from this action's rulectx onto the current
344 """Applies the changes from this action's rulectx onto the current
345 parentctx, but does not commit them."""
345 parentctx, but does not commit them."""
346 repo = self.repo
346 repo = self.repo
347 rulectx = repo[self.node]
347 rulectx = repo[self.node]
348 hg.update(repo, self.state.parentctxnode)
348 hg.update(repo, self.state.parentctxnode)
349 stats = applychanges(repo.ui, repo, rulectx, {})
349 stats = applychanges(repo.ui, repo, rulectx, {})
350 if stats and stats[3] > 0:
350 if stats and stats[3] > 0:
351 raise error.InterventionRequired(_('Fix up the change and run '
351 raise error.InterventionRequired(_('Fix up the change and run '
352 'hg histedit --continue'))
352 'hg histedit --continue'))
353
353
354 def continuedirty(self):
354 def continuedirty(self):
355 """Continues the action when changes have been applied to the working
355 """Continues the action when changes have been applied to the working
356 copy. The default behavior is to commit the dirty changes."""
356 copy. The default behavior is to commit the dirty changes."""
357 repo = self.repo
357 repo = self.repo
358 rulectx = repo[self.node]
358 rulectx = repo[self.node]
359
359
360 editor = self.commiteditor()
360 editor = self.commiteditor()
361 commit = commitfuncfor(repo, rulectx)
361 commit = commitfuncfor(repo, rulectx)
362
362
363 commit(text=rulectx.description(), user=rulectx.user(),
363 commit(text=rulectx.description(), user=rulectx.user(),
364 date=rulectx.date(), extra=rulectx.extra(), editor=editor)
364 date=rulectx.date(), extra=rulectx.extra(), editor=editor)
365
365
366 def commiteditor(self):
366 def commiteditor(self):
367 """The editor to be used to edit the commit message."""
367 """The editor to be used to edit the commit message."""
368 return False
368 return False
369
369
370 def continueclean(self):
370 def continueclean(self):
371 """Continues the action when the working copy is clean. The default
371 """Continues the action when the working copy is clean. The default
372 behavior is to accept the current commit as the new version of the
372 behavior is to accept the current commit as the new version of the
373 rulectx."""
373 rulectx."""
374 ctx = self.repo['.']
374 ctx = self.repo['.']
375 if ctx.node() == self.state.parentctxnode:
375 if ctx.node() == self.state.parentctxnode:
376 self.repo.ui.warn(_('%s: empty changeset\n') %
376 self.repo.ui.warn(_('%s: empty changeset\n') %
377 node.short(self.node))
377 node.short(self.node))
378 return ctx, [(self.node, tuple())]
378 return ctx, [(self.node, tuple())]
379 if ctx.node() == self.node:
379 if ctx.node() == self.node:
380 # Nothing changed
380 # Nothing changed
381 return ctx, []
381 return ctx, []
382 return ctx, [(self.node, (ctx.node(),))]
382 return ctx, [(self.node, (ctx.node(),))]
383
383
384 def commitfuncfor(repo, src):
384 def commitfuncfor(repo, src):
385 """Build a commit function for the replacement of <src>
385 """Build a commit function for the replacement of <src>
386
386
387 This function ensure we apply the same treatment to all changesets.
387 This function ensure we apply the same treatment to all changesets.
388
388
389 - Add a 'histedit_source' entry in extra.
389 - Add a 'histedit_source' entry in extra.
390
390
391 Note that fold has its own separated logic because its handling is a bit
391 Note that fold has its own separated logic because its handling is a bit
392 different and not easily factored out of the fold method.
392 different and not easily factored out of the fold method.
393 """
393 """
394 phasemin = src.phase()
394 phasemin = src.phase()
395 def commitfunc(**kwargs):
395 def commitfunc(**kwargs):
396 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
396 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
397 try:
397 try:
398 repo.ui.setconfig('phases', 'new-commit', phasemin,
398 repo.ui.setconfig('phases', 'new-commit', phasemin,
399 'histedit')
399 'histedit')
400 extra = kwargs.get('extra', {}).copy()
400 extra = kwargs.get('extra', {}).copy()
401 extra['histedit_source'] = src.hex()
401 extra['histedit_source'] = src.hex()
402 kwargs['extra'] = extra
402 kwargs['extra'] = extra
403 return repo.commit(**kwargs)
403 return repo.commit(**kwargs)
404 finally:
404 finally:
405 repo.ui.restoreconfig(phasebackup)
405 repo.ui.restoreconfig(phasebackup)
406 return commitfunc
406 return commitfunc
407
407
408 def applychanges(ui, repo, ctx, opts):
408 def applychanges(ui, repo, ctx, opts):
409 """Merge changeset from ctx (only) in the current working directory"""
409 """Merge changeset from ctx (only) in the current working directory"""
410 wcpar = repo.dirstate.parents()[0]
410 wcpar = repo.dirstate.parents()[0]
411 if ctx.p1().node() == wcpar:
411 if ctx.p1().node() == wcpar:
412 # edits are "in place" we do not need to make any merge,
412 # edits are "in place" we do not need to make any merge,
413 # just applies changes on parent for edition
413 # just applies changes on parent for edition
414 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
414 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
415 stats = None
415 stats = None
416 else:
416 else:
417 try:
417 try:
418 # ui.forcemerge is an internal variable, do not document
418 # ui.forcemerge is an internal variable, do not document
419 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
419 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
420 'histedit')
420 'histedit')
421 stats = mergemod.graft(repo, ctx, ctx.p1(), ['local', 'histedit'])
421 stats = mergemod.graft(repo, ctx, ctx.p1(), ['local', 'histedit'])
422 finally:
422 finally:
423 repo.ui.setconfig('ui', 'forcemerge', '', 'histedit')
423 repo.ui.setconfig('ui', 'forcemerge', '', 'histedit')
424 return stats
424 return stats
425
425
426 def collapse(repo, first, last, commitopts, skipprompt=False):
426 def collapse(repo, first, last, commitopts, skipprompt=False):
427 """collapse the set of revisions from first to last as new one.
427 """collapse the set of revisions from first to last as new one.
428
428
429 Expected commit options are:
429 Expected commit options are:
430 - message
430 - message
431 - date
431 - date
432 - username
432 - username
433 Commit message is edited in all cases.
433 Commit message is edited in all cases.
434
434
435 This function works in memory."""
435 This function works in memory."""
436 ctxs = list(repo.set('%d::%d', first, last))
436 ctxs = list(repo.set('%d::%d', first, last))
437 if not ctxs:
437 if not ctxs:
438 return None
438 return None
439 for c in ctxs:
439 for c in ctxs:
440 if not c.mutable():
440 if not c.mutable():
441 raise error.Abort(
441 raise error.Abort(
442 _("cannot fold into public change %s") % node.short(c.node()))
442 _("cannot fold into public change %s") % node.short(c.node()))
443 base = first.parents()[0]
443 base = first.parents()[0]
444
444
445 # commit a new version of the old changeset, including the update
445 # commit a new version of the old changeset, including the update
446 # collect all files which might be affected
446 # collect all files which might be affected
447 files = set()
447 files = set()
448 for ctx in ctxs:
448 for ctx in ctxs:
449 files.update(ctx.files())
449 files.update(ctx.files())
450
450
451 # Recompute copies (avoid recording a -> b -> a)
451 # Recompute copies (avoid recording a -> b -> a)
452 copied = copies.pathcopies(base, last)
452 copied = copies.pathcopies(base, last)
453
453
454 # prune files which were reverted by the updates
454 # prune files which were reverted by the updates
455 def samefile(f):
455 def samefile(f):
456 if f in last.manifest():
456 if f in last.manifest():
457 a = last.filectx(f)
457 a = last.filectx(f)
458 if f in base.manifest():
458 if f in base.manifest():
459 b = base.filectx(f)
459 b = base.filectx(f)
460 return (a.data() == b.data()
460 return (a.data() == b.data()
461 and a.flags() == b.flags())
461 and a.flags() == b.flags())
462 else:
462 else:
463 return False
463 return False
464 else:
464 else:
465 return f not in base.manifest()
465 return f not in base.manifest()
466 files = [f for f in files if not samefile(f)]
466 files = [f for f in files if not samefile(f)]
467 # commit version of these files as defined by head
467 # commit version of these files as defined by head
468 headmf = last.manifest()
468 headmf = last.manifest()
469 def filectxfn(repo, ctx, path):
469 def filectxfn(repo, ctx, path):
470 if path in headmf:
470 if path in headmf:
471 fctx = last[path]
471 fctx = last[path]
472 flags = fctx.flags()
472 flags = fctx.flags()
473 mctx = context.memfilectx(repo,
473 mctx = context.memfilectx(repo,
474 fctx.path(), fctx.data(),
474 fctx.path(), fctx.data(),
475 islink='l' in flags,
475 islink='l' in flags,
476 isexec='x' in flags,
476 isexec='x' in flags,
477 copied=copied.get(path))
477 copied=copied.get(path))
478 return mctx
478 return mctx
479 return None
479 return None
480
480
481 if commitopts.get('message'):
481 if commitopts.get('message'):
482 message = commitopts['message']
482 message = commitopts['message']
483 else:
483 else:
484 message = first.description()
484 message = first.description()
485 user = commitopts.get('user')
485 user = commitopts.get('user')
486 date = commitopts.get('date')
486 date = commitopts.get('date')
487 extra = commitopts.get('extra')
487 extra = commitopts.get('extra')
488
488
489 parents = (first.p1().node(), first.p2().node())
489 parents = (first.p1().node(), first.p2().node())
490 editor = None
490 editor = None
491 if not skipprompt:
491 if not skipprompt:
492 editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold')
492 editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold')
493 new = context.memctx(repo,
493 new = context.memctx(repo,
494 parents=parents,
494 parents=parents,
495 text=message,
495 text=message,
496 files=files,
496 files=files,
497 filectxfn=filectxfn,
497 filectxfn=filectxfn,
498 user=user,
498 user=user,
499 date=date,
499 date=date,
500 extra=extra,
500 extra=extra,
501 editor=editor)
501 editor=editor)
502 return repo.commitctx(new)
502 return repo.commitctx(new)
503
503
504 class pick(histeditaction):
504 class pick(histeditaction):
505 def run(self):
505 def run(self):
506 rulectx = self.repo[self.node]
506 rulectx = self.repo[self.node]
507 if rulectx.parents()[0].node() == self.state.parentctxnode:
507 if rulectx.parents()[0].node() == self.state.parentctxnode:
508 self.repo.ui.debug('node %s unchanged\n' % node.short(self.node))
508 self.repo.ui.debug('node %s unchanged\n' % node.short(self.node))
509 return rulectx, []
509 return rulectx, []
510
510
511 return super(pick, self).run()
511 return super(pick, self).run()
512
512
513 class edit(histeditaction):
513 class edit(histeditaction):
514 def run(self):
514 def run(self):
515 repo = self.repo
515 repo = self.repo
516 rulectx = repo[self.node]
516 rulectx = repo[self.node]
517 hg.update(repo, self.state.parentctxnode)
517 hg.update(repo, self.state.parentctxnode)
518 applychanges(repo.ui, repo, rulectx, {})
518 applychanges(repo.ui, repo, rulectx, {})
519 raise error.InterventionRequired(
519 raise error.InterventionRequired(
520 _('Make changes as needed, you may commit or record as needed '
520 _('Make changes as needed, you may commit or record as needed '
521 'now.\nWhen you are finished, run hg histedit --continue to '
521 'now.\nWhen you are finished, run hg histedit --continue to '
522 'resume.'))
522 'resume.'))
523
523
524 def commiteditor(self):
524 def commiteditor(self):
525 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit')
525 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit')
526
526
527 class fold(histeditaction):
527 class fold(histeditaction):
528 def continuedirty(self):
528 def continuedirty(self):
529 repo = self.repo
529 repo = self.repo
530 rulectx = repo[self.node]
530 rulectx = repo[self.node]
531
531
532 commit = commitfuncfor(repo, rulectx)
532 commit = commitfuncfor(repo, rulectx)
533 commit(text='fold-temp-revision %s' % node.short(self.node),
533 commit(text='fold-temp-revision %s' % node.short(self.node),
534 user=rulectx.user(), date=rulectx.date(),
534 user=rulectx.user(), date=rulectx.date(),
535 extra=rulectx.extra())
535 extra=rulectx.extra())
536
536
537 def continueclean(self):
537 def continueclean(self):
538 repo = self.repo
538 repo = self.repo
539 ctx = repo['.']
539 ctx = repo['.']
540 rulectx = repo[self.node]
540 rulectx = repo[self.node]
541 parentctxnode = self.state.parentctxnode
541 parentctxnode = self.state.parentctxnode
542 if ctx.node() == parentctxnode:
542 if ctx.node() == parentctxnode:
543 repo.ui.warn(_('%s: empty changeset\n') %
543 repo.ui.warn(_('%s: empty changeset\n') %
544 node.short(self.node))
544 node.short(self.node))
545 return ctx, [(self.node, (parentctxnode,))]
545 return ctx, [(self.node, (parentctxnode,))]
546
546
547 parentctx = repo[parentctxnode]
547 parentctx = repo[parentctxnode]
548 newcommits = set(c.node() for c in repo.set('(%d::. - %d)', parentctx,
548 newcommits = set(c.node() for c in repo.set('(%d::. - %d)', parentctx,
549 parentctx))
549 parentctx))
550 if not newcommits:
550 if not newcommits:
551 repo.ui.warn(_('%s: cannot fold - working copy is not a '
551 repo.ui.warn(_('%s: cannot fold - working copy is not a '
552 'descendant of previous commit %s\n') %
552 'descendant of previous commit %s\n') %
553 (node.short(self.node), node.short(parentctxnode)))
553 (node.short(self.node), node.short(parentctxnode)))
554 return ctx, [(self.node, (ctx.node(),))]
554 return ctx, [(self.node, (ctx.node(),))]
555
555
556 middlecommits = newcommits.copy()
556 middlecommits = newcommits.copy()
557 middlecommits.discard(ctx.node())
557 middlecommits.discard(ctx.node())
558
558
559 return self.finishfold(repo.ui, repo, parentctx, rulectx, ctx.node(),
559 return self.finishfold(repo.ui, repo, parentctx, rulectx, ctx.node(),
560 middlecommits)
560 middlecommits)
561
561
562 def skipprompt(self):
562 def skipprompt(self):
563 """Returns true if the rule should skip the message editor.
563 """Returns true if the rule should skip the message editor.
564
564
565 For example, 'fold' wants to show an editor, but 'rollup'
565 For example, 'fold' wants to show an editor, but 'rollup'
566 doesn't want to.
566 doesn't want to.
567 """
567 """
568 return False
568 return False
569
569
570 def mergedescs(self):
570 def mergedescs(self):
571 """Returns true if the rule should merge messages of multiple changes.
571 """Returns true if the rule should merge messages of multiple changes.
572
572
573 This exists mainly so that 'rollup' rules can be a subclass of
573 This exists mainly so that 'rollup' rules can be a subclass of
574 'fold'.
574 'fold'.
575 """
575 """
576 return True
576 return True
577
577
578 def finishfold(self, ui, repo, ctx, oldctx, newnode, internalchanges):
578 def finishfold(self, ui, repo, ctx, oldctx, newnode, internalchanges):
579 parent = ctx.parents()[0].node()
579 parent = ctx.parents()[0].node()
580 hg.update(repo, parent)
580 hg.update(repo, parent)
581 ### prepare new commit data
581 ### prepare new commit data
582 commitopts = {}
582 commitopts = {}
583 commitopts['user'] = ctx.user()
583 commitopts['user'] = ctx.user()
584 # commit message
584 # commit message
585 if not self.mergedescs():
585 if not self.mergedescs():
586 newmessage = ctx.description()
586 newmessage = ctx.description()
587 else:
587 else:
588 newmessage = '\n***\n'.join(
588 newmessage = '\n***\n'.join(
589 [ctx.description()] +
589 [ctx.description()] +
590 [repo[r].description() for r in internalchanges] +
590 [repo[r].description() for r in internalchanges] +
591 [oldctx.description()]) + '\n'
591 [oldctx.description()]) + '\n'
592 commitopts['message'] = newmessage
592 commitopts['message'] = newmessage
593 # date
593 # date
594 commitopts['date'] = max(ctx.date(), oldctx.date())
594 commitopts['date'] = max(ctx.date(), oldctx.date())
595 extra = ctx.extra().copy()
595 extra = ctx.extra().copy()
596 # histedit_source
596 # histedit_source
597 # note: ctx is likely a temporary commit but that the best we can do
597 # note: ctx is likely a temporary commit but that the best we can do
598 # here. This is sufficient to solve issue3681 anyway.
598 # here. This is sufficient to solve issue3681 anyway.
599 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
599 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
600 commitopts['extra'] = extra
600 commitopts['extra'] = extra
601 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
601 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
602 try:
602 try:
603 phasemin = max(ctx.phase(), oldctx.phase())
603 phasemin = max(ctx.phase(), oldctx.phase())
604 repo.ui.setconfig('phases', 'new-commit', phasemin, 'histedit')
604 repo.ui.setconfig('phases', 'new-commit', phasemin, 'histedit')
605 n = collapse(repo, ctx, repo[newnode], commitopts,
605 n = collapse(repo, ctx, repo[newnode], commitopts,
606 skipprompt=self.skipprompt())
606 skipprompt=self.skipprompt())
607 finally:
607 finally:
608 repo.ui.restoreconfig(phasebackup)
608 repo.ui.restoreconfig(phasebackup)
609 if n is None:
609 if n is None:
610 return ctx, []
610 return ctx, []
611 hg.update(repo, n)
611 hg.update(repo, n)
612 replacements = [(oldctx.node(), (newnode,)),
612 replacements = [(oldctx.node(), (newnode,)),
613 (ctx.node(), (n,)),
613 (ctx.node(), (n,)),
614 (newnode, (n,)),
614 (newnode, (n,)),
615 ]
615 ]
616 for ich in internalchanges:
616 for ich in internalchanges:
617 replacements.append((ich, (n,)))
617 replacements.append((ich, (n,)))
618 return repo[n], replacements
618 return repo[n], replacements
619
619
620 class _multifold(fold):
620 class _multifold(fold):
621 """fold subclass used for when multiple folds happen in a row
621 """fold subclass used for when multiple folds happen in a row
622
622
623 We only want to fire the editor for the folded message once when
623 We only want to fire the editor for the folded message once when
624 (say) four changes are folded down into a single change. This is
624 (say) four changes are folded down into a single change. This is
625 similar to rollup, but we should preserve both messages so that
625 similar to rollup, but we should preserve both messages so that
626 when the last fold operation runs we can show the user all the
626 when the last fold operation runs we can show the user all the
627 commit messages in their editor.
627 commit messages in their editor.
628 """
628 """
629 def skipprompt(self):
629 def skipprompt(self):
630 return True
630 return True
631
631
632 class rollup(fold):
632 class rollup(fold):
633 def mergedescs(self):
633 def mergedescs(self):
634 return False
634 return False
635
635
636 def skipprompt(self):
636 def skipprompt(self):
637 return True
637 return True
638
638
639 class drop(histeditaction):
639 class drop(histeditaction):
640 def run(self):
640 def run(self):
641 parentctx = self.repo[self.state.parentctxnode]
641 parentctx = self.repo[self.state.parentctxnode]
642 return parentctx, [(self.node, tuple())]
642 return parentctx, [(self.node, tuple())]
643
643
644 class message(histeditaction):
644 class message(histeditaction):
645 def commiteditor(self):
645 def commiteditor(self):
646 return cmdutil.getcommiteditor(edit=True, editform='histedit.mess')
646 return cmdutil.getcommiteditor(edit=True, editform='histedit.mess')
647
647
648 def findoutgoing(ui, repo, remote=None, force=False, opts=None):
648 def findoutgoing(ui, repo, remote=None, force=False, opts=None):
649 """utility function to find the first outgoing changeset
649 """utility function to find the first outgoing changeset
650
650
651 Used by initialization code"""
651 Used by initialization code"""
652 if opts is None:
652 if opts is None:
653 opts = {}
653 opts = {}
654 dest = ui.expandpath(remote or 'default-push', remote or 'default')
654 dest = ui.expandpath(remote or 'default-push', remote or 'default')
655 dest, revs = hg.parseurl(dest, None)[:2]
655 dest, revs = hg.parseurl(dest, None)[:2]
656 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
656 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
657
657
658 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
658 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
659 other = hg.peer(repo, opts, dest)
659 other = hg.peer(repo, opts, dest)
660
660
661 if revs:
661 if revs:
662 revs = [repo.lookup(rev) for rev in revs]
662 revs = [repo.lookup(rev) for rev in revs]
663
663
664 outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
664 outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
665 if not outgoing.missing:
665 if not outgoing.missing:
666 raise error.Abort(_('no outgoing ancestors'))
666 raise error.Abort(_('no outgoing ancestors'))
667 roots = list(repo.revs("roots(%ln)", outgoing.missing))
667 roots = list(repo.revs("roots(%ln)", outgoing.missing))
668 if 1 < len(roots):
668 if 1 < len(roots):
669 msg = _('there are ambiguous outgoing revisions')
669 msg = _('there are ambiguous outgoing revisions')
670 hint = _('see "hg help histedit" for more detail')
670 hint = _('see "hg help histedit" for more detail')
671 raise error.Abort(msg, hint=hint)
671 raise error.Abort(msg, hint=hint)
672 return repo.lookup(roots[0])
672 return repo.lookup(roots[0])
673
673
674 actiontable = {'p': pick,
674 actiontable = {'p': pick,
675 'pick': pick,
675 'pick': pick,
676 'e': edit,
676 'e': edit,
677 'edit': edit,
677 'edit': edit,
678 'f': fold,
678 'f': fold,
679 'fold': fold,
679 'fold': fold,
680 '_multifold': _multifold,
680 '_multifold': _multifold,
681 'r': rollup,
681 'r': rollup,
682 'roll': rollup,
682 'roll': rollup,
683 'd': drop,
683 'd': drop,
684 'drop': drop,
684 'drop': drop,
685 'm': message,
685 'm': message,
686 'mess': message,
686 'mess': message,
687 }
687 }
688
688
689 @command('histedit',
689 @command('histedit',
690 [('', 'commands', '',
690 [('', 'commands', '',
691 _('read history edits from the specified file'), _('FILE')),
691 _('read history edits from the specified file'), _('FILE')),
692 ('c', 'continue', False, _('continue an edit already in progress')),
692 ('c', 'continue', False, _('continue an edit already in progress')),
693 ('', 'edit-plan', False, _('edit remaining actions list')),
693 ('', 'edit-plan', False, _('edit remaining actions list')),
694 ('k', 'keep', False,
694 ('k', 'keep', False,
695 _("don't strip old nodes after edit is complete")),
695 _("don't strip old nodes after edit is complete")),
696 ('', 'abort', False, _('abort an edit in progress')),
696 ('', 'abort', False, _('abort an edit in progress')),
697 ('o', 'outgoing', False, _('changesets not found in destination')),
697 ('o', 'outgoing', False, _('changesets not found in destination')),
698 ('f', 'force', False,
698 ('f', 'force', False,
699 _('force outgoing even for unrelated repositories')),
699 _('force outgoing even for unrelated repositories')),
700 ('r', 'rev', [], _('first revision to be edited'), _('REV'))],
700 ('r', 'rev', [], _('first revision to be edited'), _('REV'))],
701 _("ANCESTOR | --outgoing [URL]"))
701 _("ANCESTOR | --outgoing [URL]"))
702 def histedit(ui, repo, *freeargs, **opts):
702 def histedit(ui, repo, *freeargs, **opts):
703 """interactively edit changeset history
703 """interactively edit changeset history
704
704
705 This command edits changesets between ANCESTOR and the parent of
705 This command edits changesets between ANCESTOR and the parent of
706 the working directory.
706 the working directory.
707
707
708 With --outgoing, this edits changesets not found in the
708 With --outgoing, this edits changesets not found in the
709 destination repository. If URL of the destination is omitted, the
709 destination repository. If URL of the destination is omitted, the
710 'default-push' (or 'default') path will be used.
710 'default-push' (or 'default') path will be used.
711
711
712 For safety, this command is also aborted if there are ambiguous
712 For safety, this command is also aborted if there are ambiguous
713 outgoing revisions which may confuse users: for example, if there
713 outgoing revisions which may confuse users: for example, if there
714 are multiple branches containing outgoing revisions.
714 are multiple branches containing outgoing revisions.
715
715
716 Use "min(outgoing() and ::.)" or similar revset specification
716 Use "min(outgoing() and ::.)" or similar revset specification
717 instead of --outgoing to specify edit target revision exactly in
717 instead of --outgoing to specify edit target revision exactly in
718 such ambiguous situation. See :hg:`help revsets` for detail about
718 such ambiguous situation. See :hg:`help revsets` for detail about
719 selecting revisions.
719 selecting revisions.
720
720
721 Returns 0 on success, 1 if user intervention is required (not only
721 Returns 0 on success, 1 if user intervention is required (not only
722 for intentional "edit" command, but also for resolving unexpected
722 for intentional "edit" command, but also for resolving unexpected
723 conflicts).
723 conflicts).
724 """
724 """
725 state = histeditstate(repo)
725 state = histeditstate(repo)
726 try:
726 try:
727 state.wlock = repo.wlock()
727 state.wlock = repo.wlock()
728 state.lock = repo.lock()
728 state.lock = repo.lock()
729 _histedit(ui, repo, state, *freeargs, **opts)
729 _histedit(ui, repo, state, *freeargs, **opts)
730 finally:
730 finally:
731 release(state.lock, state.wlock)
731 release(state.lock, state.wlock)
732
732
733 def _histedit(ui, repo, state, *freeargs, **opts):
733 def _histedit(ui, repo, state, *freeargs, **opts):
734 # TODO only abort if we try and histedit mq patches, not just
734 # TODO only abort if we try and histedit mq patches, not just
735 # blanket if mq patches are applied somewhere
735 # blanket if mq patches are applied somewhere
736 mq = getattr(repo, 'mq', None)
736 mq = getattr(repo, 'mq', None)
737 if mq and mq.applied:
737 if mq and mq.applied:
738 raise error.Abort(_('source has mq patches applied'))
738 raise error.Abort(_('source has mq patches applied'))
739
739
740 # basic argument incompatibility processing
740 # basic argument incompatibility processing
741 outg = opts.get('outgoing')
741 outg = opts.get('outgoing')
742 cont = opts.get('continue')
742 cont = opts.get('continue')
743 editplan = opts.get('edit_plan')
743 editplan = opts.get('edit_plan')
744 abort = opts.get('abort')
744 abort = opts.get('abort')
745 force = opts.get('force')
745 force = opts.get('force')
746 rules = opts.get('commands', '')
746 rules = opts.get('commands', '')
747 revs = opts.get('rev', [])
747 revs = opts.get('rev', [])
748 goal = 'new' # This invocation goal, in new, continue, abort
748 goal = 'new' # This invocation goal, in new, continue, abort
749 if force and not outg:
749 if force and not outg:
750 raise error.Abort(_('--force only allowed with --outgoing'))
750 raise error.Abort(_('--force only allowed with --outgoing'))
751 if cont:
751 if cont:
752 if any((outg, abort, revs, freeargs, rules, editplan)):
752 if any((outg, abort, revs, freeargs, rules, editplan)):
753 raise error.Abort(_('no arguments allowed with --continue'))
753 raise error.Abort(_('no arguments allowed with --continue'))
754 goal = 'continue'
754 goal = 'continue'
755 elif abort:
755 elif abort:
756 if any((outg, revs, freeargs, rules, editplan)):
756 if any((outg, revs, freeargs, rules, editplan)):
757 raise error.Abort(_('no arguments allowed with --abort'))
757 raise error.Abort(_('no arguments allowed with --abort'))
758 goal = 'abort'
758 goal = 'abort'
759 elif editplan:
759 elif editplan:
760 if any((outg, revs, freeargs)):
760 if any((outg, revs, freeargs)):
761 raise error.Abort(_('only --commands argument allowed with '
761 raise error.Abort(_('only --commands argument allowed with '
762 '--edit-plan'))
762 '--edit-plan'))
763 goal = 'edit-plan'
763 goal = 'edit-plan'
764 else:
764 else:
765 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
765 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
766 raise error.Abort(_('history edit already in progress, try '
766 raise error.Abort(_('history edit already in progress, try '
767 '--continue or --abort'))
767 '--continue or --abort'))
768 if outg:
768 if outg:
769 if revs:
769 if revs:
770 raise error.Abort(_('no revisions allowed with --outgoing'))
770 raise error.Abort(_('no revisions allowed with --outgoing'))
771 if len(freeargs) > 1:
771 if len(freeargs) > 1:
772 raise error.Abort(
772 raise error.Abort(
773 _('only one repo argument allowed with --outgoing'))
773 _('only one repo argument allowed with --outgoing'))
774 else:
774 else:
775 revs.extend(freeargs)
775 revs.extend(freeargs)
776 if len(revs) == 0:
776 if len(revs) == 0:
777 # experimental config: histedit.defaultrev
777 # experimental config: histedit.defaultrev
778 histeditdefault = ui.config('histedit', 'defaultrev')
778 histeditdefault = ui.config('histedit', 'defaultrev')
779 if histeditdefault:
779 if histeditdefault:
780 revs.append(histeditdefault)
780 revs.append(histeditdefault)
781 if len(revs) != 1:
781 if len(revs) != 1:
782 raise error.Abort(
782 raise error.Abort(
783 _('histedit requires exactly one ancestor revision'))
783 _('histedit requires exactly one ancestor revision'))
784
784
785
785
786 replacements = []
786 replacements = []
787 state.keep = opts.get('keep', False)
787 state.keep = opts.get('keep', False)
788 supportsmarkers = obsolete.isenabled(repo, obsolete.createmarkersopt)
788 supportsmarkers = obsolete.isenabled(repo, obsolete.createmarkersopt)
789
789
790 # rebuild state
790 # rebuild state
791 if goal == 'continue':
791 if goal == 'continue':
792 state.read()
792 state.read()
793 state = bootstrapcontinue(ui, state, opts)
793 state = bootstrapcontinue(ui, state, opts)
794 elif goal == 'edit-plan':
794 elif goal == 'edit-plan':
795 state.read()
795 state.read()
796 if not rules:
796 if not rules:
797 comment = editcomment % (node.short(state.parentctxnode),
797 comment = editcomment % (node.short(state.parentctxnode),
798 node.short(state.topmost))
798 node.short(state.topmost))
799 rules = ruleeditor(repo, ui, state.rules, comment)
799 rules = ruleeditor(repo, ui, state.rules, comment)
800 else:
800 else:
801 if rules == '-':
801 if rules == '-':
802 f = sys.stdin
802 f = sys.stdin
803 else:
803 else:
804 f = open(rules)
804 f = open(rules)
805 rules = f.read()
805 rules = f.read()
806 f.close()
806 f.close()
807 rules = [l for l in (r.strip() for r in rules.splitlines())
807 rules = [l for l in (r.strip() for r in rules.splitlines())
808 if l and not l.startswith('#')]
808 if l and not l.startswith('#')]
809 rules = verifyrules(rules, repo, [repo[c] for [_a, c] in state.rules])
809 rules = verifyrules(rules, repo, [repo[c] for [_a, c] in state.rules])
810 state.rules = rules
810 state.rules = rules
811 state.write()
811 state.write()
812 return
812 return
813 elif goal == 'abort':
813 elif goal == 'abort':
814 try:
814 try:
815 state.read()
815 state.read()
816 tmpnodes, leafs = newnodestoabort(state)
816 tmpnodes, leafs = newnodestoabort(state)
817 ui.debug('restore wc to old parent %s\n'
817 ui.debug('restore wc to old parent %s\n'
818 % node.short(state.topmost))
818 % node.short(state.topmost))
819
819
820 # Recover our old commits if necessary
820 # Recover our old commits if necessary
821 if not state.topmost in repo and state.backupfile:
821 if not state.topmost in repo and state.backupfile:
822 backupfile = repo.join(state.backupfile)
822 backupfile = repo.join(state.backupfile)
823 f = hg.openpath(ui, backupfile)
823 f = hg.openpath(ui, backupfile)
824 gen = exchange.readbundle(ui, f, backupfile)
824 gen = exchange.readbundle(ui, f, backupfile)
825 gen.apply(repo, 'histedit', 'bundle:' + backupfile)
825 gen.apply(repo, 'histedit', 'bundle:' + backupfile)
826 os.remove(backupfile)
826 os.remove(backupfile)
827
827
828 # check whether we should update away
828 # check whether we should update away
829 if repo.unfiltered().revs('parents() and (%n or %ln::)',
829 if repo.unfiltered().revs('parents() and (%n or %ln::)',
830 state.parentctxnode, leafs | tmpnodes):
830 state.parentctxnode, leafs | tmpnodes):
831 hg.clean(repo, state.topmost)
831 hg.clean(repo, state.topmost)
832 cleanupnode(ui, repo, 'created', tmpnodes)
832 cleanupnode(ui, repo, 'created', tmpnodes)
833 cleanupnode(ui, repo, 'temp', leafs)
833 cleanupnode(ui, repo, 'temp', leafs)
834 except Exception:
834 except Exception:
835 if state.inprogress():
835 if state.inprogress():
836 ui.warn(_('warning: encountered an exception during histedit '
836 ui.warn(_('warning: encountered an exception during histedit '
837 '--abort; the repository may not have been completely '
837 '--abort; the repository may not have been completely '
838 'cleaned up\n'))
838 'cleaned up\n'))
839 raise
839 raise
840 finally:
840 finally:
841 state.clear()
841 state.clear()
842 return
842 return
843 else:
843 else:
844 cmdutil.checkunfinished(repo)
844 cmdutil.checkunfinished(repo)
845 cmdutil.bailifchanged(repo)
845 cmdutil.bailifchanged(repo)
846
846
847 topmost, empty = repo.dirstate.parents()
847 topmost, empty = repo.dirstate.parents()
848 if outg:
848 if outg:
849 if freeargs:
849 if freeargs:
850 remote = freeargs[0]
850 remote = freeargs[0]
851 else:
851 else:
852 remote = None
852 remote = None
853 root = findoutgoing(ui, repo, remote, force, opts)
853 root = findoutgoing(ui, repo, remote, force, opts)
854 else:
854 else:
855 rr = list(repo.set('roots(%ld)', scmutil.revrange(repo, revs)))
855 rr = list(repo.set('roots(%ld)', scmutil.revrange(repo, revs)))
856 if len(rr) != 1:
856 if len(rr) != 1:
857 raise error.Abort(_('The specified revisions must have '
857 raise error.Abort(_('The specified revisions must have '
858 'exactly one common root'))
858 'exactly one common root'))
859 root = rr[0].node()
859 root = rr[0].node()
860
860
861 revs = between(repo, root, topmost, state.keep)
861 revs = between(repo, root, topmost, state.keep)
862 if not revs:
862 if not revs:
863 raise error.Abort(_('%s is not an ancestor of working directory') %
863 raise error.Abort(_('%s is not an ancestor of working directory') %
864 node.short(root))
864 node.short(root))
865
865
866 ctxs = [repo[r] for r in revs]
866 ctxs = [repo[r] for r in revs]
867 if not rules:
867 if not rules:
868 comment = editcomment % (node.short(root), node.short(topmost))
868 comment = editcomment % (node.short(root), node.short(topmost))
869 rules = ruleeditor(repo, ui, [['pick', c] for c in ctxs], comment)
869 rules = ruleeditor(repo, ui, [['pick', c] for c in ctxs], comment)
870 else:
870 else:
871 if rules == '-':
871 if rules == '-':
872 f = sys.stdin
872 f = sys.stdin
873 else:
873 else:
874 f = open(rules)
874 f = open(rules)
875 rules = f.read()
875 rules = f.read()
876 f.close()
876 f.close()
877 rules = [l for l in (r.strip() for r in rules.splitlines())
877 rules = [l for l in (r.strip() for r in rules.splitlines())
878 if l and not l.startswith('#')]
878 if l and not l.startswith('#')]
879 rules = verifyrules(rules, repo, ctxs)
879 rules = verifyrules(rules, repo, ctxs)
880
880
881 parentctxnode = repo[root].parents()[0].node()
881 parentctxnode = repo[root].parents()[0].node()
882
882
883 state.parentctxnode = parentctxnode
883 state.parentctxnode = parentctxnode
884 state.rules = rules
884 state.rules = rules
885 state.topmost = topmost
885 state.topmost = topmost
886 state.replacements = replacements
886 state.replacements = replacements
887
887
888 # Create a backup so we can always abort completely.
888 # Create a backup so we can always abort completely.
889 backupfile = None
889 backupfile = None
890 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
890 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
891 backupfile = repair._bundle(repo, [parentctxnode], [topmost], root,
891 backupfile = repair._bundle(repo, [parentctxnode], [topmost], root,
892 'histedit')
892 'histedit')
893 state.backupfile = backupfile
893 state.backupfile = backupfile
894
894
895 # preprocess rules so that we can hide inner folds from the user
895 # preprocess rules so that we can hide inner folds from the user
896 # and only show one editor
896 # and only show one editor
897 rules = state.rules[:]
897 rules = state.rules[:]
898 for idx, ((action, ha), (nextact, unused)) in enumerate(
898 for idx, ((action, ha), (nextact, unused)) in enumerate(
899 zip(rules, rules[1:] + [(None, None)])):
899 zip(rules, rules[1:] + [(None, None)])):
900 if action == 'fold' and nextact == 'fold':
900 if action == 'fold' and nextact == 'fold':
901 state.rules[idx] = '_multifold', ha
901 state.rules[idx] = '_multifold', ha
902
902
903 while state.rules:
903 while state.rules:
904 state.write()
904 state.write()
905 action, ha = state.rules.pop(0)
905 action, ha = state.rules.pop(0)
906 ui.debug('histedit: processing %s %s\n' % (action, ha[:12]))
906 ui.debug('histedit: processing %s %s\n' % (action, ha[:12]))
907 actobj = actiontable[action].fromrule(state, ha)
907 actobj = actiontable[action].fromrule(state, ha)
908 parentctx, replacement_ = actobj.run()
908 parentctx, replacement_ = actobj.run()
909 state.parentctxnode = parentctx.node()
909 state.parentctxnode = parentctx.node()
910 state.replacements.extend(replacement_)
910 state.replacements.extend(replacement_)
911 state.write()
911 state.write()
912
912
913 hg.update(repo, state.parentctxnode)
913 hg.update(repo, state.parentctxnode)
914
914
915 mapping, tmpnodes, created, ntm = processreplacement(state)
915 mapping, tmpnodes, created, ntm = processreplacement(state)
916 if mapping:
916 if mapping:
917 for prec, succs in mapping.iteritems():
917 for prec, succs in mapping.iteritems():
918 if not succs:
918 if not succs:
919 ui.debug('histedit: %s is dropped\n' % node.short(prec))
919 ui.debug('histedit: %s is dropped\n' % node.short(prec))
920 else:
920 else:
921 ui.debug('histedit: %s is replaced by %s\n' % (
921 ui.debug('histedit: %s is replaced by %s\n' % (
922 node.short(prec), node.short(succs[0])))
922 node.short(prec), node.short(succs[0])))
923 if len(succs) > 1:
923 if len(succs) > 1:
924 m = 'histedit: %s'
924 m = 'histedit: %s'
925 for n in succs[1:]:
925 for n in succs[1:]:
926 ui.debug(m % node.short(n))
926 ui.debug(m % node.short(n))
927
927
928 if supportsmarkers:
929 # Only create markers if the temp nodes weren't already removed.
930 obsolete.createmarkers(repo, ((repo[t],()) for t in sorted(tmpnodes)
931 if t in repo))
932 else:
933 cleanupnode(ui, repo, 'temp', tmpnodes)
934
928 if not state.keep:
935 if not state.keep:
929 if mapping:
936 if mapping:
930 movebookmarks(ui, repo, mapping, state.topmost, ntm)
937 movebookmarks(ui, repo, mapping, state.topmost, ntm)
931 # TODO update mq state
938 # TODO update mq state
932 if supportsmarkers:
939 if supportsmarkers:
933 markers = []
940 markers = []
934 # sort by revision number because it sound "right"
941 # sort by revision number because it sound "right"
935 for prec in sorted(mapping, key=repo.changelog.rev):
942 for prec in sorted(mapping, key=repo.changelog.rev):
936 succs = mapping[prec]
943 succs = mapping[prec]
937 markers.append((repo[prec],
944 markers.append((repo[prec],
938 tuple(repo[s] for s in succs)))
945 tuple(repo[s] for s in succs)))
939 if markers:
946 if markers:
940 obsolete.createmarkers(repo, markers)
947 obsolete.createmarkers(repo, markers)
941 else:
948 else:
942 cleanupnode(ui, repo, 'replaced', mapping)
949 cleanupnode(ui, repo, 'replaced', mapping)
943
950
944 cleanupnode(ui, repo, 'temp', tmpnodes)
945 state.clear()
951 state.clear()
946 if os.path.exists(repo.sjoin('undo')):
952 if os.path.exists(repo.sjoin('undo')):
947 os.unlink(repo.sjoin('undo'))
953 os.unlink(repo.sjoin('undo'))
948
954
949 def bootstrapcontinue(ui, state, opts):
955 def bootstrapcontinue(ui, state, opts):
950 repo = state.repo
956 repo = state.repo
951 if state.rules:
957 if state.rules:
952 action, currentnode = state.rules.pop(0)
958 action, currentnode = state.rules.pop(0)
953
959
954 actobj = actiontable[action].fromrule(state, currentnode)
960 actobj = actiontable[action].fromrule(state, currentnode)
955
961
956 s = repo.status()
962 s = repo.status()
957 if s.modified or s.added or s.removed or s.deleted:
963 if s.modified or s.added or s.removed or s.deleted:
958 actobj.continuedirty()
964 actobj.continuedirty()
959 s = repo.status()
965 s = repo.status()
960 if s.modified or s.added or s.removed or s.deleted:
966 if s.modified or s.added or s.removed or s.deleted:
961 raise error.Abort(_("working copy still dirty"))
967 raise error.Abort(_("working copy still dirty"))
962
968
963 parentctx, replacements = actobj.continueclean()
969 parentctx, replacements = actobj.continueclean()
964
970
965 state.parentctxnode = parentctx.node()
971 state.parentctxnode = parentctx.node()
966 state.replacements.extend(replacements)
972 state.replacements.extend(replacements)
967
973
968 return state
974 return state
969
975
970 def between(repo, old, new, keep):
976 def between(repo, old, new, keep):
971 """select and validate the set of revision to edit
977 """select and validate the set of revision to edit
972
978
973 When keep is false, the specified set can't have children."""
979 When keep is false, the specified set can't have children."""
974 ctxs = list(repo.set('%n::%n', old, new))
980 ctxs = list(repo.set('%n::%n', old, new))
975 if ctxs and not keep:
981 if ctxs and not keep:
976 if (not obsolete.isenabled(repo, obsolete.allowunstableopt) and
982 if (not obsolete.isenabled(repo, obsolete.allowunstableopt) and
977 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
983 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
978 raise error.Abort(_('cannot edit history that would orphan nodes'))
984 raise error.Abort(_('cannot edit history that would orphan nodes'))
979 if repo.revs('(%ld) and merge()', ctxs):
985 if repo.revs('(%ld) and merge()', ctxs):
980 raise error.Abort(_('cannot edit history that contains merges'))
986 raise error.Abort(_('cannot edit history that contains merges'))
981 root = ctxs[0] # list is already sorted by repo.set
987 root = ctxs[0] # list is already sorted by repo.set
982 if not root.mutable():
988 if not root.mutable():
983 raise error.Abort(_('cannot edit public changeset: %s') % root,
989 raise error.Abort(_('cannot edit public changeset: %s') % root,
984 hint=_('see "hg help phases" for details'))
990 hint=_('see "hg help phases" for details'))
985 return [c.node() for c in ctxs]
991 return [c.node() for c in ctxs]
986
992
987 def makedesc(repo, action, rev):
993 def makedesc(repo, action, rev):
988 """build a initial action line for a ctx
994 """build a initial action line for a ctx
989
995
990 line are in the form:
996 line are in the form:
991
997
992 <action> <hash> <rev> <summary>
998 <action> <hash> <rev> <summary>
993 """
999 """
994 ctx = repo[rev]
1000 ctx = repo[rev]
995 summary = ''
1001 summary = ''
996 if ctx.description():
1002 if ctx.description():
997 summary = ctx.description().splitlines()[0]
1003 summary = ctx.description().splitlines()[0]
998 line = '%s %s %d %s' % (action, ctx, ctx.rev(), summary)
1004 line = '%s %s %d %s' % (action, ctx, ctx.rev(), summary)
999 # trim to 80 columns so it's not stupidly wide in my editor
1005 # trim to 80 columns so it's not stupidly wide in my editor
1000 maxlen = repo.ui.configint('histedit', 'linelen', default=80)
1006 maxlen = repo.ui.configint('histedit', 'linelen', default=80)
1001 maxlen = max(maxlen, 22) # avoid truncating hash
1007 maxlen = max(maxlen, 22) # avoid truncating hash
1002 return util.ellipsis(line, maxlen)
1008 return util.ellipsis(line, maxlen)
1003
1009
1004 def ruleeditor(repo, ui, rules, editcomment=""):
1010 def ruleeditor(repo, ui, rules, editcomment=""):
1005 """open an editor to edit rules
1011 """open an editor to edit rules
1006
1012
1007 rules are in the format [ [act, ctx], ...] like in state.rules
1013 rules are in the format [ [act, ctx], ...] like in state.rules
1008 """
1014 """
1009 rules = '\n'.join([makedesc(repo, act, rev) for [act, rev] in rules])
1015 rules = '\n'.join([makedesc(repo, act, rev) for [act, rev] in rules])
1010 rules += '\n\n'
1016 rules += '\n\n'
1011 rules += editcomment
1017 rules += editcomment
1012 rules = ui.edit(rules, ui.username())
1018 rules = ui.edit(rules, ui.username())
1013
1019
1014 # Save edit rules in .hg/histedit-last-edit.txt in case
1020 # Save edit rules in .hg/histedit-last-edit.txt in case
1015 # the user needs to ask for help after something
1021 # the user needs to ask for help after something
1016 # surprising happens.
1022 # surprising happens.
1017 f = open(repo.join('histedit-last-edit.txt'), 'w')
1023 f = open(repo.join('histedit-last-edit.txt'), 'w')
1018 f.write(rules)
1024 f.write(rules)
1019 f.close()
1025 f.close()
1020
1026
1021 return rules
1027 return rules
1022
1028
1023 def verifyrules(rules, repo, ctxs):
1029 def verifyrules(rules, repo, ctxs):
1024 """Verify that there exists exactly one edit rule per given changeset.
1030 """Verify that there exists exactly one edit rule per given changeset.
1025
1031
1026 Will abort if there are to many or too few rules, a malformed rule,
1032 Will abort if there are to many or too few rules, a malformed rule,
1027 or a rule on a changeset outside of the user-given range.
1033 or a rule on a changeset outside of the user-given range.
1028 """
1034 """
1029 parsed = []
1035 parsed = []
1030 expected = set(c.hex() for c in ctxs)
1036 expected = set(c.hex() for c in ctxs)
1031 seen = set()
1037 seen = set()
1032 for r in rules:
1038 for r in rules:
1033 if ' ' not in r:
1039 if ' ' not in r:
1034 raise error.Abort(_('malformed line "%s"') % r)
1040 raise error.Abort(_('malformed line "%s"') % r)
1035 action, rest = r.split(' ', 1)
1041 action, rest = r.split(' ', 1)
1036 ha = rest.strip().split(' ', 1)[0]
1042 ha = rest.strip().split(' ', 1)[0]
1037 try:
1043 try:
1038 ha = repo[ha].hex()
1044 ha = repo[ha].hex()
1039 except error.RepoError:
1045 except error.RepoError:
1040 raise error.Abort(_('unknown changeset %s listed') % ha[:12])
1046 raise error.Abort(_('unknown changeset %s listed') % ha[:12])
1041 if ha not in expected:
1047 if ha not in expected:
1042 raise error.Abort(
1048 raise error.Abort(
1043 _('may not use changesets other than the ones listed'))
1049 _('may not use changesets other than the ones listed'))
1044 if ha in seen:
1050 if ha in seen:
1045 raise error.Abort(_('duplicated command for changeset %s') %
1051 raise error.Abort(_('duplicated command for changeset %s') %
1046 ha[:12])
1052 ha[:12])
1047 seen.add(ha)
1053 seen.add(ha)
1048 if action not in actiontable or action.startswith('_'):
1054 if action not in actiontable or action.startswith('_'):
1049 raise error.Abort(_('unknown action "%s"') % action)
1055 raise error.Abort(_('unknown action "%s"') % action)
1050 parsed.append([action, ha])
1056 parsed.append([action, ha])
1051 missing = sorted(expected - seen) # sort to stabilize output
1057 missing = sorted(expected - seen) # sort to stabilize output
1052 if missing:
1058 if missing:
1053 raise error.Abort(_('missing rules for changeset %s') %
1059 raise error.Abort(_('missing rules for changeset %s') %
1054 missing[0][:12],
1060 missing[0][:12],
1055 hint=_('do you want to use the drop action?'))
1061 hint=_('do you want to use the drop action?'))
1056 return parsed
1062 return parsed
1057
1063
1058 def newnodestoabort(state):
1064 def newnodestoabort(state):
1059 """process the list of replacements to return
1065 """process the list of replacements to return
1060
1066
1061 1) the list of final node
1067 1) the list of final node
1062 2) the list of temporary node
1068 2) the list of temporary node
1063
1069
1064 This meant to be used on abort as less data are required in this case.
1070 This meant to be used on abort as less data are required in this case.
1065 """
1071 """
1066 replacements = state.replacements
1072 replacements = state.replacements
1067 allsuccs = set()
1073 allsuccs = set()
1068 replaced = set()
1074 replaced = set()
1069 for rep in replacements:
1075 for rep in replacements:
1070 allsuccs.update(rep[1])
1076 allsuccs.update(rep[1])
1071 replaced.add(rep[0])
1077 replaced.add(rep[0])
1072 newnodes = allsuccs - replaced
1078 newnodes = allsuccs - replaced
1073 tmpnodes = allsuccs & replaced
1079 tmpnodes = allsuccs & replaced
1074 return newnodes, tmpnodes
1080 return newnodes, tmpnodes
1075
1081
1076
1082
1077 def processreplacement(state):
1083 def processreplacement(state):
1078 """process the list of replacements to return
1084 """process the list of replacements to return
1079
1085
1080 1) the final mapping between original and created nodes
1086 1) the final mapping between original and created nodes
1081 2) the list of temporary node created by histedit
1087 2) the list of temporary node created by histedit
1082 3) the list of new commit created by histedit"""
1088 3) the list of new commit created by histedit"""
1083 replacements = state.replacements
1089 replacements = state.replacements
1084 allsuccs = set()
1090 allsuccs = set()
1085 replaced = set()
1091 replaced = set()
1086 fullmapping = {}
1092 fullmapping = {}
1087 # initialize basic set
1093 # initialize basic set
1088 # fullmapping records all operations recorded in replacement
1094 # fullmapping records all operations recorded in replacement
1089 for rep in replacements:
1095 for rep in replacements:
1090 allsuccs.update(rep[1])
1096 allsuccs.update(rep[1])
1091 replaced.add(rep[0])
1097 replaced.add(rep[0])
1092 fullmapping.setdefault(rep[0], set()).update(rep[1])
1098 fullmapping.setdefault(rep[0], set()).update(rep[1])
1093 new = allsuccs - replaced
1099 new = allsuccs - replaced
1094 tmpnodes = allsuccs & replaced
1100 tmpnodes = allsuccs & replaced
1095 # Reduce content fullmapping into direct relation between original nodes
1101 # Reduce content fullmapping into direct relation between original nodes
1096 # and final node created during history edition
1102 # and final node created during history edition
1097 # Dropped changeset are replaced by an empty list
1103 # Dropped changeset are replaced by an empty list
1098 toproceed = set(fullmapping)
1104 toproceed = set(fullmapping)
1099 final = {}
1105 final = {}
1100 while toproceed:
1106 while toproceed:
1101 for x in list(toproceed):
1107 for x in list(toproceed):
1102 succs = fullmapping[x]
1108 succs = fullmapping[x]
1103 for s in list(succs):
1109 for s in list(succs):
1104 if s in toproceed:
1110 if s in toproceed:
1105 # non final node with unknown closure
1111 # non final node with unknown closure
1106 # We can't process this now
1112 # We can't process this now
1107 break
1113 break
1108 elif s in final:
1114 elif s in final:
1109 # non final node, replace with closure
1115 # non final node, replace with closure
1110 succs.remove(s)
1116 succs.remove(s)
1111 succs.update(final[s])
1117 succs.update(final[s])
1112 else:
1118 else:
1113 final[x] = succs
1119 final[x] = succs
1114 toproceed.remove(x)
1120 toproceed.remove(x)
1115 # remove tmpnodes from final mapping
1121 # remove tmpnodes from final mapping
1116 for n in tmpnodes:
1122 for n in tmpnodes:
1117 del final[n]
1123 del final[n]
1118 # we expect all changes involved in final to exist in the repo
1124 # we expect all changes involved in final to exist in the repo
1119 # turn `final` into list (topologically sorted)
1125 # turn `final` into list (topologically sorted)
1120 nm = state.repo.changelog.nodemap
1126 nm = state.repo.changelog.nodemap
1121 for prec, succs in final.items():
1127 for prec, succs in final.items():
1122 final[prec] = sorted(succs, key=nm.get)
1128 final[prec] = sorted(succs, key=nm.get)
1123
1129
1124 # computed topmost element (necessary for bookmark)
1130 # computed topmost element (necessary for bookmark)
1125 if new:
1131 if new:
1126 newtopmost = sorted(new, key=state.repo.changelog.rev)[-1]
1132 newtopmost = sorted(new, key=state.repo.changelog.rev)[-1]
1127 elif not final:
1133 elif not final:
1128 # Nothing rewritten at all. we won't need `newtopmost`
1134 # Nothing rewritten at all. we won't need `newtopmost`
1129 # It is the same as `oldtopmost` and `processreplacement` know it
1135 # It is the same as `oldtopmost` and `processreplacement` know it
1130 newtopmost = None
1136 newtopmost = None
1131 else:
1137 else:
1132 # every body died. The newtopmost is the parent of the root.
1138 # every body died. The newtopmost is the parent of the root.
1133 r = state.repo.changelog.rev
1139 r = state.repo.changelog.rev
1134 newtopmost = state.repo[sorted(final, key=r)[0]].p1().node()
1140 newtopmost = state.repo[sorted(final, key=r)[0]].p1().node()
1135
1141
1136 return final, tmpnodes, new, newtopmost
1142 return final, tmpnodes, new, newtopmost
1137
1143
1138 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
1144 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
1139 """Move bookmark from old to newly created node"""
1145 """Move bookmark from old to newly created node"""
1140 if not mapping:
1146 if not mapping:
1141 # if nothing got rewritten there is not purpose for this function
1147 # if nothing got rewritten there is not purpose for this function
1142 return
1148 return
1143 moves = []
1149 moves = []
1144 for bk, old in sorted(repo._bookmarks.iteritems()):
1150 for bk, old in sorted(repo._bookmarks.iteritems()):
1145 if old == oldtopmost:
1151 if old == oldtopmost:
1146 # special case ensure bookmark stay on tip.
1152 # special case ensure bookmark stay on tip.
1147 #
1153 #
1148 # This is arguably a feature and we may only want that for the
1154 # This is arguably a feature and we may only want that for the
1149 # active bookmark. But the behavior is kept compatible with the old
1155 # active bookmark. But the behavior is kept compatible with the old
1150 # version for now.
1156 # version for now.
1151 moves.append((bk, newtopmost))
1157 moves.append((bk, newtopmost))
1152 continue
1158 continue
1153 base = old
1159 base = old
1154 new = mapping.get(base, None)
1160 new = mapping.get(base, None)
1155 if new is None:
1161 if new is None:
1156 continue
1162 continue
1157 while not new:
1163 while not new:
1158 # base is killed, trying with parent
1164 # base is killed, trying with parent
1159 base = repo[base].p1().node()
1165 base = repo[base].p1().node()
1160 new = mapping.get(base, (base,))
1166 new = mapping.get(base, (base,))
1161 # nothing to move
1167 # nothing to move
1162 moves.append((bk, new[-1]))
1168 moves.append((bk, new[-1]))
1163 if moves:
1169 if moves:
1164 marks = repo._bookmarks
1170 marks = repo._bookmarks
1165 for mark, new in moves:
1171 for mark, new in moves:
1166 old = marks[mark]
1172 old = marks[mark]
1167 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
1173 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
1168 % (mark, node.short(old), node.short(new)))
1174 % (mark, node.short(old), node.short(new)))
1169 marks[mark] = new
1175 marks[mark] = new
1170 marks.write()
1176 marks.write()
1171
1177
1172 def cleanupnode(ui, repo, name, nodes):
1178 def cleanupnode(ui, repo, name, nodes):
1173 """strip a group of nodes from the repository
1179 """strip a group of nodes from the repository
1174
1180
1175 The set of node to strip may contains unknown nodes."""
1181 The set of node to strip may contains unknown nodes."""
1176 ui.debug('should strip %s nodes %s\n' %
1182 ui.debug('should strip %s nodes %s\n' %
1177 (name, ', '.join([node.short(n) for n in nodes])))
1183 (name, ', '.join([node.short(n) for n in nodes])))
1178 lock = None
1184 lock = None
1179 try:
1185 try:
1180 lock = repo.lock()
1186 lock = repo.lock()
1181 # do not let filtering get in the way of the cleanse
1187 # do not let filtering get in the way of the cleanse
1182 # we should probably get rid of obsolescence marker created during the
1188 # we should probably get rid of obsolescence marker created during the
1183 # histedit, but we currently do not have such information.
1189 # histedit, but we currently do not have such information.
1184 repo = repo.unfiltered()
1190 repo = repo.unfiltered()
1185 # Find all nodes that need to be stripped
1191 # Find all nodes that need to be stripped
1186 # (we use %lr instead of %ln to silently ignore unknown items)
1192 # (we use %lr instead of %ln to silently ignore unknown items)
1187 nm = repo.changelog.nodemap
1193 nm = repo.changelog.nodemap
1188 nodes = sorted(n for n in nodes if n in nm)
1194 nodes = sorted(n for n in nodes if n in nm)
1189 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
1195 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
1190 for c in roots:
1196 for c in roots:
1191 # We should process node in reverse order to strip tip most first.
1197 # We should process node in reverse order to strip tip most first.
1192 # but this trigger a bug in changegroup hook.
1198 # but this trigger a bug in changegroup hook.
1193 # This would reduce bundle overhead
1199 # This would reduce bundle overhead
1194 repair.strip(ui, repo, c)
1200 repair.strip(ui, repo, c)
1195 finally:
1201 finally:
1196 release(lock)
1202 release(lock)
1197
1203
1198 def stripwrapper(orig, ui, repo, nodelist, *args, **kwargs):
1204 def stripwrapper(orig, ui, repo, nodelist, *args, **kwargs):
1199 if isinstance(nodelist, str):
1205 if isinstance(nodelist, str):
1200 nodelist = [nodelist]
1206 nodelist = [nodelist]
1201 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
1207 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
1202 state = histeditstate(repo)
1208 state = histeditstate(repo)
1203 state.read()
1209 state.read()
1204 histedit_nodes = set([repo[rulehash].node() for (action, rulehash)
1210 histedit_nodes = set([repo[rulehash].node() for (action, rulehash)
1205 in state.rules if rulehash in repo])
1211 in state.rules if rulehash in repo])
1206 strip_nodes = set([repo[n].node() for n in nodelist])
1212 strip_nodes = set([repo[n].node() for n in nodelist])
1207 common_nodes = histedit_nodes & strip_nodes
1213 common_nodes = histedit_nodes & strip_nodes
1208 if common_nodes:
1214 if common_nodes:
1209 raise error.Abort(_("histedit in progress, can't strip %s")
1215 raise error.Abort(_("histedit in progress, can't strip %s")
1210 % ', '.join(node.short(x) for x in common_nodes))
1216 % ', '.join(node.short(x) for x in common_nodes))
1211 return orig(ui, repo, nodelist, *args, **kwargs)
1217 return orig(ui, repo, nodelist, *args, **kwargs)
1212
1218
1213 extensions.wrapfunction(repair, 'strip', stripwrapper)
1219 extensions.wrapfunction(repair, 'strip', stripwrapper)
1214
1220
1215 def summaryhook(ui, repo):
1221 def summaryhook(ui, repo):
1216 if not os.path.exists(repo.join('histedit-state')):
1222 if not os.path.exists(repo.join('histedit-state')):
1217 return
1223 return
1218 state = histeditstate(repo)
1224 state = histeditstate(repo)
1219 state.read()
1225 state.read()
1220 if state.rules:
1226 if state.rules:
1221 # i18n: column positioning for "hg summary"
1227 # i18n: column positioning for "hg summary"
1222 ui.write(_('hist: %s (histedit --continue)\n') %
1228 ui.write(_('hist: %s (histedit --continue)\n') %
1223 (ui.label(_('%d remaining'), 'histedit.remaining') %
1229 (ui.label(_('%d remaining'), 'histedit.remaining') %
1224 len(state.rules)))
1230 len(state.rules)))
1225
1231
1226 def extsetup(ui):
1232 def extsetup(ui):
1227 cmdutil.summaryhooks.add('histedit', summaryhook)
1233 cmdutil.summaryhooks.add('histedit', summaryhook)
1228 cmdutil.unfinishedstates.append(
1234 cmdutil.unfinishedstates.append(
1229 ['histedit-state', False, True, _('histedit in progress'),
1235 ['histedit-state', False, True, _('histedit in progress'),
1230 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
1236 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
@@ -1,348 +1,349 b''
1 Test argument handling and various data parsing
1 Test argument handling and various data parsing
2 ==================================================
2 ==================================================
3
3
4
4
5 Enable extensions used by this test.
5 Enable extensions used by this test.
6 $ cat >>$HGRCPATH <<EOF
6 $ cat >>$HGRCPATH <<EOF
7 > [extensions]
7 > [extensions]
8 > histedit=
8 > histedit=
9 > EOF
9 > EOF
10
10
11 Repo setup.
11 Repo setup.
12 $ hg init foo
12 $ hg init foo
13 $ cd foo
13 $ cd foo
14 $ echo alpha >> alpha
14 $ echo alpha >> alpha
15 $ hg addr
15 $ hg addr
16 adding alpha
16 adding alpha
17 $ hg ci -m one
17 $ hg ci -m one
18 $ echo alpha >> alpha
18 $ echo alpha >> alpha
19 $ hg ci -m two
19 $ hg ci -m two
20 $ echo alpha >> alpha
20 $ echo alpha >> alpha
21 $ hg ci -m three
21 $ hg ci -m three
22 $ echo alpha >> alpha
22 $ echo alpha >> alpha
23 $ hg ci -m four
23 $ hg ci -m four
24 $ echo alpha >> alpha
24 $ echo alpha >> alpha
25 $ hg ci -m five
25 $ hg ci -m five
26
26
27 $ hg log --style compact --graph
27 $ hg log --style compact --graph
28 @ 4[tip] 08d98a8350f3 1970-01-01 00:00 +0000 test
28 @ 4[tip] 08d98a8350f3 1970-01-01 00:00 +0000 test
29 | five
29 | five
30 |
30 |
31 o 3 c8e68270e35a 1970-01-01 00:00 +0000 test
31 o 3 c8e68270e35a 1970-01-01 00:00 +0000 test
32 | four
32 | four
33 |
33 |
34 o 2 eb57da33312f 1970-01-01 00:00 +0000 test
34 o 2 eb57da33312f 1970-01-01 00:00 +0000 test
35 | three
35 | three
36 |
36 |
37 o 1 579e40513370 1970-01-01 00:00 +0000 test
37 o 1 579e40513370 1970-01-01 00:00 +0000 test
38 | two
38 | two
39 |
39 |
40 o 0 6058cbb6cfd7 1970-01-01 00:00 +0000 test
40 o 0 6058cbb6cfd7 1970-01-01 00:00 +0000 test
41 one
41 one
42
42
43
43
44 histedit --continue/--abort with no existing state
44 histedit --continue/--abort with no existing state
45 --------------------------------------------------
45 --------------------------------------------------
46
46
47 $ hg histedit --continue
47 $ hg histedit --continue
48 abort: no histedit in progress
48 abort: no histedit in progress
49 [255]
49 [255]
50 $ hg histedit --abort
50 $ hg histedit --abort
51 abort: no histedit in progress
51 abort: no histedit in progress
52 [255]
52 [255]
53
53
54 Run a dummy edit to make sure we get tip^^ correctly via revsingle.
54 Run a dummy edit to make sure we get tip^^ correctly via revsingle.
55 --------------------------------------------------------------------
55 --------------------------------------------------------------------
56
56
57 $ HGEDITOR=cat hg histedit "tip^^"
57 $ HGEDITOR=cat hg histedit "tip^^"
58 pick eb57da33312f 2 three
58 pick eb57da33312f 2 three
59 pick c8e68270e35a 3 four
59 pick c8e68270e35a 3 four
60 pick 08d98a8350f3 4 five
60 pick 08d98a8350f3 4 five
61
61
62 # Edit history between eb57da33312f and 08d98a8350f3
62 # Edit history between eb57da33312f and 08d98a8350f3
63 #
63 #
64 # Commits are listed from least to most recent
64 # Commits are listed from least to most recent
65 #
65 #
66 # Commands:
66 # Commands:
67 # p, pick = use commit
67 # p, pick = use commit
68 # e, edit = use commit, but stop for amending
68 # e, edit = use commit, but stop for amending
69 # f, fold = use commit, but combine it with the one above
69 # f, fold = use commit, but combine it with the one above
70 # r, roll = like fold, but discard this commit's description
70 # r, roll = like fold, but discard this commit's description
71 # d, drop = remove commit from history
71 # d, drop = remove commit from history
72 # m, mess = edit commit message without changing commit content
72 # m, mess = edit commit message without changing commit content
73 #
73 #
74 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
75
75
76 Run on a revision not ancestors of the current working directory.
76 Run on a revision not ancestors of the current working directory.
77 --------------------------------------------------------------------
77 --------------------------------------------------------------------
78
78
79 $ hg up 2
79 $ hg up 2
80 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 $ hg histedit -r 4
81 $ hg histedit -r 4
82 abort: 08d98a8350f3 is not an ancestor of working directory
82 abort: 08d98a8350f3 is not an ancestor of working directory
83 [255]
83 [255]
84 $ hg up --quiet
84 $ hg up --quiet
85
85
86
86
87 Test that we pick the minimum of a revrange
87 Test that we pick the minimum of a revrange
88 ---------------------------------------
88 ---------------------------------------
89
89
90 $ HGEDITOR=cat hg histedit '2::' --commands - << EOF
90 $ HGEDITOR=cat hg histedit '2::' --commands - << EOF
91 > pick eb57da33312f 2 three
91 > pick eb57da33312f 2 three
92 > pick c8e68270e35a 3 four
92 > pick c8e68270e35a 3 four
93 > pick 08d98a8350f3 4 five
93 > pick 08d98a8350f3 4 five
94 > EOF
94 > EOF
95 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
96 $ hg up --quiet
96 $ hg up --quiet
97
97
98 $ HGEDITOR=cat hg histedit 'tip:2' --commands - << EOF
98 $ HGEDITOR=cat hg histedit 'tip:2' --commands - << EOF
99 > pick eb57da33312f 2 three
99 > pick eb57da33312f 2 three
100 > pick c8e68270e35a 3 four
100 > pick c8e68270e35a 3 four
101 > pick 08d98a8350f3 4 five
101 > pick 08d98a8350f3 4 five
102 > EOF
102 > EOF
103 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 $ hg up --quiet
104 $ hg up --quiet
105
105
106 Test config specified default
106 Test config specified default
107 -----------------------------
107 -----------------------------
108
108
109 $ HGEDITOR=cat hg histedit --config "histedit.defaultrev=only(.) - ::eb57da33312f" --commands - << EOF
109 $ HGEDITOR=cat hg histedit --config "histedit.defaultrev=only(.) - ::eb57da33312f" --commands - << EOF
110 > pick c8e68270e35a 3 four
110 > pick c8e68270e35a 3 four
111 > pick 08d98a8350f3 4 five
111 > pick 08d98a8350f3 4 five
112 > EOF
112 > EOF
113 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
113 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
114
114
115 Run on a revision not descendants of the initial parent
115 Run on a revision not descendants of the initial parent
116 --------------------------------------------------------------------
116 --------------------------------------------------------------------
117
117
118 Test the message shown for inconsistent histedit state, which may be
118 Test the message shown for inconsistent histedit state, which may be
119 created (and forgotten) by Mercurial earlier than 2.7. This emulates
119 created (and forgotten) by Mercurial earlier than 2.7. This emulates
120 Mercurial earlier than 2.7 by renaming ".hg/histedit-state"
120 Mercurial earlier than 2.7 by renaming ".hg/histedit-state"
121 temporarily.
121 temporarily.
122
122
123 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
123 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
124 @ 4 08d9 five
124 @ 4 08d9 five
125 |
125 |
126 o 3 c8e6 four
126 o 3 c8e6 four
127 |
127 |
128 o 2 eb57 three
128 o 2 eb57 three
129 |
129 |
130 $ HGEDITOR=cat hg histedit -r 4 --commands - << EOF
130 $ HGEDITOR=cat hg histedit -r 4 --commands - << EOF
131 > edit 08d98a8350f3 4 five
131 > edit 08d98a8350f3 4 five
132 > EOF
132 > EOF
133 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
133 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
134 reverting alpha
134 reverting alpha
135 Make changes as needed, you may commit or record as needed now.
135 Make changes as needed, you may commit or record as needed now.
136 When you are finished, run hg histedit --continue to resume.
136 When you are finished, run hg histedit --continue to resume.
137 [1]
137 [1]
138
138
139 $ mv .hg/histedit-state .hg/histedit-state.back
139 $ mv .hg/histedit-state .hg/histedit-state.back
140 $ hg update --quiet --clean 2
140 $ hg update --quiet --clean 2
141 $ echo alpha >> alpha
141 $ echo alpha >> alpha
142 $ mv .hg/histedit-state.back .hg/histedit-state
142 $ mv .hg/histedit-state.back .hg/histedit-state
143
143
144 $ hg histedit --continue
144 $ hg histedit --continue
145 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
145 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg (glob)
146 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg (glob)
147 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
147 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
148 @ 4 f5ed five
148 @ 4 f5ed five
149 |
149 |
150 | o 3 c8e6 four
150 | o 3 c8e6 four
151 |/
151 |/
152 o 2 eb57 three
152 o 2 eb57 three
153 |
153 |
154
154
155 $ hg unbundle -q $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg
155 $ hg unbundle -q $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg
156 $ hg strip -q -r f5ed --config extensions.strip=
156 $ hg strip -q -r f5ed --config extensions.strip=
157 $ hg up -q 08d98a8350f3
157 $ hg up -q 08d98a8350f3
158
158
159 Test that missing revisions are detected
159 Test that missing revisions are detected
160 ---------------------------------------
160 ---------------------------------------
161
161
162 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
162 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
163 > pick eb57da33312f 2 three
163 > pick eb57da33312f 2 three
164 > pick 08d98a8350f3 4 five
164 > pick 08d98a8350f3 4 five
165 > EOF
165 > EOF
166 abort: missing rules for changeset c8e68270e35a
166 abort: missing rules for changeset c8e68270e35a
167 (do you want to use the drop action?)
167 (do you want to use the drop action?)
168 [255]
168 [255]
169
169
170 Test that extra revisions are detected
170 Test that extra revisions are detected
171 ---------------------------------------
171 ---------------------------------------
172
172
173 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
173 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
174 > pick 6058cbb6cfd7 0 one
174 > pick 6058cbb6cfd7 0 one
175 > pick c8e68270e35a 3 four
175 > pick c8e68270e35a 3 four
176 > pick 08d98a8350f3 4 five
176 > pick 08d98a8350f3 4 five
177 > EOF
177 > EOF
178 abort: may not use changesets other than the ones listed
178 abort: may not use changesets other than the ones listed
179 [255]
179 [255]
180
180
181 Test malformed line
181 Test malformed line
182 ---------------------------------------
182 ---------------------------------------
183
183
184 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
184 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
185 > pickeb57da33312f2three
185 > pickeb57da33312f2three
186 > pick c8e68270e35a 3 four
186 > pick c8e68270e35a 3 four
187 > pick 08d98a8350f3 4 five
187 > pick 08d98a8350f3 4 five
188 > EOF
188 > EOF
189 abort: malformed line "pickeb57da33312f2three"
189 abort: malformed line "pickeb57da33312f2three"
190 [255]
190 [255]
191
191
192 Test unknown changeset
192 Test unknown changeset
193 ---------------------------------------
193 ---------------------------------------
194
194
195 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
195 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
196 > pick 0123456789ab 2 three
196 > pick 0123456789ab 2 three
197 > pick c8e68270e35a 3 four
197 > pick c8e68270e35a 3 four
198 > pick 08d98a8350f3 4 five
198 > pick 08d98a8350f3 4 five
199 > EOF
199 > EOF
200 abort: unknown changeset 0123456789ab listed
200 abort: unknown changeset 0123456789ab listed
201 [255]
201 [255]
202
202
203 Test unknown command
203 Test unknown command
204 ---------------------------------------
204 ---------------------------------------
205
205
206 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
206 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
207 > coin eb57da33312f 2 three
207 > coin eb57da33312f 2 three
208 > pick c8e68270e35a 3 four
208 > pick c8e68270e35a 3 four
209 > pick 08d98a8350f3 4 five
209 > pick 08d98a8350f3 4 five
210 > EOF
210 > EOF
211 abort: unknown action "coin"
211 abort: unknown action "coin"
212 [255]
212 [255]
213
213
214 Test duplicated changeset
214 Test duplicated changeset
215 ---------------------------------------
215 ---------------------------------------
216
216
217 So one is missing and one appear twice.
217 So one is missing and one appear twice.
218
218
219 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
219 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
220 > pick eb57da33312f 2 three
220 > pick eb57da33312f 2 three
221 > pick eb57da33312f 2 three
221 > pick eb57da33312f 2 three
222 > pick 08d98a8350f3 4 five
222 > pick 08d98a8350f3 4 five
223 > EOF
223 > EOF
224 abort: duplicated command for changeset eb57da33312f
224 abort: duplicated command for changeset eb57da33312f
225 [255]
225 [255]
226
226
227 Test short version of command
227 Test short version of command
228 ---------------------------------------
228 ---------------------------------------
229
229
230 Note: we use varying amounts of white space between command name and changeset
230 Note: we use varying amounts of white space between command name and changeset
231 short hash. This tests issue3893.
231 short hash. This tests issue3893.
232
232
233 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
233 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
234 > pick eb57da33312f 2 three
234 > pick eb57da33312f 2 three
235 > p c8e68270e35a 3 four
235 > p c8e68270e35a 3 four
236 > f 08d98a8350f3 4 five
236 > f 08d98a8350f3 4 five
237 > EOF
237 > EOF
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 reverting alpha
239 reverting alpha
240 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
240 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 four
241 four
242 ***
242 ***
243 five
243 five
244
244
245
245
246
246
247 HG: Enter commit message. Lines beginning with 'HG:' are removed.
247 HG: Enter commit message. Lines beginning with 'HG:' are removed.
248 HG: Leave message empty to abort commit.
248 HG: Leave message empty to abort commit.
249 HG: --
249 HG: --
250 HG: user: test
250 HG: user: test
251 HG: branch 'default'
251 HG: branch 'default'
252 HG: changed alpha
252 HG: changed alpha
253 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
255 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
255 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
256 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/c8e68270e35a-23a13bf9-backup.hg (glob)
256
257
257 $ hg update -q 2
258 $ hg update -q 2
258 $ echo x > x
259 $ echo x > x
259 $ hg add x
260 $ hg add x
260 $ hg commit -m'x' x
261 $ hg commit -m'x' x
261 created new head
262 created new head
262 $ hg histedit -r 'heads(all())'
263 $ hg histedit -r 'heads(all())'
263 abort: The specified revisions must have exactly one common root
264 abort: The specified revisions must have exactly one common root
264 [255]
265 [255]
265
266
266 Test that trimming description using multi-byte characters
267 Test that trimming description using multi-byte characters
267 --------------------------------------------------------------------
268 --------------------------------------------------------------------
268
269
269 $ python <<EOF
270 $ python <<EOF
270 > fp = open('logfile', 'w')
271 > fp = open('logfile', 'w')
271 > fp.write('12345678901234567890123456789012345678901234567890' +
272 > fp.write('12345678901234567890123456789012345678901234567890' +
272 > '12345') # there are 5 more columns for 80 columns
273 > '12345') # there are 5 more columns for 80 columns
273 >
274 >
274 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
275 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
275 > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
276 > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
276 >
277 >
277 > fp.close()
278 > fp.close()
278 > EOF
279 > EOF
279 $ echo xx >> x
280 $ echo xx >> x
280 $ hg --encoding utf-8 commit --logfile logfile
281 $ hg --encoding utf-8 commit --logfile logfile
281
282
282 $ HGEDITOR=cat hg --encoding utf-8 histedit tip
283 $ HGEDITOR=cat hg --encoding utf-8 histedit tip
283 pick 3d3ea1f3a10b 5 1234567890123456789012345678901234567890123456789012345\xe3\x81\x82... (esc)
284 pick 3d3ea1f3a10b 5 1234567890123456789012345678901234567890123456789012345\xe3\x81\x82... (esc)
284
285
285 # Edit history between 3d3ea1f3a10b and 3d3ea1f3a10b
286 # Edit history between 3d3ea1f3a10b and 3d3ea1f3a10b
286 #
287 #
287 # Commits are listed from least to most recent
288 # Commits are listed from least to most recent
288 #
289 #
289 # Commands:
290 # Commands:
290 # p, pick = use commit
291 # p, pick = use commit
291 # e, edit = use commit, but stop for amending
292 # e, edit = use commit, but stop for amending
292 # f, fold = use commit, but combine it with the one above
293 # f, fold = use commit, but combine it with the one above
293 # r, roll = like fold, but discard this commit's description
294 # r, roll = like fold, but discard this commit's description
294 # d, drop = remove commit from history
295 # d, drop = remove commit from history
295 # m, mess = edit commit message without changing commit content
296 # m, mess = edit commit message without changing commit content
296 #
297 #
297 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
298 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
298
299
299 Test --continue with --keep
300 Test --continue with --keep
300
301
301 $ hg strip -q -r . --config extensions.strip=
302 $ hg strip -q -r . --config extensions.strip=
302 $ hg histedit '.^' -q --keep --commands - << EOF
303 $ hg histedit '.^' -q --keep --commands - << EOF
303 > edit eb57da33312f 2 three
304 > edit eb57da33312f 2 three
304 > pick f3cfcca30c44 4 x
305 > pick f3cfcca30c44 4 x
305 > EOF
306 > EOF
306 Make changes as needed, you may commit or record as needed now.
307 Make changes as needed, you may commit or record as needed now.
307 When you are finished, run hg histedit --continue to resume.
308 When you are finished, run hg histedit --continue to resume.
308 [1]
309 [1]
309 $ echo edit >> alpha
310 $ echo edit >> alpha
310 $ hg histedit -q --continue
311 $ hg histedit -q --continue
311 $ hg log -G -T '{rev}:{node|short} {desc}'
312 $ hg log -G -T '{rev}:{node|short} {desc}'
312 @ 6:8fda0c726bf2 x
313 @ 6:8fda0c726bf2 x
313 |
314 |
314 o 5:63379946892c three
315 o 5:63379946892c three
315 |
316 |
316 | o 4:f3cfcca30c44 x
317 | o 4:f3cfcca30c44 x
317 | |
318 | |
318 | | o 3:2a30f3cfee78 four
319 | | o 3:2a30f3cfee78 four
319 | |/ ***
320 | |/ ***
320 | | five
321 | | five
321 | o 2:eb57da33312f three
322 | o 2:eb57da33312f three
322 |/
323 |/
323 o 1:579e40513370 two
324 o 1:579e40513370 two
324 |
325 |
325 o 0:6058cbb6cfd7 one
326 o 0:6058cbb6cfd7 one
326
327
327
328
328 Test that abort fails gracefully on exception
329 Test that abort fails gracefully on exception
329 ----------------------------------------------
330 ----------------------------------------------
330 $ hg histedit . -q --commands - << EOF
331 $ hg histedit . -q --commands - << EOF
331 > edit 8fda0c726bf2 6 x
332 > edit 8fda0c726bf2 6 x
332 > EOF
333 > EOF
333 Make changes as needed, you may commit or record as needed now.
334 Make changes as needed, you may commit or record as needed now.
334 When you are finished, run hg histedit --continue to resume.
335 When you are finished, run hg histedit --continue to resume.
335 [1]
336 [1]
336 Corrupt histedit state file
337 Corrupt histedit state file
337 $ sed 's/8fda0c726bf2/123456789012/' .hg/histedit-state > ../corrupt-histedit
338 $ sed 's/8fda0c726bf2/123456789012/' .hg/histedit-state > ../corrupt-histedit
338 $ mv ../corrupt-histedit .hg/histedit-state
339 $ mv ../corrupt-histedit .hg/histedit-state
339 $ hg histedit --abort
340 $ hg histedit --abort
340 warning: encountered an exception during histedit --abort; the repository may not have been completely cleaned up
341 warning: encountered an exception during histedit --abort; the repository may not have been completely cleaned up
341 abort: No such file or directory: * (glob)
342 abort: No such file or directory: * (glob)
342 [255]
343 [255]
343 Histedit state has been exited
344 Histedit state has been exited
344 $ hg summary -q
345 $ hg summary -q
345 parent: 5:63379946892c
346 parent: 5:63379946892c
346 commit: 1 added, 1 unknown (new branch head)
347 commit: 1 added, 1 unknown (new branch head)
347 update: 4 new changesets (update)
348 update: 4 new changesets (update)
348
349
@@ -1,182 +1,182 b''
1 $ . "$TESTDIR/histedit-helpers.sh"
1 $ . "$TESTDIR/histedit-helpers.sh"
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > histedit=
5 > histedit=
6 > EOF
6 > EOF
7
7
8 $ hg init r
8 $ hg init r
9 $ cd r
9 $ cd r
10
10
11 $ for x in a b c d e f ; do
11 $ for x in a b c d e f ; do
12 > echo $x > $x
12 > echo $x > $x
13 > hg add $x
13 > hg add $x
14 > hg ci -m $x
14 > hg ci -m $x
15 > done
15 > done
16
16
17 $ hg book -r 1 will-move-backwards
17 $ hg book -r 1 will-move-backwards
18 $ hg book -r 2 two
18 $ hg book -r 2 two
19 $ hg book -r 2 also-two
19 $ hg book -r 2 also-two
20 $ hg book -r 3 three
20 $ hg book -r 3 three
21 $ hg book -r 4 four
21 $ hg book -r 4 four
22 $ hg book -r tip five
22 $ hg book -r tip five
23 $ hg log --graph
23 $ hg log --graph
24 @ changeset: 5:652413bf663e
24 @ changeset: 5:652413bf663e
25 | bookmark: five
25 | bookmark: five
26 | tag: tip
26 | tag: tip
27 | user: test
27 | user: test
28 | date: Thu Jan 01 00:00:00 1970 +0000
28 | date: Thu Jan 01 00:00:00 1970 +0000
29 | summary: f
29 | summary: f
30 |
30 |
31 o changeset: 4:e860deea161a
31 o changeset: 4:e860deea161a
32 | bookmark: four
32 | bookmark: four
33 | user: test
33 | user: test
34 | date: Thu Jan 01 00:00:00 1970 +0000
34 | date: Thu Jan 01 00:00:00 1970 +0000
35 | summary: e
35 | summary: e
36 |
36 |
37 o changeset: 3:055a42cdd887
37 o changeset: 3:055a42cdd887
38 | bookmark: three
38 | bookmark: three
39 | user: test
39 | user: test
40 | date: Thu Jan 01 00:00:00 1970 +0000
40 | date: Thu Jan 01 00:00:00 1970 +0000
41 | summary: d
41 | summary: d
42 |
42 |
43 o changeset: 2:177f92b77385
43 o changeset: 2:177f92b77385
44 | bookmark: also-two
44 | bookmark: also-two
45 | bookmark: two
45 | bookmark: two
46 | user: test
46 | user: test
47 | date: Thu Jan 01 00:00:00 1970 +0000
47 | date: Thu Jan 01 00:00:00 1970 +0000
48 | summary: c
48 | summary: c
49 |
49 |
50 o changeset: 1:d2ae7f538514
50 o changeset: 1:d2ae7f538514
51 | bookmark: will-move-backwards
51 | bookmark: will-move-backwards
52 | user: test
52 | user: test
53 | date: Thu Jan 01 00:00:00 1970 +0000
53 | date: Thu Jan 01 00:00:00 1970 +0000
54 | summary: b
54 | summary: b
55 |
55 |
56 o changeset: 0:cb9a9f314b8b
56 o changeset: 0:cb9a9f314b8b
57 user: test
57 user: test
58 date: Thu Jan 01 00:00:00 1970 +0000
58 date: Thu Jan 01 00:00:00 1970 +0000
59 summary: a
59 summary: a
60
60
61 $ HGEDITOR=cat hg histedit 1
61 $ HGEDITOR=cat hg histedit 1
62 pick d2ae7f538514 1 b
62 pick d2ae7f538514 1 b
63 pick 177f92b77385 2 c
63 pick 177f92b77385 2 c
64 pick 055a42cdd887 3 d
64 pick 055a42cdd887 3 d
65 pick e860deea161a 4 e
65 pick e860deea161a 4 e
66 pick 652413bf663e 5 f
66 pick 652413bf663e 5 f
67
67
68 # Edit history between d2ae7f538514 and 652413bf663e
68 # Edit history between d2ae7f538514 and 652413bf663e
69 #
69 #
70 # Commits are listed from least to most recent
70 # Commits are listed from least to most recent
71 #
71 #
72 # Commands:
72 # Commands:
73 # p, pick = use commit
73 # p, pick = use commit
74 # e, edit = use commit, but stop for amending
74 # e, edit = use commit, but stop for amending
75 # f, fold = use commit, but combine it with the one above
75 # f, fold = use commit, but combine it with the one above
76 # r, roll = like fold, but discard this commit's description
76 # r, roll = like fold, but discard this commit's description
77 # d, drop = remove commit from history
77 # d, drop = remove commit from history
78 # m, mess = edit commit message without changing commit content
78 # m, mess = edit commit message without changing commit content
79 #
79 #
80 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
81 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
82 > pick 177f92b77385 2 c
82 > pick 177f92b77385 2 c
83 > drop d2ae7f538514 1 b
83 > drop d2ae7f538514 1 b
84 > pick 055a42cdd887 3 d
84 > pick 055a42cdd887 3 d
85 > fold e860deea161a 4 e
85 > fold e860deea161a 4 e
86 > pick 652413bf663e 5 f
86 > pick 652413bf663e 5 f
87 > EOF
87 > EOF
88 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-3c6c5d92-backup.hg (glob)
88 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
89 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
89 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
90 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
90 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
91 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
91 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
92 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
92 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
93 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
93 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
94 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
94 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-48787b8d-backup.hg (glob)
95 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-48787b8d-backup.hg (glob)
95 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-3c6c5d92-backup.hg (glob)
96 $ hg log --graph
96 $ hg log --graph
97 @ changeset: 3:cacdfd884a93
97 @ changeset: 3:cacdfd884a93
98 | bookmark: five
98 | bookmark: five
99 | tag: tip
99 | tag: tip
100 | user: test
100 | user: test
101 | date: Thu Jan 01 00:00:00 1970 +0000
101 | date: Thu Jan 01 00:00:00 1970 +0000
102 | summary: f
102 | summary: f
103 |
103 |
104 o changeset: 2:59d9f330561f
104 o changeset: 2:59d9f330561f
105 | bookmark: four
105 | bookmark: four
106 | bookmark: three
106 | bookmark: three
107 | user: test
107 | user: test
108 | date: Thu Jan 01 00:00:00 1970 +0000
108 | date: Thu Jan 01 00:00:00 1970 +0000
109 | summary: d
109 | summary: d
110 |
110 |
111 o changeset: 1:b346ab9a313d
111 o changeset: 1:b346ab9a313d
112 | bookmark: also-two
112 | bookmark: also-two
113 | bookmark: two
113 | bookmark: two
114 | user: test
114 | user: test
115 | date: Thu Jan 01 00:00:00 1970 +0000
115 | date: Thu Jan 01 00:00:00 1970 +0000
116 | summary: c
116 | summary: c
117 |
117 |
118 o changeset: 0:cb9a9f314b8b
118 o changeset: 0:cb9a9f314b8b
119 bookmark: will-move-backwards
119 bookmark: will-move-backwards
120 user: test
120 user: test
121 date: Thu Jan 01 00:00:00 1970 +0000
121 date: Thu Jan 01 00:00:00 1970 +0000
122 summary: a
122 summary: a
123
123
124 $ HGEDITOR=cat hg histedit 1
124 $ HGEDITOR=cat hg histedit 1
125 pick b346ab9a313d 1 c
125 pick b346ab9a313d 1 c
126 pick 59d9f330561f 2 d
126 pick 59d9f330561f 2 d
127 pick cacdfd884a93 3 f
127 pick cacdfd884a93 3 f
128
128
129 # Edit history between b346ab9a313d and cacdfd884a93
129 # Edit history between b346ab9a313d and cacdfd884a93
130 #
130 #
131 # Commits are listed from least to most recent
131 # Commits are listed from least to most recent
132 #
132 #
133 # Commands:
133 # Commands:
134 # p, pick = use commit
134 # p, pick = use commit
135 # e, edit = use commit, but stop for amending
135 # e, edit = use commit, but stop for amending
136 # f, fold = use commit, but combine it with the one above
136 # f, fold = use commit, but combine it with the one above
137 # r, roll = like fold, but discard this commit's description
137 # r, roll = like fold, but discard this commit's description
138 # d, drop = remove commit from history
138 # d, drop = remove commit from history
139 # m, mess = edit commit message without changing commit content
139 # m, mess = edit commit message without changing commit content
140 #
140 #
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
142 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
143 > pick b346ab9a313d 1 c
143 > pick b346ab9a313d 1 c
144 > pick cacdfd884a93 3 f
144 > pick cacdfd884a93 3 f
145 > pick 59d9f330561f 2 d
145 > pick 59d9f330561f 2 d
146 > EOF
146 > EOF
147 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
147 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
148 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
148 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
149 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
149 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
150 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-073008af-backup.hg (glob)
150 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-073008af-backup.hg (glob)
151
151
152 We expect 'five' to stay at tip, since the tipmost bookmark is most
152 We expect 'five' to stay at tip, since the tipmost bookmark is most
153 likely the useful signal.
153 likely the useful signal.
154
154
155 $ hg log --graph
155 $ hg log --graph
156 @ changeset: 3:c04e50810e4b
156 @ changeset: 3:c04e50810e4b
157 | bookmark: five
157 | bookmark: five
158 | bookmark: four
158 | bookmark: four
159 | bookmark: three
159 | bookmark: three
160 | tag: tip
160 | tag: tip
161 | user: test
161 | user: test
162 | date: Thu Jan 01 00:00:00 1970 +0000
162 | date: Thu Jan 01 00:00:00 1970 +0000
163 | summary: d
163 | summary: d
164 |
164 |
165 o changeset: 2:c13eb81022ca
165 o changeset: 2:c13eb81022ca
166 | user: test
166 | user: test
167 | date: Thu Jan 01 00:00:00 1970 +0000
167 | date: Thu Jan 01 00:00:00 1970 +0000
168 | summary: f
168 | summary: f
169 |
169 |
170 o changeset: 1:b346ab9a313d
170 o changeset: 1:b346ab9a313d
171 | bookmark: also-two
171 | bookmark: also-two
172 | bookmark: two
172 | bookmark: two
173 | user: test
173 | user: test
174 | date: Thu Jan 01 00:00:00 1970 +0000
174 | date: Thu Jan 01 00:00:00 1970 +0000
175 | summary: c
175 | summary: c
176 |
176 |
177 o changeset: 0:cb9a9f314b8b
177 o changeset: 0:cb9a9f314b8b
178 bookmark: will-move-backwards
178 bookmark: will-move-backwards
179 user: test
179 user: test
180 date: Thu Jan 01 00:00:00 1970 +0000
180 date: Thu Jan 01 00:00:00 1970 +0000
181 summary: a
181 summary: a
182
182
@@ -1,459 +1,460 b''
1 $ . "$TESTDIR/histedit-helpers.sh"
1 $ . "$TESTDIR/histedit-helpers.sh"
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > histedit=
5 > histedit=
6 > EOF
6 > EOF
7
7
8 $ initrepo ()
8 $ initrepo ()
9 > {
9 > {
10 > hg init r
10 > hg init r
11 > cd r
11 > cd r
12 > for x in a b c d e f ; do
12 > for x in a b c d e f ; do
13 > echo $x > $x
13 > echo $x > $x
14 > hg add $x
14 > hg add $x
15 > hg ci -m $x
15 > hg ci -m $x
16 > done
16 > done
17 > }
17 > }
18
18
19 $ initrepo
19 $ initrepo
20
20
21 log before edit
21 log before edit
22 $ hg log --graph
22 $ hg log --graph
23 @ changeset: 5:652413bf663e
23 @ changeset: 5:652413bf663e
24 | tag: tip
24 | tag: tip
25 | user: test
25 | user: test
26 | date: Thu Jan 01 00:00:00 1970 +0000
26 | date: Thu Jan 01 00:00:00 1970 +0000
27 | summary: f
27 | summary: f
28 |
28 |
29 o changeset: 4:e860deea161a
29 o changeset: 4:e860deea161a
30 | user: test
30 | user: test
31 | date: Thu Jan 01 00:00:00 1970 +0000
31 | date: Thu Jan 01 00:00:00 1970 +0000
32 | summary: e
32 | summary: e
33 |
33 |
34 o changeset: 3:055a42cdd887
34 o changeset: 3:055a42cdd887
35 | user: test
35 | user: test
36 | date: Thu Jan 01 00:00:00 1970 +0000
36 | date: Thu Jan 01 00:00:00 1970 +0000
37 | summary: d
37 | summary: d
38 |
38 |
39 o changeset: 2:177f92b77385
39 o changeset: 2:177f92b77385
40 | user: test
40 | user: test
41 | date: Thu Jan 01 00:00:00 1970 +0000
41 | date: Thu Jan 01 00:00:00 1970 +0000
42 | summary: c
42 | summary: c
43 |
43 |
44 o changeset: 1:d2ae7f538514
44 o changeset: 1:d2ae7f538514
45 | user: test
45 | user: test
46 | date: Thu Jan 01 00:00:00 1970 +0000
46 | date: Thu Jan 01 00:00:00 1970 +0000
47 | summary: b
47 | summary: b
48 |
48 |
49 o changeset: 0:cb9a9f314b8b
49 o changeset: 0:cb9a9f314b8b
50 user: test
50 user: test
51 date: Thu Jan 01 00:00:00 1970 +0000
51 date: Thu Jan 01 00:00:00 1970 +0000
52 summary: a
52 summary: a
53
53
54
54
55 show the edit commands offered
55 show the edit commands offered
56 $ HGEDITOR=cat hg histedit 177f92b77385
56 $ HGEDITOR=cat hg histedit 177f92b77385
57 pick 177f92b77385 2 c
57 pick 177f92b77385 2 c
58 pick 055a42cdd887 3 d
58 pick 055a42cdd887 3 d
59 pick e860deea161a 4 e
59 pick e860deea161a 4 e
60 pick 652413bf663e 5 f
60 pick 652413bf663e 5 f
61
61
62 # Edit history between 177f92b77385 and 652413bf663e
62 # Edit history between 177f92b77385 and 652413bf663e
63 #
63 #
64 # Commits are listed from least to most recent
64 # Commits are listed from least to most recent
65 #
65 #
66 # Commands:
66 # Commands:
67 # p, pick = use commit
67 # p, pick = use commit
68 # e, edit = use commit, but stop for amending
68 # e, edit = use commit, but stop for amending
69 # f, fold = use commit, but combine it with the one above
69 # f, fold = use commit, but combine it with the one above
70 # r, roll = like fold, but discard this commit's description
70 # r, roll = like fold, but discard this commit's description
71 # d, drop = remove commit from history
71 # d, drop = remove commit from history
72 # m, mess = edit commit message without changing commit content
72 # m, mess = edit commit message without changing commit content
73 #
73 #
74 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
75
75
76 edit the history
76 edit the history
77 (use a hacky editor to check histedit-last-edit.txt backup)
77 (use a hacky editor to check histedit-last-edit.txt backup)
78
78
79 $ EDITED="$TESTTMP/editedhistory"
79 $ EDITED="$TESTTMP/editedhistory"
80 $ cat > $EDITED <<EOF
80 $ cat > $EDITED <<EOF
81 > pick 177f92b77385 c
81 > pick 177f92b77385 c
82 > pick e860deea161a e
82 > pick e860deea161a e
83 > pick 652413bf663e f
83 > pick 652413bf663e f
84 > pick 055a42cdd887 d
84 > pick 055a42cdd887 d
85 > EOF
85 > EOF
86 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
86 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
87 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
87 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
91
91
92 rules should end up in .hg/histedit-last-edit.txt:
92 rules should end up in .hg/histedit-last-edit.txt:
93 $ cat .hg/histedit-last-edit.txt
93 $ cat .hg/histedit-last-edit.txt
94 pick 177f92b77385 c
94 pick 177f92b77385 c
95 pick e860deea161a e
95 pick e860deea161a e
96 pick 652413bf663e f
96 pick 652413bf663e f
97 pick 055a42cdd887 d
97 pick 055a42cdd887 d
98
98
99 log after edit
99 log after edit
100 $ hg log --graph
100 $ hg log --graph
101 @ changeset: 5:07114f51870f
101 @ changeset: 5:07114f51870f
102 | tag: tip
102 | tag: tip
103 | user: test
103 | user: test
104 | date: Thu Jan 01 00:00:00 1970 +0000
104 | date: Thu Jan 01 00:00:00 1970 +0000
105 | summary: d
105 | summary: d
106 |
106 |
107 o changeset: 4:8ade9693061e
107 o changeset: 4:8ade9693061e
108 | user: test
108 | user: test
109 | date: Thu Jan 01 00:00:00 1970 +0000
109 | date: Thu Jan 01 00:00:00 1970 +0000
110 | summary: f
110 | summary: f
111 |
111 |
112 o changeset: 3:d8249471110a
112 o changeset: 3:d8249471110a
113 | user: test
113 | user: test
114 | date: Thu Jan 01 00:00:00 1970 +0000
114 | date: Thu Jan 01 00:00:00 1970 +0000
115 | summary: e
115 | summary: e
116 |
116 |
117 o changeset: 2:177f92b77385
117 o changeset: 2:177f92b77385
118 | user: test
118 | user: test
119 | date: Thu Jan 01 00:00:00 1970 +0000
119 | date: Thu Jan 01 00:00:00 1970 +0000
120 | summary: c
120 | summary: c
121 |
121 |
122 o changeset: 1:d2ae7f538514
122 o changeset: 1:d2ae7f538514
123 | user: test
123 | user: test
124 | date: Thu Jan 01 00:00:00 1970 +0000
124 | date: Thu Jan 01 00:00:00 1970 +0000
125 | summary: b
125 | summary: b
126 |
126 |
127 o changeset: 0:cb9a9f314b8b
127 o changeset: 0:cb9a9f314b8b
128 user: test
128 user: test
129 date: Thu Jan 01 00:00:00 1970 +0000
129 date: Thu Jan 01 00:00:00 1970 +0000
130 summary: a
130 summary: a
131
131
132
132
133 put things back
133 put things back
134
134
135 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF | fixbundle
135 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF | fixbundle
136 > pick 177f92b77385 c
136 > pick 177f92b77385 c
137 > pick 07114f51870f d
137 > pick 07114f51870f d
138 > pick d8249471110a e
138 > pick d8249471110a e
139 > pick 8ade9693061e f
139 > pick 8ade9693061e f
140 > EOF
140 > EOF
141 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
142 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
144 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
144 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
145
145
146 $ hg log --graph
146 $ hg log --graph
147 @ changeset: 5:7eca9b5b1148
147 @ changeset: 5:7eca9b5b1148
148 | tag: tip
148 | tag: tip
149 | user: test
149 | user: test
150 | date: Thu Jan 01 00:00:00 1970 +0000
150 | date: Thu Jan 01 00:00:00 1970 +0000
151 | summary: f
151 | summary: f
152 |
152 |
153 o changeset: 4:915da888f2de
153 o changeset: 4:915da888f2de
154 | user: test
154 | user: test
155 | date: Thu Jan 01 00:00:00 1970 +0000
155 | date: Thu Jan 01 00:00:00 1970 +0000
156 | summary: e
156 | summary: e
157 |
157 |
158 o changeset: 3:10517e47bbbb
158 o changeset: 3:10517e47bbbb
159 | user: test
159 | user: test
160 | date: Thu Jan 01 00:00:00 1970 +0000
160 | date: Thu Jan 01 00:00:00 1970 +0000
161 | summary: d
161 | summary: d
162 |
162 |
163 o changeset: 2:177f92b77385
163 o changeset: 2:177f92b77385
164 | user: test
164 | user: test
165 | date: Thu Jan 01 00:00:00 1970 +0000
165 | date: Thu Jan 01 00:00:00 1970 +0000
166 | summary: c
166 | summary: c
167 |
167 |
168 o changeset: 1:d2ae7f538514
168 o changeset: 1:d2ae7f538514
169 | user: test
169 | user: test
170 | date: Thu Jan 01 00:00:00 1970 +0000
170 | date: Thu Jan 01 00:00:00 1970 +0000
171 | summary: b
171 | summary: b
172 |
172 |
173 o changeset: 0:cb9a9f314b8b
173 o changeset: 0:cb9a9f314b8b
174 user: test
174 user: test
175 date: Thu Jan 01 00:00:00 1970 +0000
175 date: Thu Jan 01 00:00:00 1970 +0000
176 summary: a
176 summary: a
177
177
178
178
179 slightly different this time
179 slightly different this time
180
180
181 $ hg histedit 177f92b77385 --commands - << EOF 2>&1 | fixbundle
181 $ hg histedit 177f92b77385 --commands - << EOF 2>&1 | fixbundle
182 > pick 10517e47bbbb d
182 > pick 10517e47bbbb d
183 > pick 7eca9b5b1148 f
183 > pick 7eca9b5b1148 f
184 > pick 915da888f2de e
184 > pick 915da888f2de e
185 > pick 177f92b77385 c
185 > pick 177f92b77385 c
186 > EOF
186 > EOF
187 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
187 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
188 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
188 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 $ hg log --graph
192 $ hg log --graph
193 @ changeset: 5:38b92f448761
193 @ changeset: 5:38b92f448761
194 | tag: tip
194 | tag: tip
195 | user: test
195 | user: test
196 | date: Thu Jan 01 00:00:00 1970 +0000
196 | date: Thu Jan 01 00:00:00 1970 +0000
197 | summary: c
197 | summary: c
198 |
198 |
199 o changeset: 4:de71b079d9ce
199 o changeset: 4:de71b079d9ce
200 | user: test
200 | user: test
201 | date: Thu Jan 01 00:00:00 1970 +0000
201 | date: Thu Jan 01 00:00:00 1970 +0000
202 | summary: e
202 | summary: e
203 |
203 |
204 o changeset: 3:be9ae3a309c6
204 o changeset: 3:be9ae3a309c6
205 | user: test
205 | user: test
206 | date: Thu Jan 01 00:00:00 1970 +0000
206 | date: Thu Jan 01 00:00:00 1970 +0000
207 | summary: f
207 | summary: f
208 |
208 |
209 o changeset: 2:799205341b6b
209 o changeset: 2:799205341b6b
210 | user: test
210 | user: test
211 | date: Thu Jan 01 00:00:00 1970 +0000
211 | date: Thu Jan 01 00:00:00 1970 +0000
212 | summary: d
212 | summary: d
213 |
213 |
214 o changeset: 1:d2ae7f538514
214 o changeset: 1:d2ae7f538514
215 | user: test
215 | user: test
216 | date: Thu Jan 01 00:00:00 1970 +0000
216 | date: Thu Jan 01 00:00:00 1970 +0000
217 | summary: b
217 | summary: b
218 |
218 |
219 o changeset: 0:cb9a9f314b8b
219 o changeset: 0:cb9a9f314b8b
220 user: test
220 user: test
221 date: Thu Jan 01 00:00:00 1970 +0000
221 date: Thu Jan 01 00:00:00 1970 +0000
222 summary: a
222 summary: a
223
223
224
224
225 keep prevents stripping dead revs
225 keep prevents stripping dead revs
226 $ hg histedit 799205341b6b --keep --commands - 2>&1 << EOF | fixbundle
226 $ hg histedit 799205341b6b --keep --commands - 2>&1 << EOF | fixbundle
227 > pick 799205341b6b d
227 > pick 799205341b6b d
228 > pick be9ae3a309c6 f
228 > pick be9ae3a309c6 f
229 > pick 38b92f448761 c
229 > pick 38b92f448761 c
230 > pick de71b079d9ce e
230 > pick de71b079d9ce e
231 > EOF
231 > EOF
232 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
232 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
233 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
235 $ hg log --graph
235 $ hg log --graph
236 @ changeset: 7:803ef1c6fcfd
236 @ changeset: 7:803ef1c6fcfd
237 | tag: tip
237 | tag: tip
238 | user: test
238 | user: test
239 | date: Thu Jan 01 00:00:00 1970 +0000
239 | date: Thu Jan 01 00:00:00 1970 +0000
240 | summary: e
240 | summary: e
241 |
241 |
242 o changeset: 6:ece0b8d93dda
242 o changeset: 6:ece0b8d93dda
243 | parent: 3:be9ae3a309c6
243 | parent: 3:be9ae3a309c6
244 | user: test
244 | user: test
245 | date: Thu Jan 01 00:00:00 1970 +0000
245 | date: Thu Jan 01 00:00:00 1970 +0000
246 | summary: c
246 | summary: c
247 |
247 |
248 | o changeset: 5:38b92f448761
248 | o changeset: 5:38b92f448761
249 | | user: test
249 | | user: test
250 | | date: Thu Jan 01 00:00:00 1970 +0000
250 | | date: Thu Jan 01 00:00:00 1970 +0000
251 | | summary: c
251 | | summary: c
252 | |
252 | |
253 | o changeset: 4:de71b079d9ce
253 | o changeset: 4:de71b079d9ce
254 |/ user: test
254 |/ user: test
255 | date: Thu Jan 01 00:00:00 1970 +0000
255 | date: Thu Jan 01 00:00:00 1970 +0000
256 | summary: e
256 | summary: e
257 |
257 |
258 o changeset: 3:be9ae3a309c6
258 o changeset: 3:be9ae3a309c6
259 | user: test
259 | user: test
260 | date: Thu Jan 01 00:00:00 1970 +0000
260 | date: Thu Jan 01 00:00:00 1970 +0000
261 | summary: f
261 | summary: f
262 |
262 |
263 o changeset: 2:799205341b6b
263 o changeset: 2:799205341b6b
264 | user: test
264 | user: test
265 | date: Thu Jan 01 00:00:00 1970 +0000
265 | date: Thu Jan 01 00:00:00 1970 +0000
266 | summary: d
266 | summary: d
267 |
267 |
268 o changeset: 1:d2ae7f538514
268 o changeset: 1:d2ae7f538514
269 | user: test
269 | user: test
270 | date: Thu Jan 01 00:00:00 1970 +0000
270 | date: Thu Jan 01 00:00:00 1970 +0000
271 | summary: b
271 | summary: b
272 |
272 |
273 o changeset: 0:cb9a9f314b8b
273 o changeset: 0:cb9a9f314b8b
274 user: test
274 user: test
275 date: Thu Jan 01 00:00:00 1970 +0000
275 date: Thu Jan 01 00:00:00 1970 +0000
276 summary: a
276 summary: a
277
277
278
278
279 try with --rev
279 try with --rev
280 $ hg histedit --commands - --rev -2 2>&1 <<EOF | fixbundle
280 $ hg histedit --commands - --rev -2 2>&1 <<EOF | fixbundle
281 > pick de71b079d9ce e
281 > pick de71b079d9ce e
282 > pick 38b92f448761 c
282 > pick 38b92f448761 c
283 > EOF
283 > EOF
284 abort: may not use changesets other than the ones listed
284 abort: may not use changesets other than the ones listed
285 $ hg log --graph
285 $ hg log --graph
286 @ changeset: 7:803ef1c6fcfd
286 @ changeset: 7:803ef1c6fcfd
287 | tag: tip
287 | tag: tip
288 | user: test
288 | user: test
289 | date: Thu Jan 01 00:00:00 1970 +0000
289 | date: Thu Jan 01 00:00:00 1970 +0000
290 | summary: e
290 | summary: e
291 |
291 |
292 o changeset: 6:ece0b8d93dda
292 o changeset: 6:ece0b8d93dda
293 | parent: 3:be9ae3a309c6
293 | parent: 3:be9ae3a309c6
294 | user: test
294 | user: test
295 | date: Thu Jan 01 00:00:00 1970 +0000
295 | date: Thu Jan 01 00:00:00 1970 +0000
296 | summary: c
296 | summary: c
297 |
297 |
298 | o changeset: 5:38b92f448761
298 | o changeset: 5:38b92f448761
299 | | user: test
299 | | user: test
300 | | date: Thu Jan 01 00:00:00 1970 +0000
300 | | date: Thu Jan 01 00:00:00 1970 +0000
301 | | summary: c
301 | | summary: c
302 | |
302 | |
303 | o changeset: 4:de71b079d9ce
303 | o changeset: 4:de71b079d9ce
304 |/ user: test
304 |/ user: test
305 | date: Thu Jan 01 00:00:00 1970 +0000
305 | date: Thu Jan 01 00:00:00 1970 +0000
306 | summary: e
306 | summary: e
307 |
307 |
308 o changeset: 3:be9ae3a309c6
308 o changeset: 3:be9ae3a309c6
309 | user: test
309 | user: test
310 | date: Thu Jan 01 00:00:00 1970 +0000
310 | date: Thu Jan 01 00:00:00 1970 +0000
311 | summary: f
311 | summary: f
312 |
312 |
313 o changeset: 2:799205341b6b
313 o changeset: 2:799205341b6b
314 | user: test
314 | user: test
315 | date: Thu Jan 01 00:00:00 1970 +0000
315 | date: Thu Jan 01 00:00:00 1970 +0000
316 | summary: d
316 | summary: d
317 |
317 |
318 o changeset: 1:d2ae7f538514
318 o changeset: 1:d2ae7f538514
319 | user: test
319 | user: test
320 | date: Thu Jan 01 00:00:00 1970 +0000
320 | date: Thu Jan 01 00:00:00 1970 +0000
321 | summary: b
321 | summary: b
322 |
322 |
323 o changeset: 0:cb9a9f314b8b
323 o changeset: 0:cb9a9f314b8b
324 user: test
324 user: test
325 date: Thu Jan 01 00:00:00 1970 +0000
325 date: Thu Jan 01 00:00:00 1970 +0000
326 summary: a
326 summary: a
327
327
328 Verify that revsetalias entries work with histedit:
328 Verify that revsetalias entries work with histedit:
329 $ cat >> $HGRCPATH <<EOF
329 $ cat >> $HGRCPATH <<EOF
330 > [revsetalias]
330 > [revsetalias]
331 > grandparent(ARG) = p1(p1(ARG))
331 > grandparent(ARG) = p1(p1(ARG))
332 > EOF
332 > EOF
333 $ echo extra commit >> c
333 $ echo extra commit >> c
334 $ hg ci -m 'extra commit to c'
334 $ hg ci -m 'extra commit to c'
335 $ HGEDITOR=cat hg histedit 'grandparent(.)'
335 $ HGEDITOR=cat hg histedit 'grandparent(.)'
336 pick ece0b8d93dda 6 c
336 pick ece0b8d93dda 6 c
337 pick 803ef1c6fcfd 7 e
337 pick 803ef1c6fcfd 7 e
338 pick 9c863c565126 8 extra commit to c
338 pick 9c863c565126 8 extra commit to c
339
339
340 # Edit history between ece0b8d93dda and 9c863c565126
340 # Edit history between ece0b8d93dda and 9c863c565126
341 #
341 #
342 # Commits are listed from least to most recent
342 # Commits are listed from least to most recent
343 #
343 #
344 # Commands:
344 # Commands:
345 # p, pick = use commit
345 # p, pick = use commit
346 # e, edit = use commit, but stop for amending
346 # e, edit = use commit, but stop for amending
347 # f, fold = use commit, but combine it with the one above
347 # f, fold = use commit, but combine it with the one above
348 # r, roll = like fold, but discard this commit's description
348 # r, roll = like fold, but discard this commit's description
349 # d, drop = remove commit from history
349 # d, drop = remove commit from history
350 # m, mess = edit commit message without changing commit content
350 # m, mess = edit commit message without changing commit content
351 #
351 #
352 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
352 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
353
353
354 should also work if a commit message is missing
354 should also work if a commit message is missing
355 $ BUNDLE="$TESTDIR/missing-comment.hg"
355 $ BUNDLE="$TESTDIR/missing-comment.hg"
356 $ hg init missing
356 $ hg init missing
357 $ cd missing
357 $ cd missing
358 $ hg unbundle $BUNDLE
358 $ hg unbundle $BUNDLE
359 adding changesets
359 adding changesets
360 adding manifests
360 adding manifests
361 adding file changes
361 adding file changes
362 added 3 changesets with 3 changes to 1 files
362 added 3 changesets with 3 changes to 1 files
363 (run 'hg update' to get a working copy)
363 (run 'hg update' to get a working copy)
364 $ hg co tip
364 $ hg co tip
365 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
365 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
366 $ hg log --graph
366 $ hg log --graph
367 @ changeset: 2:bd22688093b3
367 @ changeset: 2:bd22688093b3
368 | tag: tip
368 | tag: tip
369 | user: Robert Altman <robert.altman@telventDTN.com>
369 | user: Robert Altman <robert.altman@telventDTN.com>
370 | date: Mon Nov 28 16:40:04 2011 +0000
370 | date: Mon Nov 28 16:40:04 2011 +0000
371 | summary: Update file.
371 | summary: Update file.
372 |
372 |
373 o changeset: 1:3b3e956f9171
373 o changeset: 1:3b3e956f9171
374 | user: Robert Altman <robert.altman@telventDTN.com>
374 | user: Robert Altman <robert.altman@telventDTN.com>
375 | date: Mon Nov 28 16:37:57 2011 +0000
375 | date: Mon Nov 28 16:37:57 2011 +0000
376 |
376 |
377 o changeset: 0:141947992243
377 o changeset: 0:141947992243
378 user: Robert Altman <robert.altman@telventDTN.com>
378 user: Robert Altman <robert.altman@telventDTN.com>
379 date: Mon Nov 28 16:35:28 2011 +0000
379 date: Mon Nov 28 16:35:28 2011 +0000
380 summary: Checked in text file
380 summary: Checked in text file
381
381
382 $ hg histedit 0
382 $ hg histedit 0
383 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
383 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
384 $ cd ..
384 $ cd ..
385
385
386 $ cd ..
386 $ cd ..
387
387
388
388
389 Test to make sure folding renames doesn't cause bogus conflicts (issue4251):
389 Test to make sure folding renames doesn't cause bogus conflicts (issue4251):
390 $ hg init issue4251
390 $ hg init issue4251
391 $ cd issue4251
391 $ cd issue4251
392
392
393 $ mkdir initial-dir
393 $ mkdir initial-dir
394 $ echo foo > initial-dir/initial-file
394 $ echo foo > initial-dir/initial-file
395 $ hg add initial-dir/initial-file
395 $ hg add initial-dir/initial-file
396 $ hg commit -m "initial commit"
396 $ hg commit -m "initial commit"
397
397
398 Move the file to a new directory, and in the same commit, change its content:
398 Move the file to a new directory, and in the same commit, change its content:
399 $ mkdir another-dir
399 $ mkdir another-dir
400 $ hg mv initial-dir/initial-file another-dir/
400 $ hg mv initial-dir/initial-file another-dir/
401 $ echo changed > another-dir/initial-file
401 $ echo changed > another-dir/initial-file
402 $ hg commit -m "moved and changed"
402 $ hg commit -m "moved and changed"
403
403
404 Rename the file:
404 Rename the file:
405 $ hg mv another-dir/initial-file another-dir/renamed-file
405 $ hg mv another-dir/initial-file another-dir/renamed-file
406 $ hg commit -m "renamed"
406 $ hg commit -m "renamed"
407
407
408 Now, let's try to fold the second commit into the first:
408 Now, let's try to fold the second commit into the first:
409 $ cat > editor.sh <<EOF
409 $ cat > editor.sh <<EOF
410 > #!/bin/sh
410 > #!/bin/sh
411 > cat > \$1 <<ENDOF
411 > cat > \$1 <<ENDOF
412 > pick b0f4233702ca 0 initial commit
412 > pick b0f4233702ca 0 initial commit
413 > fold 5e8704a8f2d2 1 moved and changed
413 > fold 5e8704a8f2d2 1 moved and changed
414 > pick 40e7299e8fa7 2 renamed
414 > pick 40e7299e8fa7 2 renamed
415 > ENDOF
415 > ENDOF
416 > EOF
416 > EOF
417
417
418 $ HGEDITOR="sh ./editor.sh" hg histedit 0
418 $ HGEDITOR="sh ./editor.sh" hg histedit 0
419 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
419 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
420 adding another-dir/initial-file (glob)
420 adding another-dir/initial-file (glob)
421 removing initial-dir/initial-file (glob)
421 removing initial-dir/initial-file (glob)
422 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
422 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
423 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
423 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
424 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
424 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 saved backup bundle to $TESTTMP/issue4251/.hg/strip-backup/*-backup.hg (glob)
426 saved backup bundle to $TESTTMP/issue4251/.hg/strip-backup/*-backup.hg (glob)
427 saved backup bundle to $TESTTMP/issue4251/.hg/strip-backup/b0f4233702ca-d99e7186-backup.hg (glob)
427
428
428 $ hg --config diff.git=yes export 0
429 $ hg --config diff.git=yes export 0
429 # HG changeset patch
430 # HG changeset patch
430 # User test
431 # User test
431 # Date 0 0
432 # Date 0 0
432 # Thu Jan 01 00:00:00 1970 +0000
433 # Thu Jan 01 00:00:00 1970 +0000
433 # Node ID fffadc26f8f85623ce60b028a3f1ccc3730f8530
434 # Node ID fffadc26f8f85623ce60b028a3f1ccc3730f8530
434 # Parent 0000000000000000000000000000000000000000
435 # Parent 0000000000000000000000000000000000000000
435 pick b0f4233702ca 0 initial commit
436 pick b0f4233702ca 0 initial commit
436 fold 5e8704a8f2d2 1 moved and changed
437 fold 5e8704a8f2d2 1 moved and changed
437 pick 40e7299e8fa7 2 renamed
438 pick 40e7299e8fa7 2 renamed
438
439
439 diff --git a/another-dir/initial-file b/another-dir/initial-file
440 diff --git a/another-dir/initial-file b/another-dir/initial-file
440 new file mode 100644
441 new file mode 100644
441 --- /dev/null
442 --- /dev/null
442 +++ b/another-dir/initial-file
443 +++ b/another-dir/initial-file
443 @@ -0,0 +1,1 @@
444 @@ -0,0 +1,1 @@
444 +changed
445 +changed
445
446
446 $ hg --config diff.git=yes export 1
447 $ hg --config diff.git=yes export 1
447 # HG changeset patch
448 # HG changeset patch
448 # User test
449 # User test
449 # Date 0 0
450 # Date 0 0
450 # Thu Jan 01 00:00:00 1970 +0000
451 # Thu Jan 01 00:00:00 1970 +0000
451 # Node ID 9b730d82b00af8a2766facebfa47cc124405a118
452 # Node ID 9b730d82b00af8a2766facebfa47cc124405a118
452 # Parent fffadc26f8f85623ce60b028a3f1ccc3730f8530
453 # Parent fffadc26f8f85623ce60b028a3f1ccc3730f8530
453 renamed
454 renamed
454
455
455 diff --git a/another-dir/initial-file b/another-dir/renamed-file
456 diff --git a/another-dir/initial-file b/another-dir/renamed-file
456 rename from another-dir/initial-file
457 rename from another-dir/initial-file
457 rename to another-dir/renamed-file
458 rename to another-dir/renamed-file
458
459
459 $ cd ..
460 $ cd ..
@@ -1,570 +1,571 b''
1 Test histedit extension: Fold commands
1 Test histedit extension: Fold commands
2 ======================================
2 ======================================
3
3
4 This test file is dedicated to testing the fold command in non conflicting
4 This test file is dedicated to testing the fold command in non conflicting
5 case.
5 case.
6
6
7 Initialization
7 Initialization
8 ---------------
8 ---------------
9
9
10
10
11 $ . "$TESTDIR/histedit-helpers.sh"
11 $ . "$TESTDIR/histedit-helpers.sh"
12
12
13 $ cat >> $HGRCPATH <<EOF
13 $ cat >> $HGRCPATH <<EOF
14 > [alias]
14 > [alias]
15 > logt = log --template '{rev}:{node|short} {desc|firstline}\n'
15 > logt = log --template '{rev}:{node|short} {desc|firstline}\n'
16 > [extensions]
16 > [extensions]
17 > histedit=
17 > histedit=
18 > EOF
18 > EOF
19
19
20
20
21 Simple folding
21 Simple folding
22 --------------------
22 --------------------
23 $ initrepo ()
23 $ initrepo ()
24 > {
24 > {
25 > hg init r
25 > hg init r
26 > cd r
26 > cd r
27 > for x in a b c d e f ; do
27 > for x in a b c d e f ; do
28 > echo $x > $x
28 > echo $x > $x
29 > hg add $x
29 > hg add $x
30 > hg ci -m $x
30 > hg ci -m $x
31 > done
31 > done
32 > }
32 > }
33
33
34 $ initrepo
34 $ initrepo
35
35
36 log before edit
36 log before edit
37 $ hg logt --graph
37 $ hg logt --graph
38 @ 5:652413bf663e f
38 @ 5:652413bf663e f
39 |
39 |
40 o 4:e860deea161a e
40 o 4:e860deea161a e
41 |
41 |
42 o 3:055a42cdd887 d
42 o 3:055a42cdd887 d
43 |
43 |
44 o 2:177f92b77385 c
44 o 2:177f92b77385 c
45 |
45 |
46 o 1:d2ae7f538514 b
46 o 1:d2ae7f538514 b
47 |
47 |
48 o 0:cb9a9f314b8b a
48 o 0:cb9a9f314b8b a
49
49
50
50
51 $ hg histedit 177f92b77385 --commands - 2>&1 <<EOF | fixbundle
51 $ hg histedit 177f92b77385 --commands - 2>&1 <<EOF | fixbundle
52 > pick e860deea161a e
52 > pick e860deea161a e
53 > pick 652413bf663e f
53 > pick 652413bf663e f
54 > fold 177f92b77385 c
54 > fold 177f92b77385 c
55 > pick 055a42cdd887 d
55 > pick 055a42cdd887 d
56 > EOF
56 > EOF
57 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
57 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
58 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
60 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
61 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
64
64
65 log after edit
65 log after edit
66 $ hg logt --graph
66 $ hg logt --graph
67 @ 4:9c277da72c9b d
67 @ 4:9c277da72c9b d
68 |
68 |
69 o 3:6de59d13424a f
69 o 3:6de59d13424a f
70 |
70 |
71 o 2:ee283cb5f2d5 e
71 o 2:ee283cb5f2d5 e
72 |
72 |
73 o 1:d2ae7f538514 b
73 o 1:d2ae7f538514 b
74 |
74 |
75 o 0:cb9a9f314b8b a
75 o 0:cb9a9f314b8b a
76
76
77
77
78 post-fold manifest
78 post-fold manifest
79 $ hg manifest
79 $ hg manifest
80 a
80 a
81 b
81 b
82 c
82 c
83 d
83 d
84 e
84 e
85 f
85 f
86
86
87
87
88 check histedit_source
88 check histedit_source
89
89
90 $ hg log --debug --rev 3
90 $ hg log --debug --rev 3
91 changeset: 3:6de59d13424a8a13acd3e975514aed29dd0d9b2d
91 changeset: 3:6de59d13424a8a13acd3e975514aed29dd0d9b2d
92 phase: draft
92 phase: draft
93 parent: 2:ee283cb5f2d5955443f23a27b697a04339e9a39a
93 parent: 2:ee283cb5f2d5955443f23a27b697a04339e9a39a
94 parent: -1:0000000000000000000000000000000000000000
94 parent: -1:0000000000000000000000000000000000000000
95 manifest: 3:81eede616954057198ead0b2c73b41d1f392829a
95 manifest: 3:81eede616954057198ead0b2c73b41d1f392829a
96 user: test
96 user: test
97 date: Thu Jan 01 00:00:00 1970 +0000
97 date: Thu Jan 01 00:00:00 1970 +0000
98 files+: c f
98 files+: c f
99 extra: branch=default
99 extra: branch=default
100 extra: histedit_source=a4f7421b80f79fcc59fff01bcbf4a53d127dd6d3,177f92b773850b59254aa5e923436f921b55483b
100 extra: histedit_source=a4f7421b80f79fcc59fff01bcbf4a53d127dd6d3,177f92b773850b59254aa5e923436f921b55483b
101 description:
101 description:
102 f
102 f
103 ***
103 ***
104 c
104 c
105
105
106
106
107
107
108 rollup will fold without preserving the folded commit's message
108 rollup will fold without preserving the folded commit's message
109
109
110 $ OLDHGEDITOR=$HGEDITOR
110 $ OLDHGEDITOR=$HGEDITOR
111 $ HGEDITOR=false
111 $ HGEDITOR=false
112 $ hg histedit d2ae7f538514 --commands - 2>&1 <<EOF | fixbundle
112 $ hg histedit d2ae7f538514 --commands - 2>&1 <<EOF | fixbundle
113 > pick d2ae7f538514 b
113 > pick d2ae7f538514 b
114 > roll ee283cb5f2d5 e
114 > roll ee283cb5f2d5 e
115 > pick 6de59d13424a f
115 > pick 6de59d13424a f
116 > pick 9c277da72c9b d
116 > pick 9c277da72c9b d
117 > EOF
117 > EOF
118 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
118 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
119 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
119 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
120 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
124
124
125 $ HGEDITOR=$OLDHGEDITOR
125 $ HGEDITOR=$OLDHGEDITOR
126
126
127 log after edit
127 log after edit
128 $ hg logt --graph
128 $ hg logt --graph
129 @ 3:c4a9eb7989fc d
129 @ 3:c4a9eb7989fc d
130 |
130 |
131 o 2:8e03a72b6f83 f
131 o 2:8e03a72b6f83 f
132 |
132 |
133 o 1:391ee782c689 b
133 o 1:391ee782c689 b
134 |
134 |
135 o 0:cb9a9f314b8b a
135 o 0:cb9a9f314b8b a
136
136
137
137
138 description is taken from rollup target commit
138 description is taken from rollup target commit
139
139
140 $ hg log --debug --rev 1
140 $ hg log --debug --rev 1
141 changeset: 1:391ee782c68930be438ccf4c6a403daedbfbffa5
141 changeset: 1:391ee782c68930be438ccf4c6a403daedbfbffa5
142 phase: draft
142 phase: draft
143 parent: 0:cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
143 parent: 0:cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
144 parent: -1:0000000000000000000000000000000000000000
144 parent: -1:0000000000000000000000000000000000000000
145 manifest: 1:b5e112a3a8354e269b1524729f0918662d847c38
145 manifest: 1:b5e112a3a8354e269b1524729f0918662d847c38
146 user: test
146 user: test
147 date: Thu Jan 01 00:00:00 1970 +0000
147 date: Thu Jan 01 00:00:00 1970 +0000
148 files+: b e
148 files+: b e
149 extra: branch=default
149 extra: branch=default
150 extra: histedit_source=d2ae7f538514cd87c17547b0de4cea71fe1af9fb,ee283cb5f2d5955443f23a27b697a04339e9a39a
150 extra: histedit_source=d2ae7f538514cd87c17547b0de4cea71fe1af9fb,ee283cb5f2d5955443f23a27b697a04339e9a39a
151 description:
151 description:
152 b
152 b
153
153
154
154
155
155
156 check saving last-message.txt
156 check saving last-message.txt
157
157
158 $ cat > $TESTTMP/abortfolding.py <<EOF
158 $ cat > $TESTTMP/abortfolding.py <<EOF
159 > from mercurial import util
159 > from mercurial import util
160 > def abortfolding(ui, repo, hooktype, **kwargs):
160 > def abortfolding(ui, repo, hooktype, **kwargs):
161 > ctx = repo[kwargs.get('node')]
161 > ctx = repo[kwargs.get('node')]
162 > if set(ctx.files()) == set(['c', 'd', 'f']):
162 > if set(ctx.files()) == set(['c', 'd', 'f']):
163 > return True # abort folding commit only
163 > return True # abort folding commit only
164 > ui.warn('allow non-folding commit\\n')
164 > ui.warn('allow non-folding commit\\n')
165 > EOF
165 > EOF
166 $ cat > .hg/hgrc <<EOF
166 $ cat > .hg/hgrc <<EOF
167 > [hooks]
167 > [hooks]
168 > pretxncommit.abortfolding = python:$TESTTMP/abortfolding.py:abortfolding
168 > pretxncommit.abortfolding = python:$TESTTMP/abortfolding.py:abortfolding
169 > EOF
169 > EOF
170
170
171 $ cat > $TESTTMP/editor.sh << EOF
171 $ cat > $TESTTMP/editor.sh << EOF
172 > echo "==== before editing"
172 > echo "==== before editing"
173 > cat \$1
173 > cat \$1
174 > echo "===="
174 > echo "===="
175 > echo "check saving last-message.txt" >> \$1
175 > echo "check saving last-message.txt" >> \$1
176 > EOF
176 > EOF
177
177
178 $ rm -f .hg/last-message.txt
178 $ rm -f .hg/last-message.txt
179 $ hg status --rev '8e03a72b6f83^1::c4a9eb7989fc'
179 $ hg status --rev '8e03a72b6f83^1::c4a9eb7989fc'
180 A c
180 A c
181 A d
181 A d
182 A f
182 A f
183 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 8e03a72b6f83 --commands - 2>&1 <<EOF
183 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 8e03a72b6f83 --commands - 2>&1 <<EOF
184 > pick 8e03a72b6f83 f
184 > pick 8e03a72b6f83 f
185 > fold c4a9eb7989fc d
185 > fold c4a9eb7989fc d
186 > EOF
186 > EOF
187 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
187 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
188 adding d
188 adding d
189 allow non-folding commit
189 allow non-folding commit
190 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
190 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
191 ==== before editing
191 ==== before editing
192 f
192 f
193 ***
193 ***
194 c
194 c
195 ***
195 ***
196 d
196 d
197
197
198
198
199
199
200 HG: Enter commit message. Lines beginning with 'HG:' are removed.
200 HG: Enter commit message. Lines beginning with 'HG:' are removed.
201 HG: Leave message empty to abort commit.
201 HG: Leave message empty to abort commit.
202 HG: --
202 HG: --
203 HG: user: test
203 HG: user: test
204 HG: branch 'default'
204 HG: branch 'default'
205 HG: added c
205 HG: added c
206 HG: added d
206 HG: added d
207 HG: added f
207 HG: added f
208 ====
208 ====
209 transaction abort!
209 transaction abort!
210 rollback completed
210 rollback completed
211 abort: pretxncommit.abortfolding hook failed
211 abort: pretxncommit.abortfolding hook failed
212 [255]
212 [255]
213
213
214 $ cat .hg/last-message.txt
214 $ cat .hg/last-message.txt
215 f
215 f
216 ***
216 ***
217 c
217 c
218 ***
218 ***
219 d
219 d
220
220
221
221
222
222
223 check saving last-message.txt
223 check saving last-message.txt
224
224
225 $ cd ..
225 $ cd ..
226 $ rm -r r
226 $ rm -r r
227
227
228 folding preserves initial author
228 folding preserves initial author
229 --------------------------------
229 --------------------------------
230
230
231 $ initrepo
231 $ initrepo
232
232
233 $ hg ci --user "someone else" --amend --quiet
233 $ hg ci --user "someone else" --amend --quiet
234
234
235 tip before edit
235 tip before edit
236 $ hg log --rev .
236 $ hg log --rev .
237 changeset: 5:a00ad806cb55
237 changeset: 5:a00ad806cb55
238 tag: tip
238 tag: tip
239 user: someone else
239 user: someone else
240 date: Thu Jan 01 00:00:00 1970 +0000
240 date: Thu Jan 01 00:00:00 1970 +0000
241 summary: f
241 summary: f
242
242
243
243
244 $ hg histedit e860deea161a --commands - 2>&1 <<EOF | fixbundle
244 $ hg histedit e860deea161a --commands - 2>&1 <<EOF | fixbundle
245 > pick e860deea161a e
245 > pick e860deea161a e
246 > fold a00ad806cb55 f
246 > fold a00ad806cb55 f
247 > EOF
247 > EOF
248 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
248 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
249 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
249 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
250 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
250 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
251 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
251 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
252
252
253 tip after edit
253 tip after edit
254 $ hg log --rev .
254 $ hg log --rev .
255 changeset: 4:698d4e8040a1
255 changeset: 4:698d4e8040a1
256 tag: tip
256 tag: tip
257 user: test
257 user: test
258 date: Thu Jan 01 00:00:00 1970 +0000
258 date: Thu Jan 01 00:00:00 1970 +0000
259 summary: e
259 summary: e
260
260
261
261
262 $ cd ..
262 $ cd ..
263 $ rm -r r
263 $ rm -r r
264
264
265 folding and creating no new change doesn't break:
265 folding and creating no new change doesn't break:
266 -------------------------------------------------
266 -------------------------------------------------
267
267
268 folded content is dropped during a merge. The folded commit should properly disappear.
268 folded content is dropped during a merge. The folded commit should properly disappear.
269
269
270 $ mkdir fold-to-empty-test
270 $ mkdir fold-to-empty-test
271 $ cd fold-to-empty-test
271 $ cd fold-to-empty-test
272 $ hg init
272 $ hg init
273 $ printf "1\n2\n3\n" > file
273 $ printf "1\n2\n3\n" > file
274 $ hg add file
274 $ hg add file
275 $ hg commit -m '1+2+3'
275 $ hg commit -m '1+2+3'
276 $ echo 4 >> file
276 $ echo 4 >> file
277 $ hg commit -m '+4'
277 $ hg commit -m '+4'
278 $ echo 5 >> file
278 $ echo 5 >> file
279 $ hg commit -m '+5'
279 $ hg commit -m '+5'
280 $ echo 6 >> file
280 $ echo 6 >> file
281 $ hg commit -m '+6'
281 $ hg commit -m '+6'
282 $ hg logt --graph
282 $ hg logt --graph
283 @ 3:251d831eeec5 +6
283 @ 3:251d831eeec5 +6
284 |
284 |
285 o 2:888f9082bf99 +5
285 o 2:888f9082bf99 +5
286 |
286 |
287 o 1:617f94f13c0f +4
287 o 1:617f94f13c0f +4
288 |
288 |
289 o 0:0189ba417d34 1+2+3
289 o 0:0189ba417d34 1+2+3
290
290
291
291
292 $ hg histedit 1 --commands - << EOF
292 $ hg histedit 1 --commands - << EOF
293 > pick 617f94f13c0f 1 +4
293 > pick 617f94f13c0f 1 +4
294 > drop 888f9082bf99 2 +5
294 > drop 888f9082bf99 2 +5
295 > fold 251d831eeec5 3 +6
295 > fold 251d831eeec5 3 +6
296 > EOF
296 > EOF
297 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
297 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
298 merging file
298 merging file
299 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
299 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
300 Fix up the change and run hg histedit --continue
300 Fix up the change and run hg histedit --continue
301 [1]
301 [1]
302 There were conflicts, we keep P1 content. This
302 There were conflicts, we keep P1 content. This
303 should effectively drop the changes from +6.
303 should effectively drop the changes from +6.
304 $ hg status
304 $ hg status
305 M file
305 M file
306 ? file.orig
306 ? file.orig
307 $ hg resolve -l
307 $ hg resolve -l
308 U file
308 U file
309 $ hg revert -r 'p1()' file
309 $ hg revert -r 'p1()' file
310 $ hg resolve --mark file
310 $ hg resolve --mark file
311 (no more unresolved files)
311 (no more unresolved files)
312 $ hg histedit --continue
312 $ hg histedit --continue
313 251d831eeec5: empty changeset
313 251d831eeec5: empty changeset
314 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
315 saved backup bundle to $TESTTMP/*-backup.hg (glob)
315 saved backup bundle to $TESTTMP/*-backup.hg (glob)
316 $ hg logt --graph
316 $ hg logt --graph
317 @ 1:617f94f13c0f +4
317 @ 1:617f94f13c0f +4
318 |
318 |
319 o 0:0189ba417d34 1+2+3
319 o 0:0189ba417d34 1+2+3
320
320
321
321
322 $ cd ..
322 $ cd ..
323
323
324
324
325 Test fold through dropped
325 Test fold through dropped
326 -------------------------
326 -------------------------
327
327
328
328
329 Test corner case where folded revision is separated from its parent by a
329 Test corner case where folded revision is separated from its parent by a
330 dropped revision.
330 dropped revision.
331
331
332
332
333 $ hg init fold-with-dropped
333 $ hg init fold-with-dropped
334 $ cd fold-with-dropped
334 $ cd fold-with-dropped
335 $ printf "1\n2\n3\n" > file
335 $ printf "1\n2\n3\n" > file
336 $ hg commit -Am '1+2+3'
336 $ hg commit -Am '1+2+3'
337 adding file
337 adding file
338 $ echo 4 >> file
338 $ echo 4 >> file
339 $ hg commit -m '+4'
339 $ hg commit -m '+4'
340 $ echo 5 >> file
340 $ echo 5 >> file
341 $ hg commit -m '+5'
341 $ hg commit -m '+5'
342 $ echo 6 >> file
342 $ echo 6 >> file
343 $ hg commit -m '+6'
343 $ hg commit -m '+6'
344 $ hg logt -G
344 $ hg logt -G
345 @ 3:251d831eeec5 +6
345 @ 3:251d831eeec5 +6
346 |
346 |
347 o 2:888f9082bf99 +5
347 o 2:888f9082bf99 +5
348 |
348 |
349 o 1:617f94f13c0f +4
349 o 1:617f94f13c0f +4
350 |
350 |
351 o 0:0189ba417d34 1+2+3
351 o 0:0189ba417d34 1+2+3
352
352
353 $ hg histedit 1 --commands - << EOF
353 $ hg histedit 1 --commands - << EOF
354 > pick 617f94f13c0f 1 +4
354 > pick 617f94f13c0f 1 +4
355 > drop 888f9082bf99 2 +5
355 > drop 888f9082bf99 2 +5
356 > fold 251d831eeec5 3 +6
356 > fold 251d831eeec5 3 +6
357 > EOF
357 > EOF
358 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 merging file
359 merging file
360 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
360 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
361 Fix up the change and run hg histedit --continue
361 Fix up the change and run hg histedit --continue
362 [1]
362 [1]
363 $ cat > file << EOF
363 $ cat > file << EOF
364 > 1
364 > 1
365 > 2
365 > 2
366 > 3
366 > 3
367 > 4
367 > 4
368 > 5
368 > 5
369 > EOF
369 > EOF
370 $ hg resolve --mark file
370 $ hg resolve --mark file
371 (no more unresolved files)
371 (no more unresolved files)
372 $ hg commit -m '+5.2'
372 $ hg commit -m '+5.2'
373 created new head
373 created new head
374 $ echo 6 >> file
374 $ echo 6 >> file
375 $ HGEDITOR=cat hg histedit --continue
375 $ HGEDITOR=cat hg histedit --continue
376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 +4
377 +4
378 ***
378 ***
379 +5.2
379 +5.2
380 ***
380 ***
381 +6
381 +6
382
382
383
383
384
384
385 HG: Enter commit message. Lines beginning with 'HG:' are removed.
385 HG: Enter commit message. Lines beginning with 'HG:' are removed.
386 HG: Leave message empty to abort commit.
386 HG: Leave message empty to abort commit.
387 HG: --
387 HG: --
388 HG: user: test
388 HG: user: test
389 HG: branch 'default'
389 HG: branch 'default'
390 HG: changed file
390 HG: changed file
391 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
391 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
392 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
393 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-3d69522c-backup.hg (glob)
393 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/55c8d8dc79ce-4066cd98-backup.hg (glob)
394 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-a35700fc-backup.hg (glob)
394 $ hg logt -G
395 $ hg logt -G
395 @ 1:10c647b2cdd5 +4
396 @ 1:10c647b2cdd5 +4
396 |
397 |
397 o 0:0189ba417d34 1+2+3
398 o 0:0189ba417d34 1+2+3
398
399
399 $ hg export tip
400 $ hg export tip
400 # HG changeset patch
401 # HG changeset patch
401 # User test
402 # User test
402 # Date 0 0
403 # Date 0 0
403 # Thu Jan 01 00:00:00 1970 +0000
404 # Thu Jan 01 00:00:00 1970 +0000
404 # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
405 # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
405 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
406 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
406 +4
407 +4
407 ***
408 ***
408 +5.2
409 +5.2
409 ***
410 ***
410 +6
411 +6
411
412
412 diff -r 0189ba417d34 -r 10c647b2cdd5 file
413 diff -r 0189ba417d34 -r 10c647b2cdd5 file
413 --- a/file Thu Jan 01 00:00:00 1970 +0000
414 --- a/file Thu Jan 01 00:00:00 1970 +0000
414 +++ b/file Thu Jan 01 00:00:00 1970 +0000
415 +++ b/file Thu Jan 01 00:00:00 1970 +0000
415 @@ -1,3 +1,6 @@
416 @@ -1,3 +1,6 @@
416 1
417 1
417 2
418 2
418 3
419 3
419 +4
420 +4
420 +5
421 +5
421 +6
422 +6
422 $ cd ..
423 $ cd ..
423
424
424
425
425 Folding with initial rename (issue3729)
426 Folding with initial rename (issue3729)
426 ---------------------------------------
427 ---------------------------------------
427
428
428 $ hg init fold-rename
429 $ hg init fold-rename
429 $ cd fold-rename
430 $ cd fold-rename
430 $ echo a > a.txt
431 $ echo a > a.txt
431 $ hg add a.txt
432 $ hg add a.txt
432 $ hg commit -m a
433 $ hg commit -m a
433 $ hg rename a.txt b.txt
434 $ hg rename a.txt b.txt
434 $ hg commit -m rename
435 $ hg commit -m rename
435 $ echo b >> b.txt
436 $ echo b >> b.txt
436 $ hg commit -m b
437 $ hg commit -m b
437
438
438 $ hg logt --follow b.txt
439 $ hg logt --follow b.txt
439 2:e0371e0426bc b
440 2:e0371e0426bc b
440 1:1c4f440a8085 rename
441 1:1c4f440a8085 rename
441 0:6c795aa153cb a
442 0:6c795aa153cb a
442
443
443 $ hg histedit 1c4f440a8085 --commands - 2>&1 << EOF | fixbundle
444 $ hg histedit 1c4f440a8085 --commands - 2>&1 << EOF | fixbundle
444 > pick 1c4f440a8085 rename
445 > pick 1c4f440a8085 rename
445 > fold e0371e0426bc b
446 > fold e0371e0426bc b
446 > EOF
447 > EOF
447 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 reverting b.txt
449 reverting b.txt
449 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
450 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
450 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
451 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
451 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
452 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
452
453
453 $ hg logt --follow b.txt
454 $ hg logt --follow b.txt
454 1:cf858d235c76 rename
455 1:cf858d235c76 rename
455 0:6c795aa153cb a
456 0:6c795aa153cb a
456
457
457 $ cd ..
458 $ cd ..
458
459
459 Folding with swapping
460 Folding with swapping
460 ---------------------
461 ---------------------
461
462
462 This is an excuse to test hook with histedit temporary commit (issue4422)
463 This is an excuse to test hook with histedit temporary commit (issue4422)
463
464
464
465
465 $ hg init issue4422
466 $ hg init issue4422
466 $ cd issue4422
467 $ cd issue4422
467 $ echo a > a.txt
468 $ echo a > a.txt
468 $ hg add a.txt
469 $ hg add a.txt
469 $ hg commit -m a
470 $ hg commit -m a
470 $ echo b > b.txt
471 $ echo b > b.txt
471 $ hg add b.txt
472 $ hg add b.txt
472 $ hg commit -m b
473 $ hg commit -m b
473 $ echo c > c.txt
474 $ echo c > c.txt
474 $ hg add c.txt
475 $ hg add c.txt
475 $ hg commit -m c
476 $ hg commit -m c
476
477
477 $ hg logt
478 $ hg logt
478 2:a1a953ffb4b0 c
479 2:a1a953ffb4b0 c
479 1:199b6bb90248 b
480 1:199b6bb90248 b
480 0:6c795aa153cb a
481 0:6c795aa153cb a
481
482
482 Setup the proper environment variable symbol for the platform, to be subbed
483 Setup the proper environment variable symbol for the platform, to be subbed
483 into the hook command.
484 into the hook command.
484 #if windows
485 #if windows
485 $ NODE="%HG_NODE%"
486 $ NODE="%HG_NODE%"
486 #else
487 #else
487 $ NODE="\$HG_NODE"
488 $ NODE="\$HG_NODE"
488 #endif
489 #endif
489 $ hg histedit 6c795aa153cb --config hooks.commit="echo commit $NODE" --commands - 2>&1 << EOF | fixbundle
490 $ hg histedit 6c795aa153cb --config hooks.commit="echo commit $NODE" --commands - 2>&1 << EOF | fixbundle
490 > pick 199b6bb90248 b
491 > pick 199b6bb90248 b
491 > fold a1a953ffb4b0 c
492 > fold a1a953ffb4b0 c
492 > pick 6c795aa153cb a
493 > pick 6c795aa153cb a
493 > EOF
494 > EOF
494 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
495 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
495 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
496 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
496 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
497 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
497 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
499 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
499 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 commit 9599899f62c05f4377548c32bf1c9f1a39634b0c
501 commit 9599899f62c05f4377548c32bf1c9f1a39634b0c
501
502
502 $ hg logt
503 $ hg logt
503 1:9599899f62c0 a
504 1:9599899f62c0 a
504 0:79b99e9c8e49 b
505 0:79b99e9c8e49 b
505
506
506 $ echo "foo" > amended.txt
507 $ echo "foo" > amended.txt
507 $ hg add amended.txt
508 $ hg add amended.txt
508 $ hg ci -q --config extensions.largefiles= --amend -I amended.txt
509 $ hg ci -q --config extensions.largefiles= --amend -I amended.txt
509
510
510 Test that folding multiple changes in a row doesn't show multiple
511 Test that folding multiple changes in a row doesn't show multiple
511 editors.
512 editors.
512
513
513 $ echo foo >> foo
514 $ echo foo >> foo
514 $ hg add foo
515 $ hg add foo
515 $ hg ci -m foo1
516 $ hg ci -m foo1
516 $ echo foo >> foo
517 $ echo foo >> foo
517 $ hg ci -m foo2
518 $ hg ci -m foo2
518 $ echo foo >> foo
519 $ echo foo >> foo
519 $ hg ci -m foo3
520 $ hg ci -m foo3
520 $ hg logt
521 $ hg logt
521 4:21679ff7675c foo3
522 4:21679ff7675c foo3
522 3:b7389cc4d66e foo2
523 3:b7389cc4d66e foo2
523 2:0e01aeef5fa8 foo1
524 2:0e01aeef5fa8 foo1
524 1:578c7455730c a
525 1:578c7455730c a
525 0:79b99e9c8e49 b
526 0:79b99e9c8e49 b
526 $ cat > $TESTTMP/editor.sh <<EOF
527 $ cat > $TESTTMP/editor.sh <<EOF
527 > echo ran editor >> $TESTTMP/editorlog.txt
528 > echo ran editor >> $TESTTMP/editorlog.txt
528 > cat \$1 >> $TESTTMP/editorlog.txt
529 > cat \$1 >> $TESTTMP/editorlog.txt
529 > echo END >> $TESTTMP/editorlog.txt
530 > echo END >> $TESTTMP/editorlog.txt
530 > echo merged foos > \$1
531 > echo merged foos > \$1
531 > EOF
532 > EOF
532 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 1 --commands - 2>&1 <<EOF | fixbundle
533 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 1 --commands - 2>&1 <<EOF | fixbundle
533 > pick 578c7455730c 1 a
534 > pick 578c7455730c 1 a
534 > pick 0e01aeef5fa8 2 foo1
535 > pick 0e01aeef5fa8 2 foo1
535 > fold b7389cc4d66e 3 foo2
536 > fold b7389cc4d66e 3 foo2
536 > fold 21679ff7675c 4 foo3
537 > fold 21679ff7675c 4 foo3
537 > EOF
538 > EOF
538 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 reverting foo
540 reverting foo
540 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
541 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
541 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
543 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
543 merging foo
544 merging foo
544 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
545 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
545 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
546 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
546 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
547 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
547 $ hg logt
548 $ hg logt
548 2:e8bedbda72c1 merged foos
549 2:e8bedbda72c1 merged foos
549 1:578c7455730c a
550 1:578c7455730c a
550 0:79b99e9c8e49 b
551 0:79b99e9c8e49 b
551 Editor should have run only once
552 Editor should have run only once
552 $ cat $TESTTMP/editorlog.txt
553 $ cat $TESTTMP/editorlog.txt
553 ran editor
554 ran editor
554 foo1
555 foo1
555 ***
556 ***
556 foo2
557 foo2
557 ***
558 ***
558 foo3
559 foo3
559
560
560
561
561
562
562 HG: Enter commit message. Lines beginning with 'HG:' are removed.
563 HG: Enter commit message. Lines beginning with 'HG:' are removed.
563 HG: Leave message empty to abort commit.
564 HG: Leave message empty to abort commit.
564 HG: --
565 HG: --
565 HG: user: test
566 HG: user: test
566 HG: branch 'default'
567 HG: branch 'default'
567 HG: added foo
568 HG: added foo
568 END
569 END
569
570
570 $ cd ..
571 $ cd ..
@@ -1,460 +1,463 b''
1 $ . "$TESTDIR/histedit-helpers.sh"
1 $ . "$TESTDIR/histedit-helpers.sh"
2
2
3 Enable obsolete
3 Enable obsolete
4
4
5 $ cat >> $HGRCPATH << EOF
5 $ cat >> $HGRCPATH << EOF
6 > [ui]
6 > [ui]
7 > logtemplate= {rev}:{node|short} {desc|firstline}
7 > logtemplate= {rev}:{node|short} {desc|firstline}
8 > [phases]
8 > [phases]
9 > publish=False
9 > publish=False
10 > [experimental]
10 > [experimental]
11 > evolution=createmarkers,allowunstable
11 > evolution=createmarkers,allowunstable
12 > [extensions]
12 > [extensions]
13 > histedit=
13 > histedit=
14 > rebase=
14 > rebase=
15 > EOF
15 > EOF
16
16
17 $ hg init base
17 $ hg init base
18 $ cd base
18 $ cd base
19
19
20 $ for x in a b c d e f ; do
20 $ for x in a b c d e f ; do
21 > echo $x > $x
21 > echo $x > $x
22 > hg add $x
22 > hg add $x
23 > hg ci -m $x
23 > hg ci -m $x
24 > done
24 > done
25
25
26 $ hg log --graph
26 $ hg log --graph
27 @ 5:652413bf663e f
27 @ 5:652413bf663e f
28 |
28 |
29 o 4:e860deea161a e
29 o 4:e860deea161a e
30 |
30 |
31 o 3:055a42cdd887 d
31 o 3:055a42cdd887 d
32 |
32 |
33 o 2:177f92b77385 c
33 o 2:177f92b77385 c
34 |
34 |
35 o 1:d2ae7f538514 b
35 o 1:d2ae7f538514 b
36 |
36 |
37 o 0:cb9a9f314b8b a
37 o 0:cb9a9f314b8b a
38
38
39
39
40 $ HGEDITOR=cat hg histedit 1
40 $ HGEDITOR=cat hg histedit 1
41 pick d2ae7f538514 1 b
41 pick d2ae7f538514 1 b
42 pick 177f92b77385 2 c
42 pick 177f92b77385 2 c
43 pick 055a42cdd887 3 d
43 pick 055a42cdd887 3 d
44 pick e860deea161a 4 e
44 pick e860deea161a 4 e
45 pick 652413bf663e 5 f
45 pick 652413bf663e 5 f
46
46
47 # Edit history between d2ae7f538514 and 652413bf663e
47 # Edit history between d2ae7f538514 and 652413bf663e
48 #
48 #
49 # Commits are listed from least to most recent
49 # Commits are listed from least to most recent
50 #
50 #
51 # Commands:
51 # Commands:
52 # p, pick = use commit
52 # p, pick = use commit
53 # e, edit = use commit, but stop for amending
53 # e, edit = use commit, but stop for amending
54 # f, fold = use commit, but combine it with the one above
54 # f, fold = use commit, but combine it with the one above
55 # r, roll = like fold, but discard this commit's description
55 # r, roll = like fold, but discard this commit's description
56 # d, drop = remove commit from history
56 # d, drop = remove commit from history
57 # m, mess = edit commit message without changing commit content
57 # m, mess = edit commit message without changing commit content
58 #
58 #
59 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
60 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
61 > pick 177f92b77385 2 c
61 > pick 177f92b77385 2 c
62 > drop d2ae7f538514 1 b
62 > drop d2ae7f538514 1 b
63 > pick 055a42cdd887 3 d
63 > pick 055a42cdd887 3 d
64 > fold e860deea161a 4 e
64 > fold e860deea161a 4 e
65 > pick 652413bf663e 5 f
65 > pick 652413bf663e 5 f
66 > EOF
66 > EOF
67 saved backup bundle to $TESTTMP/base/.hg/strip-backup/96e494a2d553-3c6c5d92-backup.hg (glob)
67 [1]
68 $ hg log --graph --hidden
68 $ hg log --graph --hidden
69 @ 8:cacdfd884a93 f
69 @ 10:cacdfd884a93 f
70 |
71 o 9:59d9f330561f d
70 |
72 |
71 o 7:59d9f330561f d
73 | x 8:b558abc46d09 fold-temp-revision e860deea161a
72 |
74 | |
75 | x 7:96e494a2d553 d
76 |/
73 o 6:b346ab9a313d c
77 o 6:b346ab9a313d c
74 |
78 |
75 | x 5:652413bf663e f
79 | x 5:652413bf663e f
76 | |
80 | |
77 | x 4:e860deea161a e
81 | x 4:e860deea161a e
78 | |
82 | |
79 | x 3:055a42cdd887 d
83 | x 3:055a42cdd887 d
80 | |
84 | |
81 | x 2:177f92b77385 c
85 | x 2:177f92b77385 c
82 | |
86 | |
83 | x 1:d2ae7f538514 b
87 | x 1:d2ae7f538514 b
84 |/
88 |/
85 o 0:cb9a9f314b8b a
89 o 0:cb9a9f314b8b a
86
90
87 $ hg debugobsolete
91 $ hg debugobsolete
92 96e494a2d553dd05902ba1cee1d94d4cb7b8faed 0 {b346ab9a313db8537ecf96fca3ca3ca984ef3bd7} (*) {'user': 'test'} (glob)
93 b558abc46d09c30f57ac31e85a8a3d64d2e906e4 0 {96e494a2d553dd05902ba1cee1d94d4cb7b8faed} (*) {'user': 'test'} (glob)
88 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b} (*) {'user': 'test'} (glob)
94 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b} (*) {'user': 'test'} (glob)
89 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 (*) {'user': 'test'} (glob)
95 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 (*) {'user': 'test'} (glob)
90 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
96 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
91 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
97 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
92 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 (*) {'user': 'test'} (glob)
98 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 (*) {'user': 'test'} (glob)
93
99
94
100
95 Ensure hidden revision does not prevent histedit
101 Ensure hidden revision does not prevent histedit
96 -------------------------------------------------
102 -------------------------------------------------
97
103
98 create an hidden revision
104 create an hidden revision
99
105
100 $ hg histedit 6 --commands - << EOF
106 $ hg histedit 6 --commands - << EOF
101 > pick b346ab9a313d 6 c
107 > pick b346ab9a313d 6 c
102 > drop 59d9f330561f 7 d
108 > drop 59d9f330561f 7 d
103 > pick cacdfd884a93 8 f
109 > pick cacdfd884a93 8 f
104 > EOF
110 > EOF
105 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
111 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
106 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 $ hg log --graph
113 $ hg log --graph
108 @ 9:c13eb81022ca f
114 @ 11:c13eb81022ca f
109 |
115 |
110 o 6:b346ab9a313d c
116 o 6:b346ab9a313d c
111 |
117 |
112 o 0:cb9a9f314b8b a
118 o 0:cb9a9f314b8b a
113
119
114 check hidden revision are ignored (6 have hidden children 7 and 8)
120 check hidden revision are ignored (6 have hidden children 7 and 8)
115
121
116 $ hg histedit 6 --commands - << EOF
122 $ hg histedit 6 --commands - << EOF
117 > pick b346ab9a313d 6 c
123 > pick b346ab9a313d 6 c
118 > pick c13eb81022ca 8 f
124 > pick c13eb81022ca 8 f
119 > EOF
125 > EOF
120 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
121
127
122
128
123
129
124 Test that rewriting leaving instability behind is allowed
130 Test that rewriting leaving instability behind is allowed
125 ---------------------------------------------------------------------
131 ---------------------------------------------------------------------
126
132
127 $ hg up '.^'
133 $ hg up '.^'
128 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
134 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
129 $ hg log -r 'children(.)'
135 $ hg log -r 'children(.)'
130 9:c13eb81022ca f (no-eol)
136 11:c13eb81022ca f (no-eol)
131 $ hg histedit -r '.' --commands - <<EOF
137 $ hg histedit -r '.' --commands - <<EOF
132 > edit b346ab9a313d 6 c
138 > edit b346ab9a313d 6 c
133 > EOF
139 > EOF
134 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
140 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
135 adding c
141 adding c
136 Make changes as needed, you may commit or record as needed now.
142 Make changes as needed, you may commit or record as needed now.
137 When you are finished, run hg histedit --continue to resume.
143 When you are finished, run hg histedit --continue to resume.
138 [1]
144 [1]
139 $ echo c >> c
145 $ echo c >> c
140 $ hg histedit --continue
146 $ hg histedit --continue
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142
148
143 $ hg log -r 'unstable()'
149 $ hg log -r 'unstable()'
144 9:c13eb81022ca f (no-eol)
150 11:c13eb81022ca f (no-eol)
145
151
146 stabilise
152 stabilise
147
153
148 $ hg rebase -r 'unstable()' -d .
154 $ hg rebase -r 'unstable()' -d .
149 rebasing 9:c13eb81022ca "f"
155 rebasing 11:c13eb81022ca "f"
150 $ hg up tip -q
156 $ hg up tip -q
151
157
152 Test dropping of changeset on the top of the stack
158 Test dropping of changeset on the top of the stack
153 -------------------------------------------------------
159 -------------------------------------------------------
154
160
155 Nothing is rewritten below, the working directory parent must be change for the
161 Nothing is rewritten below, the working directory parent must be change for the
156 dropped changeset to be hidden.
162 dropped changeset to be hidden.
157
163
158 $ cd ..
164 $ cd ..
159 $ hg clone base droplast
165 $ hg clone base droplast
160 updating to branch default
166 updating to branch default
161 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
167 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 $ cd droplast
168 $ cd droplast
163 $ hg histedit -r '40db8afa467b' --commands - << EOF
169 $ hg histedit -r '40db8afa467b' --commands - << EOF
164 > pick 40db8afa467b 10 c
170 > pick 40db8afa467b 10 c
165 > drop b449568bf7fc 11 f
171 > drop b449568bf7fc 11 f
166 > EOF
172 > EOF
167 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
173 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
168 $ hg log -G
174 $ hg log -G
169 @ 10:40db8afa467b c
175 @ 12:40db8afa467b c
170 |
176 |
171 o 0:cb9a9f314b8b a
177 o 0:cb9a9f314b8b a
172
178
173
179
174 With rewritten ancestors
180 With rewritten ancestors
175
181
176 $ echo e > e
182 $ echo e > e
177 $ hg add e
183 $ hg add e
178 $ hg commit -m g
184 $ hg commit -m g
179 $ echo f > f
185 $ echo f > f
180 $ hg add f
186 $ hg add f
181 $ hg commit -m h
187 $ hg commit -m h
182 $ hg histedit -r '40db8afa467b' --commands - << EOF
188 $ hg histedit -r '40db8afa467b' --commands - << EOF
183 > pick 47a8561c0449 12 g
189 > pick 47a8561c0449 12 g
184 > pick 40db8afa467b 10 c
190 > pick 40db8afa467b 10 c
185 > drop 1b3b05f35ff0 13 h
191 > drop 1b3b05f35ff0 13 h
186 > EOF
192 > EOF
187 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
193 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
188 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
194 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 $ hg log -G
196 $ hg log -G
191 @ 15:ee6544123ab8 c
197 @ 17:ee6544123ab8 c
192 |
198 |
193 o 14:269e713e9eae g
199 o 16:269e713e9eae g
194 |
200 |
195 o 0:cb9a9f314b8b a
201 o 0:cb9a9f314b8b a
196
202
197 $ cd ../base
203 $ cd ../base
198
204
199
205
200
206
201 Test phases support
207 Test phases support
202 ===========================================
208 ===========================================
203
209
204 Check that histedit respect immutability
210 Check that histedit respect immutability
205 -------------------------------------------
211 -------------------------------------------
206
212
207 $ cat >> $HGRCPATH << EOF
213 $ cat >> $HGRCPATH << EOF
208 > [ui]
214 > [ui]
209 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
215 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
210 > EOF
216 > EOF
211
217
212 $ hg ph -pv '.^'
218 $ hg ph -pv '.^'
213 phase changed for 2 changesets
219 phase changed for 2 changesets
214 $ hg log -G
220 $ hg log -G
215 @ 11:b449568bf7fc (draft) f
221 @ 13:b449568bf7fc (draft) f
216 |
222 |
217 o 10:40db8afa467b (public) c
223 o 12:40db8afa467b (public) c
218 |
224 |
219 o 0:cb9a9f314b8b (public) a
225 o 0:cb9a9f314b8b (public) a
220
226
221 $ hg histedit -r '.~2'
227 $ hg histedit -r '.~2'
222 abort: cannot edit public changeset: cb9a9f314b8b
228 abort: cannot edit public changeset: cb9a9f314b8b
223 (see "hg help phases" for details)
229 (see "hg help phases" for details)
224 [255]
230 [255]
225
231
226
232
227 Prepare further testing
233 Prepare further testing
228 -------------------------------------------
234 -------------------------------------------
229
235
230 $ for x in g h i j k ; do
236 $ for x in g h i j k ; do
231 > echo $x > $x
237 > echo $x > $x
232 > hg add $x
238 > hg add $x
233 > hg ci -m $x
239 > hg ci -m $x
234 > done
240 > done
235 $ hg phase --force --secret .~2
241 $ hg phase --force --secret .~2
236 $ hg log -G
242 $ hg log -G
237 @ 16:ee118ab9fa44 (secret) k
243 @ 18:ee118ab9fa44 (secret) k
238 |
244 |
239 o 15:3a6c53ee7f3d (secret) j
245 o 17:3a6c53ee7f3d (secret) j
240 |
246 |
241 o 14:b605fb7503f2 (secret) i
247 o 16:b605fb7503f2 (secret) i
242 |
248 |
243 o 13:7395e1ff83bd (draft) h
249 o 15:7395e1ff83bd (draft) h
244 |
250 |
245 o 12:6b70183d2492 (draft) g
251 o 14:6b70183d2492 (draft) g
246 |
252 |
247 o 11:b449568bf7fc (draft) f
253 o 13:b449568bf7fc (draft) f
248 |
254 |
249 o 10:40db8afa467b (public) c
255 o 12:40db8afa467b (public) c
250 |
256 |
251 o 0:cb9a9f314b8b (public) a
257 o 0:cb9a9f314b8b (public) a
252
258
253 $ cd ..
259 $ cd ..
254
260
255 simple phase conservation
261 simple phase conservation
256 -------------------------------------------
262 -------------------------------------------
257
263
258 Resulting changeset should conserve the phase of the original one whatever the
264 Resulting changeset should conserve the phase of the original one whatever the
259 phases.new-commit option is.
265 phases.new-commit option is.
260
266
261 New-commit as draft (default)
267 New-commit as draft (default)
262
268
263 $ cp -r base simple-draft
269 $ cp -r base simple-draft
264 $ cd simple-draft
270 $ cd simple-draft
265 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
271 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
266 > edit b449568bf7fc 11 f
272 > edit b449568bf7fc 11 f
267 > pick 6b70183d2492 12 g
273 > pick 6b70183d2492 12 g
268 > pick 7395e1ff83bd 13 h
274 > pick 7395e1ff83bd 13 h
269 > pick b605fb7503f2 14 i
275 > pick b605fb7503f2 14 i
270 > pick 3a6c53ee7f3d 15 j
276 > pick 3a6c53ee7f3d 15 j
271 > pick ee118ab9fa44 16 k
277 > pick ee118ab9fa44 16 k
272 > EOF
278 > EOF
273 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
279 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
274 adding f
280 adding f
275 Make changes as needed, you may commit or record as needed now.
281 Make changes as needed, you may commit or record as needed now.
276 When you are finished, run hg histedit --continue to resume.
282 When you are finished, run hg histedit --continue to resume.
277 [1]
283 [1]
278 $ echo f >> f
284 $ echo f >> f
279 $ hg histedit --continue
285 $ hg histedit --continue
280 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
286 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
281 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
282 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
289 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
291 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
286 $ hg log -G
292 $ hg log -G
287 @ 22:12e89af74238 (secret) k
293 @ 24:12e89af74238 (secret) k
288 |
294 |
289 o 21:636a8687b22e (secret) j
295 o 23:636a8687b22e (secret) j
290 |
296 |
291 o 20:ccaf0a38653f (secret) i
297 o 22:ccaf0a38653f (secret) i
292 |
298 |
293 o 19:11a89d1c2613 (draft) h
299 o 21:11a89d1c2613 (draft) h
294 |
300 |
295 o 18:c1dec7ca82ea (draft) g
301 o 20:c1dec7ca82ea (draft) g
296 |
302 |
297 o 17:087281e68428 (draft) f
303 o 19:087281e68428 (draft) f
298 |
304 |
299 o 10:40db8afa467b (public) c
305 o 12:40db8afa467b (public) c
300 |
306 |
301 o 0:cb9a9f314b8b (public) a
307 o 0:cb9a9f314b8b (public) a
302
308
303 $ cd ..
309 $ cd ..
304
310
305
311
306 New-commit as draft (default)
312 New-commit as draft (default)
307
313
308 $ cp -r base simple-secret
314 $ cp -r base simple-secret
309 $ cd simple-secret
315 $ cd simple-secret
310 $ cat >> .hg/hgrc << EOF
316 $ cat >> .hg/hgrc << EOF
311 > [phases]
317 > [phases]
312 > new-commit=secret
318 > new-commit=secret
313 > EOF
319 > EOF
314 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
320 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
315 > edit b449568bf7fc 11 f
321 > edit b449568bf7fc 11 f
316 > pick 6b70183d2492 12 g
322 > pick 6b70183d2492 12 g
317 > pick 7395e1ff83bd 13 h
323 > pick 7395e1ff83bd 13 h
318 > pick b605fb7503f2 14 i
324 > pick b605fb7503f2 14 i
319 > pick 3a6c53ee7f3d 15 j
325 > pick 3a6c53ee7f3d 15 j
320 > pick ee118ab9fa44 16 k
326 > pick ee118ab9fa44 16 k
321 > EOF
327 > EOF
322 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
328 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
323 adding f
329 adding f
324 Make changes as needed, you may commit or record as needed now.
330 Make changes as needed, you may commit or record as needed now.
325 When you are finished, run hg histedit --continue to resume.
331 When you are finished, run hg histedit --continue to resume.
326 [1]
332 [1]
327 $ echo f >> f
333 $ echo f >> f
328 $ hg histedit --continue
334 $ hg histedit --continue
329 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
336 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
338 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
339 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 $ hg log -G
341 $ hg log -G
336 @ 22:12e89af74238 (secret) k
342 @ 24:12e89af74238 (secret) k
337 |
343 |
338 o 21:636a8687b22e (secret) j
344 o 23:636a8687b22e (secret) j
339 |
345 |
340 o 20:ccaf0a38653f (secret) i
346 o 22:ccaf0a38653f (secret) i
341 |
347 |
342 o 19:11a89d1c2613 (draft) h
348 o 21:11a89d1c2613 (draft) h
343 |
349 |
344 o 18:c1dec7ca82ea (draft) g
350 o 20:c1dec7ca82ea (draft) g
345 |
351 |
346 o 17:087281e68428 (draft) f
352 o 19:087281e68428 (draft) f
347 |
353 |
348 o 10:40db8afa467b (public) c
354 o 12:40db8afa467b (public) c
349 |
355 |
350 o 0:cb9a9f314b8b (public) a
356 o 0:cb9a9f314b8b (public) a
351
357
352 $ cd ..
358 $ cd ..
353
359
354
360
355 Changeset reordering
361 Changeset reordering
356 -------------------------------------------
362 -------------------------------------------
357
363
358 If a secret changeset is put before a draft one, all descendant should be secret.
364 If a secret changeset is put before a draft one, all descendant should be secret.
359 It seems more important to present the secret phase.
365 It seems more important to present the secret phase.
360
366
361 $ cp -r base reorder
367 $ cp -r base reorder
362 $ cd reorder
368 $ cd reorder
363 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
369 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
364 > pick b449568bf7fc 11 f
370 > pick b449568bf7fc 11 f
365 > pick 3a6c53ee7f3d 15 j
371 > pick 3a6c53ee7f3d 15 j
366 > pick 6b70183d2492 12 g
372 > pick 6b70183d2492 12 g
367 > pick b605fb7503f2 14 i
373 > pick b605fb7503f2 14 i
368 > pick 7395e1ff83bd 13 h
374 > pick 7395e1ff83bd 13 h
369 > pick ee118ab9fa44 16 k
375 > pick ee118ab9fa44 16 k
370 > EOF
376 > EOF
371 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
377 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
372 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
373 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
379 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
380 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 $ hg log -G
383 $ hg log -G
378 @ 21:558246857888 (secret) k
384 @ 23:558246857888 (secret) k
379 |
385 |
380 o 20:28bd44768535 (secret) h
386 o 22:28bd44768535 (secret) h
381 |
387 |
382 o 19:d5395202aeb9 (secret) i
388 o 21:d5395202aeb9 (secret) i
383 |
389 |
384 o 18:21edda8e341b (secret) g
390 o 20:21edda8e341b (secret) g
385 |
391 |
386 o 17:5ab64f3a4832 (secret) j
392 o 19:5ab64f3a4832 (secret) j
387 |
393 |
388 o 11:b449568bf7fc (draft) f
394 o 13:b449568bf7fc (draft) f
389 |
395 |
390 o 10:40db8afa467b (public) c
396 o 12:40db8afa467b (public) c
391 |
397 |
392 o 0:cb9a9f314b8b (public) a
398 o 0:cb9a9f314b8b (public) a
393
399
394 $ cd ..
400 $ cd ..
395
401
396 Changeset folding
402 Changeset folding
397 -------------------------------------------
403 -------------------------------------------
398
404
399 Folding a secret changeset with a draft one turn the result secret (again,
405 Folding a secret changeset with a draft one turn the result secret (again,
400 better safe than sorry). Folding between same phase changeset still works
406 better safe than sorry). Folding between same phase changeset still works
401
407
402 Note that there is a few reordering in this series for more extensive test
408 Note that there is a few reordering in this series for more extensive test
403
409
404 $ cp -r base folding
410 $ cp -r base folding
405 $ cd folding
411 $ cd folding
406 $ cat >> .hg/hgrc << EOF
412 $ cat >> .hg/hgrc << EOF
407 > [phases]
413 > [phases]
408 > new-commit=secret
414 > new-commit=secret
409 > EOF
415 > EOF
410 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
416 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
411 > pick 7395e1ff83bd 13 h
417 > pick 7395e1ff83bd 13 h
412 > fold b449568bf7fc 11 f
418 > fold b449568bf7fc 11 f
413 > pick 6b70183d2492 12 g
419 > pick 6b70183d2492 12 g
414 > fold 3a6c53ee7f3d 15 j
420 > fold 3a6c53ee7f3d 15 j
415 > pick b605fb7503f2 14 i
421 > pick b605fb7503f2 14 i
416 > fold ee118ab9fa44 16 k
422 > fold ee118ab9fa44 16 k
417 > EOF
423 > EOF
418 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
424 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
419 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
420 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
426 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
421 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
422 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
423 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
429 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
424 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
430 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
425 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
434 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
429 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
435 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
436 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/58019c66f35f-96092fce-backup.hg (glob)
432 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/83d1858e070b-f3469cf8-backup.hg (glob)
433 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/859969f5ed7e-d89a19d7-backup.hg (glob)
434 $ hg log -G
437 $ hg log -G
435 @ 19:f9daec13fb98 (secret) i
438 @ 27:f9daec13fb98 (secret) i
436 |
439 |
437 o 18:49807617f46a (secret) g
440 o 24:49807617f46a (secret) g
438 |
441 |
439 o 17:050280826e04 (draft) h
442 o 21:050280826e04 (draft) h
440 |
443 |
441 o 10:40db8afa467b (public) c
444 o 12:40db8afa467b (public) c
442 |
445 |
443 o 0:cb9a9f314b8b (public) a
446 o 0:cb9a9f314b8b (public) a
444
447
445 $ hg co 18
448 $ hg co 49807617f46a
446 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
449 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
447 $ echo wat >> wat
450 $ echo wat >> wat
448 $ hg add wat
451 $ hg add wat
449 $ hg ci -m 'add wat'
452 $ hg ci -m 'add wat'
450 created new head
453 created new head
451 $ hg merge 19
454 $ hg merge f9daec13fb98
452 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
455 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
453 (branch merge, don't forget to commit)
456 (branch merge, don't forget to commit)
454 $ hg ci -m 'merge'
457 $ hg ci -m 'merge'
455 $ echo not wat > wat
458 $ echo not wat > wat
456 $ hg ci -m 'modify wat'
459 $ hg ci -m 'modify wat'
457 $ hg histedit 17
460 $ hg histedit 050280826e04
458 abort: cannot edit history that contains merges
461 abort: cannot edit history that contains merges
459 [255]
462 [255]
460 $ cd ..
463 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now