##// END OF EJS Templates
histedit: modify rollup to discard date from the rollup commit (issue4820)...
Ben Schmidt -
r31056:37ab9e20 default
parent child Browse files
Show More
@@ -1,1606 +1,1621
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 and date
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 and date
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. The date used
74 Edit the commit message to your liking, then close the editor. The date used
75 for the commit will be the later of the two commits' dates. For this example,
75 for the commit will be the later of the two commits' dates. For this example,
76 let's assume that the commit message was changed to ``Add beta and delta.``
76 let's assume that the commit message was changed to ``Add beta and delta.``
77 After histedit has run and had a chance to remove any old or temporary
77 After histedit has run and had a chance to remove any old or temporary
78 revisions it needed, the history looks like this::
78 revisions it needed, the history looks 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. If there are uncommitted
100 histedit --continue`` to finish this step. If there are uncommitted
101 changes, you'll be prompted for a new commit message, but the default
101 changes, you'll be prompted for a new commit message, but the default
102 commit message will be the original message for the ``edit`` ed
102 commit message will be the original message for the ``edit`` ed
103 revision, and the date of the original commit will be preserved.
103 revision, and the date of the original commit will be preserved.
104
104
105 The ``message`` operation will give you a chance to revise a commit
105 The ``message`` operation will give you a chance to revise a commit
106 message without changing the contents. It's a shortcut for doing
106 message without changing the contents. It's a shortcut for doing
107 ``edit`` immediately followed by `hg histedit --continue``.
107 ``edit`` immediately followed by `hg histedit --continue``.
108
108
109 If ``histedit`` encounters a conflict when moving a revision (while
109 If ``histedit`` encounters a conflict when moving a revision (while
110 handling ``pick`` or ``fold``), it'll stop in a similar manner to
110 handling ``pick`` or ``fold``), it'll stop in a similar manner to
111 ``edit`` with the difference that it won't prompt you for a commit
111 ``edit`` with the difference that it won't prompt you for a commit
112 message when done. If you decide at this point that you don't like how
112 message when done. If you decide at this point that you don't like how
113 much work it will be to rearrange history, or that you made a mistake,
113 much work it will be to rearrange history, or that you made a mistake,
114 you can use ``hg histedit --abort`` to abandon the new changes you
114 you can use ``hg histedit --abort`` to abandon the new changes you
115 have made and return to the state before you attempted to edit your
115 have made and return to the state before you attempted to edit your
116 history.
116 history.
117
117
118 If we clone the histedit-ed example repository above and add four more
118 If we clone the histedit-ed example repository above and add four more
119 changes, such that we have the following history::
119 changes, such that we have the following history::
120
120
121 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
121 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
122 | Add theta
122 | Add theta
123 |
123 |
124 o 5 140988835471 2009-04-27 18:04 -0500 stefan
124 o 5 140988835471 2009-04-27 18:04 -0500 stefan
125 | Add eta
125 | Add eta
126 |
126 |
127 o 4 122930637314 2009-04-27 18:04 -0500 stefan
127 o 4 122930637314 2009-04-27 18:04 -0500 stefan
128 | Add zeta
128 | Add zeta
129 |
129 |
130 o 3 836302820282 2009-04-27 18:04 -0500 stefan
130 o 3 836302820282 2009-04-27 18:04 -0500 stefan
131 | Add epsilon
131 | Add epsilon
132 |
132 |
133 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
133 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
134 | Add beta and delta.
134 | Add beta and delta.
135 |
135 |
136 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
136 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
137 | Add gamma
137 | Add gamma
138 |
138 |
139 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
139 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
140 Add alpha
140 Add alpha
141
141
142 If you run ``hg histedit --outgoing`` on the clone then it is the same
142 If you run ``hg histedit --outgoing`` on the clone then it is the same
143 as running ``hg histedit 836302820282``. If you need plan to push to a
143 as running ``hg histedit 836302820282``. If you need plan to push to a
144 repository that Mercurial does not detect to be related to the source
144 repository that Mercurial does not detect to be related to the source
145 repo, you can add a ``--force`` option.
145 repo, you can add a ``--force`` option.
146
146
147 Config
147 Config
148 ------
148 ------
149
149
150 Histedit rule lines are truncated to 80 characters by default. You
150 Histedit rule lines are truncated to 80 characters by default. You
151 can customize this behavior by setting a different length in your
151 can customize this behavior by setting a different length in your
152 configuration file::
152 configuration file::
153
153
154 [histedit]
154 [histedit]
155 linelen = 120 # truncate rule lines at 120 characters
155 linelen = 120 # truncate rule lines at 120 characters
156
156
157 ``hg histedit`` attempts to automatically choose an appropriate base
157 ``hg histedit`` attempts to automatically choose an appropriate base
158 revision to use. To change which base revision is used, define a
158 revision to use. To change which base revision is used, define a
159 revset in your configuration file::
159 revset in your configuration file::
160
160
161 [histedit]
161 [histedit]
162 defaultrev = only(.) & draft()
162 defaultrev = only(.) & draft()
163
163
164 By default each edited revision needs to be present in histedit commands.
164 By default each edited revision needs to be present in histedit commands.
165 To remove revision you need to use ``drop`` operation. You can configure
165 To remove revision you need to use ``drop`` operation. You can configure
166 the drop to be implicit for missing commits by adding::
166 the drop to be implicit for missing commits by adding::
167
167
168 [histedit]
168 [histedit]
169 dropmissing = True
169 dropmissing = True
170
170
171 """
171 """
172
172
173 from __future__ import absolute_import
173 from __future__ import absolute_import
174
174
175 import errno
175 import errno
176 import os
176 import os
177
177
178 from mercurial.i18n import _
178 from mercurial.i18n import _
179 from mercurial import (
179 from mercurial import (
180 bundle2,
180 bundle2,
181 cmdutil,
181 cmdutil,
182 context,
182 context,
183 copies,
183 copies,
184 destutil,
184 destutil,
185 discovery,
185 discovery,
186 error,
186 error,
187 exchange,
187 exchange,
188 extensions,
188 extensions,
189 hg,
189 hg,
190 lock,
190 lock,
191 merge as mergemod,
191 merge as mergemod,
192 node,
192 node,
193 obsolete,
193 obsolete,
194 repair,
194 repair,
195 scmutil,
195 scmutil,
196 util,
196 util,
197 )
197 )
198
198
199 pickle = util.pickle
199 pickle = util.pickle
200 release = lock.release
200 release = lock.release
201 cmdtable = {}
201 cmdtable = {}
202 command = cmdutil.command(cmdtable)
202 command = cmdutil.command(cmdtable)
203
203
204 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
204 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
205 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
205 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
206 # be specifying the version(s) of Mercurial they are tested with, or
206 # be specifying the version(s) of Mercurial they are tested with, or
207 # leave the attribute unspecified.
207 # leave the attribute unspecified.
208 testedwith = 'ships-with-hg-core'
208 testedwith = 'ships-with-hg-core'
209
209
210 actiontable = {}
210 actiontable = {}
211 primaryactions = set()
211 primaryactions = set()
212 secondaryactions = set()
212 secondaryactions = set()
213 tertiaryactions = set()
213 tertiaryactions = set()
214 internalactions = set()
214 internalactions = set()
215
215
216 def geteditcomment(ui, first, last):
216 def geteditcomment(ui, first, last):
217 """ construct the editor comment
217 """ construct the editor comment
218 The comment includes::
218 The comment includes::
219 - an intro
219 - an intro
220 - sorted primary commands
220 - sorted primary commands
221 - sorted short commands
221 - sorted short commands
222 - sorted long commands
222 - sorted long commands
223 - additional hints
223 - additional hints
224
224
225 Commands are only included once.
225 Commands are only included once.
226 """
226 """
227 intro = _("""Edit history between %s and %s
227 intro = _("""Edit history between %s and %s
228
228
229 Commits are listed from least to most recent
229 Commits are listed from least to most recent
230
230
231 You can reorder changesets by reordering the lines
231 You can reorder changesets by reordering the lines
232
232
233 Commands:
233 Commands:
234 """)
234 """)
235 actions = []
235 actions = []
236 def addverb(v):
236 def addverb(v):
237 a = actiontable[v]
237 a = actiontable[v]
238 lines = a.message.split("\n")
238 lines = a.message.split("\n")
239 if len(a.verbs):
239 if len(a.verbs):
240 v = ', '.join(sorted(a.verbs, key=lambda v: len(v)))
240 v = ', '.join(sorted(a.verbs, key=lambda v: len(v)))
241 actions.append(" %s = %s" % (v, lines[0]))
241 actions.append(" %s = %s" % (v, lines[0]))
242 actions.extend([' %s' for l in lines[1:]])
242 actions.extend([' %s' for l in lines[1:]])
243
243
244 for v in (
244 for v in (
245 sorted(primaryactions) +
245 sorted(primaryactions) +
246 sorted(secondaryactions) +
246 sorted(secondaryactions) +
247 sorted(tertiaryactions)
247 sorted(tertiaryactions)
248 ):
248 ):
249 addverb(v)
249 addverb(v)
250 actions.append('')
250 actions.append('')
251
251
252 hints = []
252 hints = []
253 if ui.configbool('histedit', 'dropmissing'):
253 if ui.configbool('histedit', 'dropmissing'):
254 hints.append("Deleting a changeset from the list "
254 hints.append("Deleting a changeset from the list "
255 "will DISCARD it from the edited history!")
255 "will DISCARD it from the edited history!")
256
256
257 lines = (intro % (first, last)).split('\n') + actions + hints
257 lines = (intro % (first, last)).split('\n') + actions + hints
258
258
259 return ''.join(['# %s\n' % l if l else '#\n' for l in lines])
259 return ''.join(['# %s\n' % l if l else '#\n' for l in lines])
260
260
261 class histeditstate(object):
261 class histeditstate(object):
262 def __init__(self, repo, parentctxnode=None, actions=None, keep=None,
262 def __init__(self, repo, parentctxnode=None, actions=None, keep=None,
263 topmost=None, replacements=None, lock=None, wlock=None):
263 topmost=None, replacements=None, lock=None, wlock=None):
264 self.repo = repo
264 self.repo = repo
265 self.actions = actions
265 self.actions = actions
266 self.keep = keep
266 self.keep = keep
267 self.topmost = topmost
267 self.topmost = topmost
268 self.parentctxnode = parentctxnode
268 self.parentctxnode = parentctxnode
269 self.lock = lock
269 self.lock = lock
270 self.wlock = wlock
270 self.wlock = wlock
271 self.backupfile = None
271 self.backupfile = None
272 if replacements is None:
272 if replacements is None:
273 self.replacements = []
273 self.replacements = []
274 else:
274 else:
275 self.replacements = replacements
275 self.replacements = replacements
276
276
277 def read(self):
277 def read(self):
278 """Load histedit state from disk and set fields appropriately."""
278 """Load histedit state from disk and set fields appropriately."""
279 try:
279 try:
280 state = self.repo.vfs.read('histedit-state')
280 state = self.repo.vfs.read('histedit-state')
281 except IOError as err:
281 except IOError as err:
282 if err.errno != errno.ENOENT:
282 if err.errno != errno.ENOENT:
283 raise
283 raise
284 cmdutil.wrongtooltocontinue(self.repo, _('histedit'))
284 cmdutil.wrongtooltocontinue(self.repo, _('histedit'))
285
285
286 if state.startswith('v1\n'):
286 if state.startswith('v1\n'):
287 data = self._load()
287 data = self._load()
288 parentctxnode, rules, keep, topmost, replacements, backupfile = data
288 parentctxnode, rules, keep, topmost, replacements, backupfile = data
289 else:
289 else:
290 data = pickle.loads(state)
290 data = pickle.loads(state)
291 parentctxnode, rules, keep, topmost, replacements = data
291 parentctxnode, rules, keep, topmost, replacements = data
292 backupfile = None
292 backupfile = None
293
293
294 self.parentctxnode = parentctxnode
294 self.parentctxnode = parentctxnode
295 rules = "\n".join(["%s %s" % (verb, rest) for [verb, rest] in rules])
295 rules = "\n".join(["%s %s" % (verb, rest) for [verb, rest] in rules])
296 actions = parserules(rules, self)
296 actions = parserules(rules, self)
297 self.actions = actions
297 self.actions = actions
298 self.keep = keep
298 self.keep = keep
299 self.topmost = topmost
299 self.topmost = topmost
300 self.replacements = replacements
300 self.replacements = replacements
301 self.backupfile = backupfile
301 self.backupfile = backupfile
302
302
303 def write(self):
303 def write(self):
304 fp = self.repo.vfs('histedit-state', 'w')
304 fp = self.repo.vfs('histedit-state', 'w')
305 fp.write('v1\n')
305 fp.write('v1\n')
306 fp.write('%s\n' % node.hex(self.parentctxnode))
306 fp.write('%s\n' % node.hex(self.parentctxnode))
307 fp.write('%s\n' % node.hex(self.topmost))
307 fp.write('%s\n' % node.hex(self.topmost))
308 fp.write('%s\n' % self.keep)
308 fp.write('%s\n' % self.keep)
309 fp.write('%d\n' % len(self.actions))
309 fp.write('%d\n' % len(self.actions))
310 for action in self.actions:
310 for action in self.actions:
311 fp.write('%s\n' % action.tostate())
311 fp.write('%s\n' % action.tostate())
312 fp.write('%d\n' % len(self.replacements))
312 fp.write('%d\n' % len(self.replacements))
313 for replacement in self.replacements:
313 for replacement in self.replacements:
314 fp.write('%s%s\n' % (node.hex(replacement[0]), ''.join(node.hex(r)
314 fp.write('%s%s\n' % (node.hex(replacement[0]), ''.join(node.hex(r)
315 for r in replacement[1])))
315 for r in replacement[1])))
316 backupfile = self.backupfile
316 backupfile = self.backupfile
317 if not backupfile:
317 if not backupfile:
318 backupfile = ''
318 backupfile = ''
319 fp.write('%s\n' % backupfile)
319 fp.write('%s\n' % backupfile)
320 fp.close()
320 fp.close()
321
321
322 def _load(self):
322 def _load(self):
323 fp = self.repo.vfs('histedit-state', 'r')
323 fp = self.repo.vfs('histedit-state', 'r')
324 lines = [l[:-1] for l in fp.readlines()]
324 lines = [l[:-1] for l in fp.readlines()]
325
325
326 index = 0
326 index = 0
327 lines[index] # version number
327 lines[index] # version number
328 index += 1
328 index += 1
329
329
330 parentctxnode = node.bin(lines[index])
330 parentctxnode = node.bin(lines[index])
331 index += 1
331 index += 1
332
332
333 topmost = node.bin(lines[index])
333 topmost = node.bin(lines[index])
334 index += 1
334 index += 1
335
335
336 keep = lines[index] == 'True'
336 keep = lines[index] == 'True'
337 index += 1
337 index += 1
338
338
339 # Rules
339 # Rules
340 rules = []
340 rules = []
341 rulelen = int(lines[index])
341 rulelen = int(lines[index])
342 index += 1
342 index += 1
343 for i in xrange(rulelen):
343 for i in xrange(rulelen):
344 ruleaction = lines[index]
344 ruleaction = lines[index]
345 index += 1
345 index += 1
346 rule = lines[index]
346 rule = lines[index]
347 index += 1
347 index += 1
348 rules.append((ruleaction, rule))
348 rules.append((ruleaction, rule))
349
349
350 # Replacements
350 # Replacements
351 replacements = []
351 replacements = []
352 replacementlen = int(lines[index])
352 replacementlen = int(lines[index])
353 index += 1
353 index += 1
354 for i in xrange(replacementlen):
354 for i in xrange(replacementlen):
355 replacement = lines[index]
355 replacement = lines[index]
356 original = node.bin(replacement[:40])
356 original = node.bin(replacement[:40])
357 succ = [node.bin(replacement[i:i + 40]) for i in
357 succ = [node.bin(replacement[i:i + 40]) for i in
358 range(40, len(replacement), 40)]
358 range(40, len(replacement), 40)]
359 replacements.append((original, succ))
359 replacements.append((original, succ))
360 index += 1
360 index += 1
361
361
362 backupfile = lines[index]
362 backupfile = lines[index]
363 index += 1
363 index += 1
364
364
365 fp.close()
365 fp.close()
366
366
367 return parentctxnode, rules, keep, topmost, replacements, backupfile
367 return parentctxnode, rules, keep, topmost, replacements, backupfile
368
368
369 def clear(self):
369 def clear(self):
370 if self.inprogress():
370 if self.inprogress():
371 self.repo.vfs.unlink('histedit-state')
371 self.repo.vfs.unlink('histedit-state')
372
372
373 def inprogress(self):
373 def inprogress(self):
374 return self.repo.vfs.exists('histedit-state')
374 return self.repo.vfs.exists('histedit-state')
375
375
376
376
377 class histeditaction(object):
377 class histeditaction(object):
378 def __init__(self, state, node):
378 def __init__(self, state, node):
379 self.state = state
379 self.state = state
380 self.repo = state.repo
380 self.repo = state.repo
381 self.node = node
381 self.node = node
382
382
383 @classmethod
383 @classmethod
384 def fromrule(cls, state, rule):
384 def fromrule(cls, state, rule):
385 """Parses the given rule, returning an instance of the histeditaction.
385 """Parses the given rule, returning an instance of the histeditaction.
386 """
386 """
387 rulehash = rule.strip().split(' ', 1)[0]
387 rulehash = rule.strip().split(' ', 1)[0]
388 try:
388 try:
389 rev = node.bin(rulehash)
389 rev = node.bin(rulehash)
390 except TypeError:
390 except TypeError:
391 raise error.ParseError("invalid changeset %s" % rulehash)
391 raise error.ParseError("invalid changeset %s" % rulehash)
392 return cls(state, rev)
392 return cls(state, rev)
393
393
394 def verify(self, prev, expected, seen):
394 def verify(self, prev, expected, seen):
395 """ Verifies semantic correctness of the rule"""
395 """ Verifies semantic correctness of the rule"""
396 repo = self.repo
396 repo = self.repo
397 ha = node.hex(self.node)
397 ha = node.hex(self.node)
398 try:
398 try:
399 self.node = repo[ha].node()
399 self.node = repo[ha].node()
400 except error.RepoError:
400 except error.RepoError:
401 raise error.ParseError(_('unknown changeset %s listed')
401 raise error.ParseError(_('unknown changeset %s listed')
402 % ha[:12])
402 % ha[:12])
403 if self.node is not None:
403 if self.node is not None:
404 self._verifynodeconstraints(prev, expected, seen)
404 self._verifynodeconstraints(prev, expected, seen)
405
405
406 def _verifynodeconstraints(self, prev, expected, seen):
406 def _verifynodeconstraints(self, prev, expected, seen):
407 # by default command need a node in the edited list
407 # by default command need a node in the edited list
408 if self.node not in expected:
408 if self.node not in expected:
409 raise error.ParseError(_('%s "%s" changeset was not a candidate')
409 raise error.ParseError(_('%s "%s" changeset was not a candidate')
410 % (self.verb, node.short(self.node)),
410 % (self.verb, node.short(self.node)),
411 hint=_('only use listed changesets'))
411 hint=_('only use listed changesets'))
412 # and only one command per node
412 # and only one command per node
413 if self.node in seen:
413 if self.node in seen:
414 raise error.ParseError(_('duplicated command for changeset %s') %
414 raise error.ParseError(_('duplicated command for changeset %s') %
415 node.short(self.node))
415 node.short(self.node))
416
416
417 def torule(self):
417 def torule(self):
418 """build a histedit rule line for an action
418 """build a histedit rule line for an action
419
419
420 by default lines are in the form:
420 by default lines are in the form:
421 <hash> <rev> <summary>
421 <hash> <rev> <summary>
422 """
422 """
423 ctx = self.repo[self.node]
423 ctx = self.repo[self.node]
424 summary = _getsummary(ctx)
424 summary = _getsummary(ctx)
425 line = '%s %s %d %s' % (self.verb, ctx, ctx.rev(), summary)
425 line = '%s %s %d %s' % (self.verb, ctx, ctx.rev(), summary)
426 # trim to 75 columns by default so it's not stupidly wide in my editor
426 # trim to 75 columns by default so it's not stupidly wide in my editor
427 # (the 5 more are left for verb)
427 # (the 5 more are left for verb)
428 maxlen = self.repo.ui.configint('histedit', 'linelen', default=80)
428 maxlen = self.repo.ui.configint('histedit', 'linelen', default=80)
429 maxlen = max(maxlen, 22) # avoid truncating hash
429 maxlen = max(maxlen, 22) # avoid truncating hash
430 return util.ellipsis(line, maxlen)
430 return util.ellipsis(line, maxlen)
431
431
432 def tostate(self):
432 def tostate(self):
433 """Print an action in format used by histedit state files
433 """Print an action in format used by histedit state files
434 (the first line is a verb, the remainder is the second)
434 (the first line is a verb, the remainder is the second)
435 """
435 """
436 return "%s\n%s" % (self.verb, node.hex(self.node))
436 return "%s\n%s" % (self.verb, node.hex(self.node))
437
437
438 def run(self):
438 def run(self):
439 """Runs the action. The default behavior is simply apply the action's
439 """Runs the action. The default behavior is simply apply the action's
440 rulectx onto the current parentctx."""
440 rulectx onto the current parentctx."""
441 self.applychange()
441 self.applychange()
442 self.continuedirty()
442 self.continuedirty()
443 return self.continueclean()
443 return self.continueclean()
444
444
445 def applychange(self):
445 def applychange(self):
446 """Applies the changes from this action's rulectx onto the current
446 """Applies the changes from this action's rulectx onto the current
447 parentctx, but does not commit them."""
447 parentctx, but does not commit them."""
448 repo = self.repo
448 repo = self.repo
449 rulectx = repo[self.node]
449 rulectx = repo[self.node]
450 repo.ui.pushbuffer(error=True, labeled=True)
450 repo.ui.pushbuffer(error=True, labeled=True)
451 hg.update(repo, self.state.parentctxnode, quietempty=True)
451 hg.update(repo, self.state.parentctxnode, quietempty=True)
452 stats = applychanges(repo.ui, repo, rulectx, {})
452 stats = applychanges(repo.ui, repo, rulectx, {})
453 if stats and stats[3] > 0:
453 if stats and stats[3] > 0:
454 buf = repo.ui.popbuffer()
454 buf = repo.ui.popbuffer()
455 repo.ui.write(*buf)
455 repo.ui.write(*buf)
456 raise error.InterventionRequired(
456 raise error.InterventionRequired(
457 _('Fix up the change (%s %s)') %
457 _('Fix up the change (%s %s)') %
458 (self.verb, node.short(self.node)),
458 (self.verb, node.short(self.node)),
459 hint=_('hg histedit --continue to resume'))
459 hint=_('hg histedit --continue to resume'))
460 else:
460 else:
461 repo.ui.popbuffer()
461 repo.ui.popbuffer()
462
462
463 def continuedirty(self):
463 def continuedirty(self):
464 """Continues the action when changes have been applied to the working
464 """Continues the action when changes have been applied to the working
465 copy. The default behavior is to commit the dirty changes."""
465 copy. The default behavior is to commit the dirty changes."""
466 repo = self.repo
466 repo = self.repo
467 rulectx = repo[self.node]
467 rulectx = repo[self.node]
468
468
469 editor = self.commiteditor()
469 editor = self.commiteditor()
470 commit = commitfuncfor(repo, rulectx)
470 commit = commitfuncfor(repo, rulectx)
471
471
472 commit(text=rulectx.description(), user=rulectx.user(),
472 commit(text=rulectx.description(), user=rulectx.user(),
473 date=rulectx.date(), extra=rulectx.extra(), editor=editor)
473 date=rulectx.date(), extra=rulectx.extra(), editor=editor)
474
474
475 def commiteditor(self):
475 def commiteditor(self):
476 """The editor to be used to edit the commit message."""
476 """The editor to be used to edit the commit message."""
477 return False
477 return False
478
478
479 def continueclean(self):
479 def continueclean(self):
480 """Continues the action when the working copy is clean. The default
480 """Continues the action when the working copy is clean. The default
481 behavior is to accept the current commit as the new version of the
481 behavior is to accept the current commit as the new version of the
482 rulectx."""
482 rulectx."""
483 ctx = self.repo['.']
483 ctx = self.repo['.']
484 if ctx.node() == self.state.parentctxnode:
484 if ctx.node() == self.state.parentctxnode:
485 self.repo.ui.warn(_('%s: skipping changeset (no changes)\n') %
485 self.repo.ui.warn(_('%s: skipping changeset (no changes)\n') %
486 node.short(self.node))
486 node.short(self.node))
487 return ctx, [(self.node, tuple())]
487 return ctx, [(self.node, tuple())]
488 if ctx.node() == self.node:
488 if ctx.node() == self.node:
489 # Nothing changed
489 # Nothing changed
490 return ctx, []
490 return ctx, []
491 return ctx, [(self.node, (ctx.node(),))]
491 return ctx, [(self.node, (ctx.node(),))]
492
492
493 def commitfuncfor(repo, src):
493 def commitfuncfor(repo, src):
494 """Build a commit function for the replacement of <src>
494 """Build a commit function for the replacement of <src>
495
495
496 This function ensure we apply the same treatment to all changesets.
496 This function ensure we apply the same treatment to all changesets.
497
497
498 - Add a 'histedit_source' entry in extra.
498 - Add a 'histedit_source' entry in extra.
499
499
500 Note that fold has its own separated logic because its handling is a bit
500 Note that fold has its own separated logic because its handling is a bit
501 different and not easily factored out of the fold method.
501 different and not easily factored out of the fold method.
502 """
502 """
503 phasemin = src.phase()
503 phasemin = src.phase()
504 def commitfunc(**kwargs):
504 def commitfunc(**kwargs):
505 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
505 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
506 try:
506 try:
507 repo.ui.setconfig('phases', 'new-commit', phasemin,
507 repo.ui.setconfig('phases', 'new-commit', phasemin,
508 'histedit')
508 'histedit')
509 extra = kwargs.get('extra', {}).copy()
509 extra = kwargs.get('extra', {}).copy()
510 extra['histedit_source'] = src.hex()
510 extra['histedit_source'] = src.hex()
511 kwargs['extra'] = extra
511 kwargs['extra'] = extra
512 return repo.commit(**kwargs)
512 return repo.commit(**kwargs)
513 finally:
513 finally:
514 repo.ui.restoreconfig(phasebackup)
514 repo.ui.restoreconfig(phasebackup)
515 return commitfunc
515 return commitfunc
516
516
517 def applychanges(ui, repo, ctx, opts):
517 def applychanges(ui, repo, ctx, opts):
518 """Merge changeset from ctx (only) in the current working directory"""
518 """Merge changeset from ctx (only) in the current working directory"""
519 wcpar = repo.dirstate.parents()[0]
519 wcpar = repo.dirstate.parents()[0]
520 if ctx.p1().node() == wcpar:
520 if ctx.p1().node() == wcpar:
521 # edits are "in place" we do not need to make any merge,
521 # edits are "in place" we do not need to make any merge,
522 # just applies changes on parent for editing
522 # just applies changes on parent for editing
523 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
523 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
524 stats = None
524 stats = None
525 else:
525 else:
526 try:
526 try:
527 # ui.forcemerge is an internal variable, do not document
527 # ui.forcemerge is an internal variable, do not document
528 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
528 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
529 'histedit')
529 'histedit')
530 stats = mergemod.graft(repo, ctx, ctx.p1(), ['local', 'histedit'])
530 stats = mergemod.graft(repo, ctx, ctx.p1(), ['local', 'histedit'])
531 finally:
531 finally:
532 repo.ui.setconfig('ui', 'forcemerge', '', 'histedit')
532 repo.ui.setconfig('ui', 'forcemerge', '', 'histedit')
533 return stats
533 return stats
534
534
535 def collapse(repo, first, last, commitopts, skipprompt=False):
535 def collapse(repo, first, last, commitopts, skipprompt=False):
536 """collapse the set of revisions from first to last as new one.
536 """collapse the set of revisions from first to last as new one.
537
537
538 Expected commit options are:
538 Expected commit options are:
539 - message
539 - message
540 - date
540 - date
541 - username
541 - username
542 Commit message is edited in all cases.
542 Commit message is edited in all cases.
543
543
544 This function works in memory."""
544 This function works in memory."""
545 ctxs = list(repo.set('%d::%d', first, last))
545 ctxs = list(repo.set('%d::%d', first, last))
546 if not ctxs:
546 if not ctxs:
547 return None
547 return None
548 for c in ctxs:
548 for c in ctxs:
549 if not c.mutable():
549 if not c.mutable():
550 raise error.ParseError(
550 raise error.ParseError(
551 _("cannot fold into public change %s") % node.short(c.node()))
551 _("cannot fold into public change %s") % node.short(c.node()))
552 base = first.parents()[0]
552 base = first.parents()[0]
553
553
554 # commit a new version of the old changeset, including the update
554 # commit a new version of the old changeset, including the update
555 # collect all files which might be affected
555 # collect all files which might be affected
556 files = set()
556 files = set()
557 for ctx in ctxs:
557 for ctx in ctxs:
558 files.update(ctx.files())
558 files.update(ctx.files())
559
559
560 # Recompute copies (avoid recording a -> b -> a)
560 # Recompute copies (avoid recording a -> b -> a)
561 copied = copies.pathcopies(base, last)
561 copied = copies.pathcopies(base, last)
562
562
563 # prune files which were reverted by the updates
563 # prune files which were reverted by the updates
564 files = [f for f in files if not cmdutil.samefile(f, last, base)]
564 files = [f for f in files if not cmdutil.samefile(f, last, base)]
565 # commit version of these files as defined by head
565 # commit version of these files as defined by head
566 headmf = last.manifest()
566 headmf = last.manifest()
567 def filectxfn(repo, ctx, path):
567 def filectxfn(repo, ctx, path):
568 if path in headmf:
568 if path in headmf:
569 fctx = last[path]
569 fctx = last[path]
570 flags = fctx.flags()
570 flags = fctx.flags()
571 mctx = context.memfilectx(repo,
571 mctx = context.memfilectx(repo,
572 fctx.path(), fctx.data(),
572 fctx.path(), fctx.data(),
573 islink='l' in flags,
573 islink='l' in flags,
574 isexec='x' in flags,
574 isexec='x' in flags,
575 copied=copied.get(path))
575 copied=copied.get(path))
576 return mctx
576 return mctx
577 return None
577 return None
578
578
579 if commitopts.get('message'):
579 if commitopts.get('message'):
580 message = commitopts['message']
580 message = commitopts['message']
581 else:
581 else:
582 message = first.description()
582 message = first.description()
583 user = commitopts.get('user')
583 user = commitopts.get('user')
584 date = commitopts.get('date')
584 date = commitopts.get('date')
585 extra = commitopts.get('extra')
585 extra = commitopts.get('extra')
586
586
587 parents = (first.p1().node(), first.p2().node())
587 parents = (first.p1().node(), first.p2().node())
588 editor = None
588 editor = None
589 if not skipprompt:
589 if not skipprompt:
590 editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold')
590 editor = cmdutil.getcommiteditor(edit=True, editform='histedit.fold')
591 new = context.memctx(repo,
591 new = context.memctx(repo,
592 parents=parents,
592 parents=parents,
593 text=message,
593 text=message,
594 files=files,
594 files=files,
595 filectxfn=filectxfn,
595 filectxfn=filectxfn,
596 user=user,
596 user=user,
597 date=date,
597 date=date,
598 extra=extra,
598 extra=extra,
599 editor=editor)
599 editor=editor)
600 return repo.commitctx(new)
600 return repo.commitctx(new)
601
601
602 def _isdirtywc(repo):
602 def _isdirtywc(repo):
603 return repo[None].dirty(missing=True)
603 return repo[None].dirty(missing=True)
604
604
605 def abortdirty():
605 def abortdirty():
606 raise error.Abort(_('working copy has pending changes'),
606 raise error.Abort(_('working copy has pending changes'),
607 hint=_('amend, commit, or revert them and run histedit '
607 hint=_('amend, commit, or revert them and run histedit '
608 '--continue, or abort with histedit --abort'))
608 '--continue, or abort with histedit --abort'))
609
609
610 def action(verbs, message, priority=False, internal=False):
610 def action(verbs, message, priority=False, internal=False):
611 def wrap(cls):
611 def wrap(cls):
612 assert not priority or not internal
612 assert not priority or not internal
613 verb = verbs[0]
613 verb = verbs[0]
614 if priority:
614 if priority:
615 primaryactions.add(verb)
615 primaryactions.add(verb)
616 elif internal:
616 elif internal:
617 internalactions.add(verb)
617 internalactions.add(verb)
618 elif len(verbs) > 1:
618 elif len(verbs) > 1:
619 secondaryactions.add(verb)
619 secondaryactions.add(verb)
620 else:
620 else:
621 tertiaryactions.add(verb)
621 tertiaryactions.add(verb)
622
622
623 cls.verb = verb
623 cls.verb = verb
624 cls.verbs = verbs
624 cls.verbs = verbs
625 cls.message = message
625 cls.message = message
626 for verb in verbs:
626 for verb in verbs:
627 actiontable[verb] = cls
627 actiontable[verb] = cls
628 return cls
628 return cls
629 return wrap
629 return wrap
630
630
631 @action(['pick', 'p'],
631 @action(['pick', 'p'],
632 _('use commit'),
632 _('use commit'),
633 priority=True)
633 priority=True)
634 class pick(histeditaction):
634 class pick(histeditaction):
635 def run(self):
635 def run(self):
636 rulectx = self.repo[self.node]
636 rulectx = self.repo[self.node]
637 if rulectx.parents()[0].node() == self.state.parentctxnode:
637 if rulectx.parents()[0].node() == self.state.parentctxnode:
638 self.repo.ui.debug('node %s unchanged\n' % node.short(self.node))
638 self.repo.ui.debug('node %s unchanged\n' % node.short(self.node))
639 return rulectx, []
639 return rulectx, []
640
640
641 return super(pick, self).run()
641 return super(pick, self).run()
642
642
643 @action(['edit', 'e'],
643 @action(['edit', 'e'],
644 _('use commit, but stop for amending'),
644 _('use commit, but stop for amending'),
645 priority=True)
645 priority=True)
646 class edit(histeditaction):
646 class edit(histeditaction):
647 def run(self):
647 def run(self):
648 repo = self.repo
648 repo = self.repo
649 rulectx = repo[self.node]
649 rulectx = repo[self.node]
650 hg.update(repo, self.state.parentctxnode, quietempty=True)
650 hg.update(repo, self.state.parentctxnode, quietempty=True)
651 applychanges(repo.ui, repo, rulectx, {})
651 applychanges(repo.ui, repo, rulectx, {})
652 raise error.InterventionRequired(
652 raise error.InterventionRequired(
653 _('Editing (%s), you may commit or record as needed now.')
653 _('Editing (%s), you may commit or record as needed now.')
654 % node.short(self.node),
654 % node.short(self.node),
655 hint=_('hg histedit --continue to resume'))
655 hint=_('hg histedit --continue to resume'))
656
656
657 def commiteditor(self):
657 def commiteditor(self):
658 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit')
658 return cmdutil.getcommiteditor(edit=True, editform='histedit.edit')
659
659
660 @action(['fold', 'f'],
660 @action(['fold', 'f'],
661 _('use commit, but combine it with the one above'))
661 _('use commit, but combine it with the one above'))
662 class fold(histeditaction):
662 class fold(histeditaction):
663 def verify(self, prev, expected, seen):
663 def verify(self, prev, expected, seen):
664 """ Verifies semantic correctness of the fold rule"""
664 """ Verifies semantic correctness of the fold rule"""
665 super(fold, self).verify(prev, expected, seen)
665 super(fold, self).verify(prev, expected, seen)
666 repo = self.repo
666 repo = self.repo
667 if not prev:
667 if not prev:
668 c = repo[self.node].parents()[0]
668 c = repo[self.node].parents()[0]
669 elif not prev.verb in ('pick', 'base'):
669 elif not prev.verb in ('pick', 'base'):
670 return
670 return
671 else:
671 else:
672 c = repo[prev.node]
672 c = repo[prev.node]
673 if not c.mutable():
673 if not c.mutable():
674 raise error.ParseError(
674 raise error.ParseError(
675 _("cannot fold into public change %s") % node.short(c.node()))
675 _("cannot fold into public change %s") % node.short(c.node()))
676
676
677
677
678 def continuedirty(self):
678 def continuedirty(self):
679 repo = self.repo
679 repo = self.repo
680 rulectx = repo[self.node]
680 rulectx = repo[self.node]
681
681
682 commit = commitfuncfor(repo, rulectx)
682 commit = commitfuncfor(repo, rulectx)
683 commit(text='fold-temp-revision %s' % node.short(self.node),
683 commit(text='fold-temp-revision %s' % node.short(self.node),
684 user=rulectx.user(), date=rulectx.date(),
684 user=rulectx.user(), date=rulectx.date(),
685 extra=rulectx.extra())
685 extra=rulectx.extra())
686
686
687 def continueclean(self):
687 def continueclean(self):
688 repo = self.repo
688 repo = self.repo
689 ctx = repo['.']
689 ctx = repo['.']
690 rulectx = repo[self.node]
690 rulectx = repo[self.node]
691 parentctxnode = self.state.parentctxnode
691 parentctxnode = self.state.parentctxnode
692 if ctx.node() == parentctxnode:
692 if ctx.node() == parentctxnode:
693 repo.ui.warn(_('%s: empty changeset\n') %
693 repo.ui.warn(_('%s: empty changeset\n') %
694 node.short(self.node))
694 node.short(self.node))
695 return ctx, [(self.node, (parentctxnode,))]
695 return ctx, [(self.node, (parentctxnode,))]
696
696
697 parentctx = repo[parentctxnode]
697 parentctx = repo[parentctxnode]
698 newcommits = set(c.node() for c in repo.set('(%d::. - %d)', parentctx,
698 newcommits = set(c.node() for c in repo.set('(%d::. - %d)', parentctx,
699 parentctx))
699 parentctx))
700 if not newcommits:
700 if not newcommits:
701 repo.ui.warn(_('%s: cannot fold - working copy is not a '
701 repo.ui.warn(_('%s: cannot fold - working copy is not a '
702 'descendant of previous commit %s\n') %
702 'descendant of previous commit %s\n') %
703 (node.short(self.node), node.short(parentctxnode)))
703 (node.short(self.node), node.short(parentctxnode)))
704 return ctx, [(self.node, (ctx.node(),))]
704 return ctx, [(self.node, (ctx.node(),))]
705
705
706 middlecommits = newcommits.copy()
706 middlecommits = newcommits.copy()
707 middlecommits.discard(ctx.node())
707 middlecommits.discard(ctx.node())
708
708
709 return self.finishfold(repo.ui, repo, parentctx, rulectx, ctx.node(),
709 return self.finishfold(repo.ui, repo, parentctx, rulectx, ctx.node(),
710 middlecommits)
710 middlecommits)
711
711
712 def skipprompt(self):
712 def skipprompt(self):
713 """Returns true if the rule should skip the message editor.
713 """Returns true if the rule should skip the message editor.
714
714
715 For example, 'fold' wants to show an editor, but 'rollup'
715 For example, 'fold' wants to show an editor, but 'rollup'
716 doesn't want to.
716 doesn't want to.
717 """
717 """
718 return False
718 return False
719
719
720 def mergedescs(self):
720 def mergedescs(self):
721 """Returns true if the rule should merge messages of multiple changes.
721 """Returns true if the rule should merge messages of multiple changes.
722
722
723 This exists mainly so that 'rollup' rules can be a subclass of
723 This exists mainly so that 'rollup' rules can be a subclass of
724 'fold'.
724 'fold'.
725 """
725 """
726 return True
726 return True
727
727
728 def firstdate(self):
729 """Returns true if the rule should preserve the date of the first
730 change.
731
732 This exists mainly so that 'rollup' rules can be a subclass of
733 'fold'.
734 """
735 return False
736
728 def finishfold(self, ui, repo, ctx, oldctx, newnode, internalchanges):
737 def finishfold(self, ui, repo, ctx, oldctx, newnode, internalchanges):
729 parent = ctx.parents()[0].node()
738 parent = ctx.parents()[0].node()
730 repo.ui.pushbuffer()
739 repo.ui.pushbuffer()
731 hg.update(repo, parent)
740 hg.update(repo, parent)
732 repo.ui.popbuffer()
741 repo.ui.popbuffer()
733 ### prepare new commit data
742 ### prepare new commit data
734 commitopts = {}
743 commitopts = {}
735 commitopts['user'] = ctx.user()
744 commitopts['user'] = ctx.user()
736 # commit message
745 # commit message
737 if not self.mergedescs():
746 if not self.mergedescs():
738 newmessage = ctx.description()
747 newmessage = ctx.description()
739 else:
748 else:
740 newmessage = '\n***\n'.join(
749 newmessage = '\n***\n'.join(
741 [ctx.description()] +
750 [ctx.description()] +
742 [repo[r].description() for r in internalchanges] +
751 [repo[r].description() for r in internalchanges] +
743 [oldctx.description()]) + '\n'
752 [oldctx.description()]) + '\n'
744 commitopts['message'] = newmessage
753 commitopts['message'] = newmessage
745 # date
754 # date
746 commitopts['date'] = max(ctx.date(), oldctx.date())
755 if self.firstdate():
756 commitopts['date'] = ctx.date()
757 else:
758 commitopts['date'] = max(ctx.date(), oldctx.date())
747 extra = ctx.extra().copy()
759 extra = ctx.extra().copy()
748 # histedit_source
760 # histedit_source
749 # note: ctx is likely a temporary commit but that the best we can do
761 # note: ctx is likely a temporary commit but that the best we can do
750 # here. This is sufficient to solve issue3681 anyway.
762 # here. This is sufficient to solve issue3681 anyway.
751 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
763 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
752 commitopts['extra'] = extra
764 commitopts['extra'] = extra
753 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
765 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
754 try:
766 try:
755 phasemin = max(ctx.phase(), oldctx.phase())
767 phasemin = max(ctx.phase(), oldctx.phase())
756 repo.ui.setconfig('phases', 'new-commit', phasemin, 'histedit')
768 repo.ui.setconfig('phases', 'new-commit', phasemin, 'histedit')
757 n = collapse(repo, ctx, repo[newnode], commitopts,
769 n = collapse(repo, ctx, repo[newnode], commitopts,
758 skipprompt=self.skipprompt())
770 skipprompt=self.skipprompt())
759 finally:
771 finally:
760 repo.ui.restoreconfig(phasebackup)
772 repo.ui.restoreconfig(phasebackup)
761 if n is None:
773 if n is None:
762 return ctx, []
774 return ctx, []
763 repo.ui.pushbuffer()
775 repo.ui.pushbuffer()
764 hg.update(repo, n)
776 hg.update(repo, n)
765 repo.ui.popbuffer()
777 repo.ui.popbuffer()
766 replacements = [(oldctx.node(), (newnode,)),
778 replacements = [(oldctx.node(), (newnode,)),
767 (ctx.node(), (n,)),
779 (ctx.node(), (n,)),
768 (newnode, (n,)),
780 (newnode, (n,)),
769 ]
781 ]
770 for ich in internalchanges:
782 for ich in internalchanges:
771 replacements.append((ich, (n,)))
783 replacements.append((ich, (n,)))
772 return repo[n], replacements
784 return repo[n], replacements
773
785
774 class base(histeditaction):
786 class base(histeditaction):
775
787
776 def run(self):
788 def run(self):
777 if self.repo['.'].node() != self.node:
789 if self.repo['.'].node() != self.node:
778 mergemod.update(self.repo, self.node, False, True)
790 mergemod.update(self.repo, self.node, False, True)
779 # branchmerge, force)
791 # branchmerge, force)
780 return self.continueclean()
792 return self.continueclean()
781
793
782 def continuedirty(self):
794 def continuedirty(self):
783 abortdirty()
795 abortdirty()
784
796
785 def continueclean(self):
797 def continueclean(self):
786 basectx = self.repo['.']
798 basectx = self.repo['.']
787 return basectx, []
799 return basectx, []
788
800
789 def _verifynodeconstraints(self, prev, expected, seen):
801 def _verifynodeconstraints(self, prev, expected, seen):
790 # base can only be use with a node not in the edited set
802 # base can only be use with a node not in the edited set
791 if self.node in expected:
803 if self.node in expected:
792 msg = _('%s "%s" changeset was an edited list candidate')
804 msg = _('%s "%s" changeset was an edited list candidate')
793 raise error.ParseError(
805 raise error.ParseError(
794 msg % (self.verb, node.short(self.node)),
806 msg % (self.verb, node.short(self.node)),
795 hint=_('base must only use unlisted changesets'))
807 hint=_('base must only use unlisted changesets'))
796
808
797 @action(['_multifold'],
809 @action(['_multifold'],
798 _(
810 _(
799 """fold subclass used for when multiple folds happen in a row
811 """fold subclass used for when multiple folds happen in a row
800
812
801 We only want to fire the editor for the folded message once when
813 We only want to fire the editor for the folded message once when
802 (say) four changes are folded down into a single change. This is
814 (say) four changes are folded down into a single change. This is
803 similar to rollup, but we should preserve both messages so that
815 similar to rollup, but we should preserve both messages so that
804 when the last fold operation runs we can show the user all the
816 when the last fold operation runs we can show the user all the
805 commit messages in their editor.
817 commit messages in their editor.
806 """),
818 """),
807 internal=True)
819 internal=True)
808 class _multifold(fold):
820 class _multifold(fold):
809 def skipprompt(self):
821 def skipprompt(self):
810 return True
822 return True
811
823
812 @action(["roll", "r"],
824 @action(["roll", "r"],
813 _("like fold, but discard this commit's description"))
825 _("like fold, but discard this commit's description and date"))
814 class rollup(fold):
826 class rollup(fold):
815 def mergedescs(self):
827 def mergedescs(self):
816 return False
828 return False
817
829
818 def skipprompt(self):
830 def skipprompt(self):
819 return True
831 return True
820
832
833 def firstdate(self):
834 return True
835
821 @action(["drop", "d"],
836 @action(["drop", "d"],
822 _('remove commit from history'))
837 _('remove commit from history'))
823 class drop(histeditaction):
838 class drop(histeditaction):
824 def run(self):
839 def run(self):
825 parentctx = self.repo[self.state.parentctxnode]
840 parentctx = self.repo[self.state.parentctxnode]
826 return parentctx, [(self.node, tuple())]
841 return parentctx, [(self.node, tuple())]
827
842
828 @action(["mess", "m"],
843 @action(["mess", "m"],
829 _('edit commit message without changing commit content'),
844 _('edit commit message without changing commit content'),
830 priority=True)
845 priority=True)
831 class message(histeditaction):
846 class message(histeditaction):
832 def commiteditor(self):
847 def commiteditor(self):
833 return cmdutil.getcommiteditor(edit=True, editform='histedit.mess')
848 return cmdutil.getcommiteditor(edit=True, editform='histedit.mess')
834
849
835 def findoutgoing(ui, repo, remote=None, force=False, opts=None):
850 def findoutgoing(ui, repo, remote=None, force=False, opts=None):
836 """utility function to find the first outgoing changeset
851 """utility function to find the first outgoing changeset
837
852
838 Used by initialization code"""
853 Used by initialization code"""
839 if opts is None:
854 if opts is None:
840 opts = {}
855 opts = {}
841 dest = ui.expandpath(remote or 'default-push', remote or 'default')
856 dest = ui.expandpath(remote or 'default-push', remote or 'default')
842 dest, revs = hg.parseurl(dest, None)[:2]
857 dest, revs = hg.parseurl(dest, None)[:2]
843 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
858 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
844
859
845 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
860 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
846 other = hg.peer(repo, opts, dest)
861 other = hg.peer(repo, opts, dest)
847
862
848 if revs:
863 if revs:
849 revs = [repo.lookup(rev) for rev in revs]
864 revs = [repo.lookup(rev) for rev in revs]
850
865
851 outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
866 outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
852 if not outgoing.missing:
867 if not outgoing.missing:
853 raise error.Abort(_('no outgoing ancestors'))
868 raise error.Abort(_('no outgoing ancestors'))
854 roots = list(repo.revs("roots(%ln)", outgoing.missing))
869 roots = list(repo.revs("roots(%ln)", outgoing.missing))
855 if 1 < len(roots):
870 if 1 < len(roots):
856 msg = _('there are ambiguous outgoing revisions')
871 msg = _('there are ambiguous outgoing revisions')
857 hint = _("see 'hg help histedit' for more detail")
872 hint = _("see 'hg help histedit' for more detail")
858 raise error.Abort(msg, hint=hint)
873 raise error.Abort(msg, hint=hint)
859 return repo.lookup(roots[0])
874 return repo.lookup(roots[0])
860
875
861
876
862 @command('histedit',
877 @command('histedit',
863 [('', 'commands', '',
878 [('', 'commands', '',
864 _('read history edits from the specified file'), _('FILE')),
879 _('read history edits from the specified file'), _('FILE')),
865 ('c', 'continue', False, _('continue an edit already in progress')),
880 ('c', 'continue', False, _('continue an edit already in progress')),
866 ('', 'edit-plan', False, _('edit remaining actions list')),
881 ('', 'edit-plan', False, _('edit remaining actions list')),
867 ('k', 'keep', False,
882 ('k', 'keep', False,
868 _("don't strip old nodes after edit is complete")),
883 _("don't strip old nodes after edit is complete")),
869 ('', 'abort', False, _('abort an edit in progress')),
884 ('', 'abort', False, _('abort an edit in progress')),
870 ('o', 'outgoing', False, _('changesets not found in destination')),
885 ('o', 'outgoing', False, _('changesets not found in destination')),
871 ('f', 'force', False,
886 ('f', 'force', False,
872 _('force outgoing even for unrelated repositories')),
887 _('force outgoing even for unrelated repositories')),
873 ('r', 'rev', [], _('first revision to be edited'), _('REV'))],
888 ('r', 'rev', [], _('first revision to be edited'), _('REV'))],
874 _("[OPTIONS] ([ANCESTOR] | --outgoing [URL])"))
889 _("[OPTIONS] ([ANCESTOR] | --outgoing [URL])"))
875 def histedit(ui, repo, *freeargs, **opts):
890 def histedit(ui, repo, *freeargs, **opts):
876 """interactively edit changeset history
891 """interactively edit changeset history
877
892
878 This command lets you edit a linear series of changesets (up to
893 This command lets you edit a linear series of changesets (up to
879 and including the working directory, which should be clean).
894 and including the working directory, which should be clean).
880 You can:
895 You can:
881
896
882 - `pick` to [re]order a changeset
897 - `pick` to [re]order a changeset
883
898
884 - `drop` to omit changeset
899 - `drop` to omit changeset
885
900
886 - `mess` to reword the changeset commit message
901 - `mess` to reword the changeset commit message
887
902
888 - `fold` to combine it with the preceding changeset (using the later date)
903 - `fold` to combine it with the preceding changeset (using the later date)
889
904
890 - `roll` like fold, but discarding this commit's description
905 - `roll` like fold, but discarding this commit's description and date
891
906
892 - `edit` to edit this changeset (preserving date)
907 - `edit` to edit this changeset (preserving date)
893
908
894 There are a number of ways to select the root changeset:
909 There are a number of ways to select the root changeset:
895
910
896 - Specify ANCESTOR directly
911 - Specify ANCESTOR directly
897
912
898 - Use --outgoing -- it will be the first linear changeset not
913 - Use --outgoing -- it will be the first linear changeset not
899 included in destination. (See :hg:`help config.paths.default-push`)
914 included in destination. (See :hg:`help config.paths.default-push`)
900
915
901 - Otherwise, the value from the "histedit.defaultrev" config option
916 - Otherwise, the value from the "histedit.defaultrev" config option
902 is used as a revset to select the base revision when ANCESTOR is not
917 is used as a revset to select the base revision when ANCESTOR is not
903 specified. The first revision returned by the revset is used. By
918 specified. The first revision returned by the revset is used. By
904 default, this selects the editable history that is unique to the
919 default, this selects the editable history that is unique to the
905 ancestry of the working directory.
920 ancestry of the working directory.
906
921
907 .. container:: verbose
922 .. container:: verbose
908
923
909 If you use --outgoing, this command will abort if there are ambiguous
924 If you use --outgoing, this command will abort if there are ambiguous
910 outgoing revisions. For example, if there are multiple branches
925 outgoing revisions. For example, if there are multiple branches
911 containing outgoing revisions.
926 containing outgoing revisions.
912
927
913 Use "min(outgoing() and ::.)" or similar revset specification
928 Use "min(outgoing() and ::.)" or similar revset specification
914 instead of --outgoing to specify edit target revision exactly in
929 instead of --outgoing to specify edit target revision exactly in
915 such ambiguous situation. See :hg:`help revsets` for detail about
930 such ambiguous situation. See :hg:`help revsets` for detail about
916 selecting revisions.
931 selecting revisions.
917
932
918 .. container:: verbose
933 .. container:: verbose
919
934
920 Examples:
935 Examples:
921
936
922 - A number of changes have been made.
937 - A number of changes have been made.
923 Revision 3 is no longer needed.
938 Revision 3 is no longer needed.
924
939
925 Start history editing from revision 3::
940 Start history editing from revision 3::
926
941
927 hg histedit -r 3
942 hg histedit -r 3
928
943
929 An editor opens, containing the list of revisions,
944 An editor opens, containing the list of revisions,
930 with specific actions specified::
945 with specific actions specified::
931
946
932 pick 5339bf82f0ca 3 Zworgle the foobar
947 pick 5339bf82f0ca 3 Zworgle the foobar
933 pick 8ef592ce7cc4 4 Bedazzle the zerlog
948 pick 8ef592ce7cc4 4 Bedazzle the zerlog
934 pick 0a9639fcda9d 5 Morgify the cromulancy
949 pick 0a9639fcda9d 5 Morgify the cromulancy
935
950
936 Additional information about the possible actions
951 Additional information about the possible actions
937 to take appears below the list of revisions.
952 to take appears below the list of revisions.
938
953
939 To remove revision 3 from the history,
954 To remove revision 3 from the history,
940 its action (at the beginning of the relevant line)
955 its action (at the beginning of the relevant line)
941 is changed to 'drop'::
956 is changed to 'drop'::
942
957
943 drop 5339bf82f0ca 3 Zworgle the foobar
958 drop 5339bf82f0ca 3 Zworgle the foobar
944 pick 8ef592ce7cc4 4 Bedazzle the zerlog
959 pick 8ef592ce7cc4 4 Bedazzle the zerlog
945 pick 0a9639fcda9d 5 Morgify the cromulancy
960 pick 0a9639fcda9d 5 Morgify the cromulancy
946
961
947 - A number of changes have been made.
962 - A number of changes have been made.
948 Revision 2 and 4 need to be swapped.
963 Revision 2 and 4 need to be swapped.
949
964
950 Start history editing from revision 2::
965 Start history editing from revision 2::
951
966
952 hg histedit -r 2
967 hg histedit -r 2
953
968
954 An editor opens, containing the list of revisions,
969 An editor opens, containing the list of revisions,
955 with specific actions specified::
970 with specific actions specified::
956
971
957 pick 252a1af424ad 2 Blorb a morgwazzle
972 pick 252a1af424ad 2 Blorb a morgwazzle
958 pick 5339bf82f0ca 3 Zworgle the foobar
973 pick 5339bf82f0ca 3 Zworgle the foobar
959 pick 8ef592ce7cc4 4 Bedazzle the zerlog
974 pick 8ef592ce7cc4 4 Bedazzle the zerlog
960
975
961 To swap revision 2 and 4, its lines are swapped
976 To swap revision 2 and 4, its lines are swapped
962 in the editor::
977 in the editor::
963
978
964 pick 8ef592ce7cc4 4 Bedazzle the zerlog
979 pick 8ef592ce7cc4 4 Bedazzle the zerlog
965 pick 5339bf82f0ca 3 Zworgle the foobar
980 pick 5339bf82f0ca 3 Zworgle the foobar
966 pick 252a1af424ad 2 Blorb a morgwazzle
981 pick 252a1af424ad 2 Blorb a morgwazzle
967
982
968 Returns 0 on success, 1 if user intervention is required (not only
983 Returns 0 on success, 1 if user intervention is required (not only
969 for intentional "edit" command, but also for resolving unexpected
984 for intentional "edit" command, but also for resolving unexpected
970 conflicts).
985 conflicts).
971 """
986 """
972 state = histeditstate(repo)
987 state = histeditstate(repo)
973 try:
988 try:
974 state.wlock = repo.wlock()
989 state.wlock = repo.wlock()
975 state.lock = repo.lock()
990 state.lock = repo.lock()
976 _histedit(ui, repo, state, *freeargs, **opts)
991 _histedit(ui, repo, state, *freeargs, **opts)
977 finally:
992 finally:
978 release(state.lock, state.wlock)
993 release(state.lock, state.wlock)
979
994
980 goalcontinue = 'continue'
995 goalcontinue = 'continue'
981 goalabort = 'abort'
996 goalabort = 'abort'
982 goaleditplan = 'edit-plan'
997 goaleditplan = 'edit-plan'
983 goalnew = 'new'
998 goalnew = 'new'
984
999
985 def _getgoal(opts):
1000 def _getgoal(opts):
986 if opts.get('continue'):
1001 if opts.get('continue'):
987 return goalcontinue
1002 return goalcontinue
988 if opts.get('abort'):
1003 if opts.get('abort'):
989 return goalabort
1004 return goalabort
990 if opts.get('edit_plan'):
1005 if opts.get('edit_plan'):
991 return goaleditplan
1006 return goaleditplan
992 return goalnew
1007 return goalnew
993
1008
994 def _readfile(ui, path):
1009 def _readfile(ui, path):
995 if path == '-':
1010 if path == '-':
996 with ui.timeblockedsection('histedit'):
1011 with ui.timeblockedsection('histedit'):
997 return ui.fin.read()
1012 return ui.fin.read()
998 else:
1013 else:
999 with open(path, 'rb') as f:
1014 with open(path, 'rb') as f:
1000 return f.read()
1015 return f.read()
1001
1016
1002 def _validateargs(ui, repo, state, freeargs, opts, goal, rules, revs):
1017 def _validateargs(ui, repo, state, freeargs, opts, goal, rules, revs):
1003 # TODO only abort if we try to histedit mq patches, not just
1018 # TODO only abort if we try to histedit mq patches, not just
1004 # blanket if mq patches are applied somewhere
1019 # blanket if mq patches are applied somewhere
1005 mq = getattr(repo, 'mq', None)
1020 mq = getattr(repo, 'mq', None)
1006 if mq and mq.applied:
1021 if mq and mq.applied:
1007 raise error.Abort(_('source has mq patches applied'))
1022 raise error.Abort(_('source has mq patches applied'))
1008
1023
1009 # basic argument incompatibility processing
1024 # basic argument incompatibility processing
1010 outg = opts.get('outgoing')
1025 outg = opts.get('outgoing')
1011 editplan = opts.get('edit_plan')
1026 editplan = opts.get('edit_plan')
1012 abort = opts.get('abort')
1027 abort = opts.get('abort')
1013 force = opts.get('force')
1028 force = opts.get('force')
1014 if force and not outg:
1029 if force and not outg:
1015 raise error.Abort(_('--force only allowed with --outgoing'))
1030 raise error.Abort(_('--force only allowed with --outgoing'))
1016 if goal == 'continue':
1031 if goal == 'continue':
1017 if any((outg, abort, revs, freeargs, rules, editplan)):
1032 if any((outg, abort, revs, freeargs, rules, editplan)):
1018 raise error.Abort(_('no arguments allowed with --continue'))
1033 raise error.Abort(_('no arguments allowed with --continue'))
1019 elif goal == 'abort':
1034 elif goal == 'abort':
1020 if any((outg, revs, freeargs, rules, editplan)):
1035 if any((outg, revs, freeargs, rules, editplan)):
1021 raise error.Abort(_('no arguments allowed with --abort'))
1036 raise error.Abort(_('no arguments allowed with --abort'))
1022 elif goal == 'edit-plan':
1037 elif goal == 'edit-plan':
1023 if any((outg, revs, freeargs)):
1038 if any((outg, revs, freeargs)):
1024 raise error.Abort(_('only --commands argument allowed with '
1039 raise error.Abort(_('only --commands argument allowed with '
1025 '--edit-plan'))
1040 '--edit-plan'))
1026 else:
1041 else:
1027 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
1042 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
1028 raise error.Abort(_('history edit already in progress, try '
1043 raise error.Abort(_('history edit already in progress, try '
1029 '--continue or --abort'))
1044 '--continue or --abort'))
1030 if outg:
1045 if outg:
1031 if revs:
1046 if revs:
1032 raise error.Abort(_('no revisions allowed with --outgoing'))
1047 raise error.Abort(_('no revisions allowed with --outgoing'))
1033 if len(freeargs) > 1:
1048 if len(freeargs) > 1:
1034 raise error.Abort(
1049 raise error.Abort(
1035 _('only one repo argument allowed with --outgoing'))
1050 _('only one repo argument allowed with --outgoing'))
1036 else:
1051 else:
1037 revs.extend(freeargs)
1052 revs.extend(freeargs)
1038 if len(revs) == 0:
1053 if len(revs) == 0:
1039 defaultrev = destutil.desthistedit(ui, repo)
1054 defaultrev = destutil.desthistedit(ui, repo)
1040 if defaultrev is not None:
1055 if defaultrev is not None:
1041 revs.append(defaultrev)
1056 revs.append(defaultrev)
1042
1057
1043 if len(revs) != 1:
1058 if len(revs) != 1:
1044 raise error.Abort(
1059 raise error.Abort(
1045 _('histedit requires exactly one ancestor revision'))
1060 _('histedit requires exactly one ancestor revision'))
1046
1061
1047 def _histedit(ui, repo, state, *freeargs, **opts):
1062 def _histedit(ui, repo, state, *freeargs, **opts):
1048 goal = _getgoal(opts)
1063 goal = _getgoal(opts)
1049 revs = opts.get('rev', [])
1064 revs = opts.get('rev', [])
1050 rules = opts.get('commands', '')
1065 rules = opts.get('commands', '')
1051 state.keep = opts.get('keep', False)
1066 state.keep = opts.get('keep', False)
1052
1067
1053 _validateargs(ui, repo, state, freeargs, opts, goal, rules, revs)
1068 _validateargs(ui, repo, state, freeargs, opts, goal, rules, revs)
1054
1069
1055 # rebuild state
1070 # rebuild state
1056 if goal == goalcontinue:
1071 if goal == goalcontinue:
1057 state.read()
1072 state.read()
1058 state = bootstrapcontinue(ui, state, opts)
1073 state = bootstrapcontinue(ui, state, opts)
1059 elif goal == goaleditplan:
1074 elif goal == goaleditplan:
1060 _edithisteditplan(ui, repo, state, rules)
1075 _edithisteditplan(ui, repo, state, rules)
1061 return
1076 return
1062 elif goal == goalabort:
1077 elif goal == goalabort:
1063 _aborthistedit(ui, repo, state)
1078 _aborthistedit(ui, repo, state)
1064 return
1079 return
1065 else:
1080 else:
1066 # goal == goalnew
1081 # goal == goalnew
1067 _newhistedit(ui, repo, state, revs, freeargs, opts)
1082 _newhistedit(ui, repo, state, revs, freeargs, opts)
1068
1083
1069 _continuehistedit(ui, repo, state)
1084 _continuehistedit(ui, repo, state)
1070 _finishhistedit(ui, repo, state)
1085 _finishhistedit(ui, repo, state)
1071
1086
1072 def _continuehistedit(ui, repo, state):
1087 def _continuehistedit(ui, repo, state):
1073 """This function runs after either:
1088 """This function runs after either:
1074 - bootstrapcontinue (if the goal is 'continue')
1089 - bootstrapcontinue (if the goal is 'continue')
1075 - _newhistedit (if the goal is 'new')
1090 - _newhistedit (if the goal is 'new')
1076 """
1091 """
1077 # preprocess rules so that we can hide inner folds from the user
1092 # preprocess rules so that we can hide inner folds from the user
1078 # and only show one editor
1093 # and only show one editor
1079 actions = state.actions[:]
1094 actions = state.actions[:]
1080 for idx, (action, nextact) in enumerate(
1095 for idx, (action, nextact) in enumerate(
1081 zip(actions, actions[1:] + [None])):
1096 zip(actions, actions[1:] + [None])):
1082 if action.verb == 'fold' and nextact and nextact.verb == 'fold':
1097 if action.verb == 'fold' and nextact and nextact.verb == 'fold':
1083 state.actions[idx].__class__ = _multifold
1098 state.actions[idx].__class__ = _multifold
1084
1099
1085 total = len(state.actions)
1100 total = len(state.actions)
1086 pos = 0
1101 pos = 0
1087 while state.actions:
1102 while state.actions:
1088 state.write()
1103 state.write()
1089 actobj = state.actions.pop(0)
1104 actobj = state.actions.pop(0)
1090 pos += 1
1105 pos += 1
1091 ui.progress(_("editing"), pos, actobj.torule(),
1106 ui.progress(_("editing"), pos, actobj.torule(),
1092 _('changes'), total)
1107 _('changes'), total)
1093 ui.debug('histedit: processing %s %s\n' % (actobj.verb,\
1108 ui.debug('histedit: processing %s %s\n' % (actobj.verb,\
1094 actobj.torule()))
1109 actobj.torule()))
1095 parentctx, replacement_ = actobj.run()
1110 parentctx, replacement_ = actobj.run()
1096 state.parentctxnode = parentctx.node()
1111 state.parentctxnode = parentctx.node()
1097 state.replacements.extend(replacement_)
1112 state.replacements.extend(replacement_)
1098 state.write()
1113 state.write()
1099 ui.progress(_("editing"), None)
1114 ui.progress(_("editing"), None)
1100
1115
1101 def _finishhistedit(ui, repo, state):
1116 def _finishhistedit(ui, repo, state):
1102 """This action runs when histedit is finishing its session"""
1117 """This action runs when histedit is finishing its session"""
1103 repo.ui.pushbuffer()
1118 repo.ui.pushbuffer()
1104 hg.update(repo, state.parentctxnode, quietempty=True)
1119 hg.update(repo, state.parentctxnode, quietempty=True)
1105 repo.ui.popbuffer()
1120 repo.ui.popbuffer()
1106
1121
1107 mapping, tmpnodes, created, ntm = processreplacement(state)
1122 mapping, tmpnodes, created, ntm = processreplacement(state)
1108 if mapping:
1123 if mapping:
1109 for prec, succs in mapping.iteritems():
1124 for prec, succs in mapping.iteritems():
1110 if not succs:
1125 if not succs:
1111 ui.debug('histedit: %s is dropped\n' % node.short(prec))
1126 ui.debug('histedit: %s is dropped\n' % node.short(prec))
1112 else:
1127 else:
1113 ui.debug('histedit: %s is replaced by %s\n' % (
1128 ui.debug('histedit: %s is replaced by %s\n' % (
1114 node.short(prec), node.short(succs[0])))
1129 node.short(prec), node.short(succs[0])))
1115 if len(succs) > 1:
1130 if len(succs) > 1:
1116 m = 'histedit: %s'
1131 m = 'histedit: %s'
1117 for n in succs[1:]:
1132 for n in succs[1:]:
1118 ui.debug(m % node.short(n))
1133 ui.debug(m % node.short(n))
1119
1134
1120 supportsmarkers = obsolete.isenabled(repo, obsolete.createmarkersopt)
1135 supportsmarkers = obsolete.isenabled(repo, obsolete.createmarkersopt)
1121 if supportsmarkers:
1136 if supportsmarkers:
1122 # Only create markers if the temp nodes weren't already removed.
1137 # Only create markers if the temp nodes weren't already removed.
1123 obsolete.createmarkers(repo, ((repo[t],()) for t in sorted(tmpnodes)
1138 obsolete.createmarkers(repo, ((repo[t],()) for t in sorted(tmpnodes)
1124 if t in repo))
1139 if t in repo))
1125 else:
1140 else:
1126 cleanupnode(ui, repo, 'temp', tmpnodes)
1141 cleanupnode(ui, repo, 'temp', tmpnodes)
1127
1142
1128 if not state.keep:
1143 if not state.keep:
1129 if mapping:
1144 if mapping:
1130 movebookmarks(ui, repo, mapping, state.topmost, ntm)
1145 movebookmarks(ui, repo, mapping, state.topmost, ntm)
1131 # TODO update mq state
1146 # TODO update mq state
1132 if supportsmarkers:
1147 if supportsmarkers:
1133 markers = []
1148 markers = []
1134 # sort by revision number because it sound "right"
1149 # sort by revision number because it sound "right"
1135 for prec in sorted(mapping, key=repo.changelog.rev):
1150 for prec in sorted(mapping, key=repo.changelog.rev):
1136 succs = mapping[prec]
1151 succs = mapping[prec]
1137 markers.append((repo[prec],
1152 markers.append((repo[prec],
1138 tuple(repo[s] for s in succs)))
1153 tuple(repo[s] for s in succs)))
1139 if markers:
1154 if markers:
1140 obsolete.createmarkers(repo, markers)
1155 obsolete.createmarkers(repo, markers)
1141 else:
1156 else:
1142 cleanupnode(ui, repo, 'replaced', mapping)
1157 cleanupnode(ui, repo, 'replaced', mapping)
1143
1158
1144 state.clear()
1159 state.clear()
1145 if os.path.exists(repo.sjoin('undo')):
1160 if os.path.exists(repo.sjoin('undo')):
1146 os.unlink(repo.sjoin('undo'))
1161 os.unlink(repo.sjoin('undo'))
1147 if repo.vfs.exists('histedit-last-edit.txt'):
1162 if repo.vfs.exists('histedit-last-edit.txt'):
1148 repo.vfs.unlink('histedit-last-edit.txt')
1163 repo.vfs.unlink('histedit-last-edit.txt')
1149
1164
1150 def _aborthistedit(ui, repo, state):
1165 def _aborthistedit(ui, repo, state):
1151 try:
1166 try:
1152 state.read()
1167 state.read()
1153 __, leafs, tmpnodes, __ = processreplacement(state)
1168 __, leafs, tmpnodes, __ = processreplacement(state)
1154 ui.debug('restore wc to old parent %s\n'
1169 ui.debug('restore wc to old parent %s\n'
1155 % node.short(state.topmost))
1170 % node.short(state.topmost))
1156
1171
1157 # Recover our old commits if necessary
1172 # Recover our old commits if necessary
1158 if not state.topmost in repo and state.backupfile:
1173 if not state.topmost in repo and state.backupfile:
1159 backupfile = repo.join(state.backupfile)
1174 backupfile = repo.join(state.backupfile)
1160 f = hg.openpath(ui, backupfile)
1175 f = hg.openpath(ui, backupfile)
1161 gen = exchange.readbundle(ui, f, backupfile)
1176 gen = exchange.readbundle(ui, f, backupfile)
1162 with repo.transaction('histedit.abort') as tr:
1177 with repo.transaction('histedit.abort') as tr:
1163 if not isinstance(gen, bundle2.unbundle20):
1178 if not isinstance(gen, bundle2.unbundle20):
1164 gen.apply(repo, 'histedit', 'bundle:' + backupfile)
1179 gen.apply(repo, 'histedit', 'bundle:' + backupfile)
1165 if isinstance(gen, bundle2.unbundle20):
1180 if isinstance(gen, bundle2.unbundle20):
1166 bundle2.applybundle(repo, gen, tr,
1181 bundle2.applybundle(repo, gen, tr,
1167 source='histedit',
1182 source='histedit',
1168 url='bundle:' + backupfile)
1183 url='bundle:' + backupfile)
1169
1184
1170 os.remove(backupfile)
1185 os.remove(backupfile)
1171
1186
1172 # check whether we should update away
1187 # check whether we should update away
1173 if repo.unfiltered().revs('parents() and (%n or %ln::)',
1188 if repo.unfiltered().revs('parents() and (%n or %ln::)',
1174 state.parentctxnode, leafs | tmpnodes):
1189 state.parentctxnode, leafs | tmpnodes):
1175 hg.clean(repo, state.topmost, show_stats=True, quietempty=True)
1190 hg.clean(repo, state.topmost, show_stats=True, quietempty=True)
1176 cleanupnode(ui, repo, 'created', tmpnodes)
1191 cleanupnode(ui, repo, 'created', tmpnodes)
1177 cleanupnode(ui, repo, 'temp', leafs)
1192 cleanupnode(ui, repo, 'temp', leafs)
1178 except Exception:
1193 except Exception:
1179 if state.inprogress():
1194 if state.inprogress():
1180 ui.warn(_('warning: encountered an exception during histedit '
1195 ui.warn(_('warning: encountered an exception during histedit '
1181 '--abort; the repository may not have been completely '
1196 '--abort; the repository may not have been completely '
1182 'cleaned up\n'))
1197 'cleaned up\n'))
1183 raise
1198 raise
1184 finally:
1199 finally:
1185 state.clear()
1200 state.clear()
1186
1201
1187 def _edithisteditplan(ui, repo, state, rules):
1202 def _edithisteditplan(ui, repo, state, rules):
1188 state.read()
1203 state.read()
1189 if not rules:
1204 if not rules:
1190 comment = geteditcomment(ui,
1205 comment = geteditcomment(ui,
1191 node.short(state.parentctxnode),
1206 node.short(state.parentctxnode),
1192 node.short(state.topmost))
1207 node.short(state.topmost))
1193 rules = ruleeditor(repo, ui, state.actions, comment)
1208 rules = ruleeditor(repo, ui, state.actions, comment)
1194 else:
1209 else:
1195 rules = _readfile(ui, rules)
1210 rules = _readfile(ui, rules)
1196 actions = parserules(rules, state)
1211 actions = parserules(rules, state)
1197 ctxs = [repo[act.node] \
1212 ctxs = [repo[act.node] \
1198 for act in state.actions if act.node]
1213 for act in state.actions if act.node]
1199 warnverifyactions(ui, repo, actions, state, ctxs)
1214 warnverifyactions(ui, repo, actions, state, ctxs)
1200 state.actions = actions
1215 state.actions = actions
1201 state.write()
1216 state.write()
1202
1217
1203 def _newhistedit(ui, repo, state, revs, freeargs, opts):
1218 def _newhistedit(ui, repo, state, revs, freeargs, opts):
1204 outg = opts.get('outgoing')
1219 outg = opts.get('outgoing')
1205 rules = opts.get('commands', '')
1220 rules = opts.get('commands', '')
1206 force = opts.get('force')
1221 force = opts.get('force')
1207
1222
1208 cmdutil.checkunfinished(repo)
1223 cmdutil.checkunfinished(repo)
1209 cmdutil.bailifchanged(repo)
1224 cmdutil.bailifchanged(repo)
1210
1225
1211 topmost, empty = repo.dirstate.parents()
1226 topmost, empty = repo.dirstate.parents()
1212 if outg:
1227 if outg:
1213 if freeargs:
1228 if freeargs:
1214 remote = freeargs[0]
1229 remote = freeargs[0]
1215 else:
1230 else:
1216 remote = None
1231 remote = None
1217 root = findoutgoing(ui, repo, remote, force, opts)
1232 root = findoutgoing(ui, repo, remote, force, opts)
1218 else:
1233 else:
1219 rr = list(repo.set('roots(%ld)', scmutil.revrange(repo, revs)))
1234 rr = list(repo.set('roots(%ld)', scmutil.revrange(repo, revs)))
1220 if len(rr) != 1:
1235 if len(rr) != 1:
1221 raise error.Abort(_('The specified revisions must have '
1236 raise error.Abort(_('The specified revisions must have '
1222 'exactly one common root'))
1237 'exactly one common root'))
1223 root = rr[0].node()
1238 root = rr[0].node()
1224
1239
1225 revs = between(repo, root, topmost, state.keep)
1240 revs = between(repo, root, topmost, state.keep)
1226 if not revs:
1241 if not revs:
1227 raise error.Abort(_('%s is not an ancestor of working directory') %
1242 raise error.Abort(_('%s is not an ancestor of working directory') %
1228 node.short(root))
1243 node.short(root))
1229
1244
1230 ctxs = [repo[r] for r in revs]
1245 ctxs = [repo[r] for r in revs]
1231 if not rules:
1246 if not rules:
1232 comment = geteditcomment(ui, node.short(root), node.short(topmost))
1247 comment = geteditcomment(ui, node.short(root), node.short(topmost))
1233 actions = [pick(state, r) for r in revs]
1248 actions = [pick(state, r) for r in revs]
1234 rules = ruleeditor(repo, ui, actions, comment)
1249 rules = ruleeditor(repo, ui, actions, comment)
1235 else:
1250 else:
1236 rules = _readfile(ui, rules)
1251 rules = _readfile(ui, rules)
1237 actions = parserules(rules, state)
1252 actions = parserules(rules, state)
1238 warnverifyactions(ui, repo, actions, state, ctxs)
1253 warnverifyactions(ui, repo, actions, state, ctxs)
1239
1254
1240 parentctxnode = repo[root].parents()[0].node()
1255 parentctxnode = repo[root].parents()[0].node()
1241
1256
1242 state.parentctxnode = parentctxnode
1257 state.parentctxnode = parentctxnode
1243 state.actions = actions
1258 state.actions = actions
1244 state.topmost = topmost
1259 state.topmost = topmost
1245 state.replacements = []
1260 state.replacements = []
1246
1261
1247 # Create a backup so we can always abort completely.
1262 # Create a backup so we can always abort completely.
1248 backupfile = None
1263 backupfile = None
1249 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1264 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1250 backupfile = repair._bundle(repo, [parentctxnode], [topmost], root,
1265 backupfile = repair._bundle(repo, [parentctxnode], [topmost], root,
1251 'histedit')
1266 'histedit')
1252 state.backupfile = backupfile
1267 state.backupfile = backupfile
1253
1268
1254 def _getsummary(ctx):
1269 def _getsummary(ctx):
1255 # a common pattern is to extract the summary but default to the empty
1270 # a common pattern is to extract the summary but default to the empty
1256 # string
1271 # string
1257 summary = ctx.description() or ''
1272 summary = ctx.description() or ''
1258 if summary:
1273 if summary:
1259 summary = summary.splitlines()[0]
1274 summary = summary.splitlines()[0]
1260 return summary
1275 return summary
1261
1276
1262 def bootstrapcontinue(ui, state, opts):
1277 def bootstrapcontinue(ui, state, opts):
1263 repo = state.repo
1278 repo = state.repo
1264 if state.actions:
1279 if state.actions:
1265 actobj = state.actions.pop(0)
1280 actobj = state.actions.pop(0)
1266
1281
1267 if _isdirtywc(repo):
1282 if _isdirtywc(repo):
1268 actobj.continuedirty()
1283 actobj.continuedirty()
1269 if _isdirtywc(repo):
1284 if _isdirtywc(repo):
1270 abortdirty()
1285 abortdirty()
1271
1286
1272 parentctx, replacements = actobj.continueclean()
1287 parentctx, replacements = actobj.continueclean()
1273
1288
1274 state.parentctxnode = parentctx.node()
1289 state.parentctxnode = parentctx.node()
1275 state.replacements.extend(replacements)
1290 state.replacements.extend(replacements)
1276
1291
1277 return state
1292 return state
1278
1293
1279 def between(repo, old, new, keep):
1294 def between(repo, old, new, keep):
1280 """select and validate the set of revision to edit
1295 """select and validate the set of revision to edit
1281
1296
1282 When keep is false, the specified set can't have children."""
1297 When keep is false, the specified set can't have children."""
1283 ctxs = list(repo.set('%n::%n', old, new))
1298 ctxs = list(repo.set('%n::%n', old, new))
1284 if ctxs and not keep:
1299 if ctxs and not keep:
1285 if (not obsolete.isenabled(repo, obsolete.allowunstableopt) and
1300 if (not obsolete.isenabled(repo, obsolete.allowunstableopt) and
1286 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
1301 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
1287 raise error.Abort(_('can only histedit a changeset together '
1302 raise error.Abort(_('can only histedit a changeset together '
1288 'with all its descendants'))
1303 'with all its descendants'))
1289 if repo.revs('(%ld) and merge()', ctxs):
1304 if repo.revs('(%ld) and merge()', ctxs):
1290 raise error.Abort(_('cannot edit history that contains merges'))
1305 raise error.Abort(_('cannot edit history that contains merges'))
1291 root = ctxs[0] # list is already sorted by repo.set
1306 root = ctxs[0] # list is already sorted by repo.set
1292 if not root.mutable():
1307 if not root.mutable():
1293 raise error.Abort(_('cannot edit public changeset: %s') % root,
1308 raise error.Abort(_('cannot edit public changeset: %s') % root,
1294 hint=_("see 'hg help phases' for details"))
1309 hint=_("see 'hg help phases' for details"))
1295 return [c.node() for c in ctxs]
1310 return [c.node() for c in ctxs]
1296
1311
1297 def ruleeditor(repo, ui, actions, editcomment=""):
1312 def ruleeditor(repo, ui, actions, editcomment=""):
1298 """open an editor to edit rules
1313 """open an editor to edit rules
1299
1314
1300 rules are in the format [ [act, ctx], ...] like in state.rules
1315 rules are in the format [ [act, ctx], ...] like in state.rules
1301 """
1316 """
1302 if repo.ui.configbool("experimental", "histedit.autoverb"):
1317 if repo.ui.configbool("experimental", "histedit.autoverb"):
1303 newact = util.sortdict()
1318 newact = util.sortdict()
1304 for act in actions:
1319 for act in actions:
1305 ctx = repo[act.node]
1320 ctx = repo[act.node]
1306 summary = _getsummary(ctx)
1321 summary = _getsummary(ctx)
1307 fword = summary.split(' ', 1)[0].lower()
1322 fword = summary.split(' ', 1)[0].lower()
1308 added = False
1323 added = False
1309
1324
1310 # if it doesn't end with the special character '!' just skip this
1325 # if it doesn't end with the special character '!' just skip this
1311 if fword.endswith('!'):
1326 if fword.endswith('!'):
1312 fword = fword[:-1]
1327 fword = fword[:-1]
1313 if fword in primaryactions | secondaryactions | tertiaryactions:
1328 if fword in primaryactions | secondaryactions | tertiaryactions:
1314 act.verb = fword
1329 act.verb = fword
1315 # get the target summary
1330 # get the target summary
1316 tsum = summary[len(fword) + 1:].lstrip()
1331 tsum = summary[len(fword) + 1:].lstrip()
1317 # safe but slow: reverse iterate over the actions so we
1332 # safe but slow: reverse iterate over the actions so we
1318 # don't clash on two commits having the same summary
1333 # don't clash on two commits having the same summary
1319 for na, l in reversed(list(newact.iteritems())):
1334 for na, l in reversed(list(newact.iteritems())):
1320 actx = repo[na.node]
1335 actx = repo[na.node]
1321 asum = _getsummary(actx)
1336 asum = _getsummary(actx)
1322 if asum == tsum:
1337 if asum == tsum:
1323 added = True
1338 added = True
1324 l.append(act)
1339 l.append(act)
1325 break
1340 break
1326
1341
1327 if not added:
1342 if not added:
1328 newact[act] = []
1343 newact[act] = []
1329
1344
1330 # copy over and flatten the new list
1345 # copy over and flatten the new list
1331 actions = []
1346 actions = []
1332 for na, l in newact.iteritems():
1347 for na, l in newact.iteritems():
1333 actions.append(na)
1348 actions.append(na)
1334 actions += l
1349 actions += l
1335
1350
1336 rules = '\n'.join([act.torule() for act in actions])
1351 rules = '\n'.join([act.torule() for act in actions])
1337 rules += '\n\n'
1352 rules += '\n\n'
1338 rules += editcomment
1353 rules += editcomment
1339 rules = ui.edit(rules, ui.username(), {'prefix': 'histedit'},
1354 rules = ui.edit(rules, ui.username(), {'prefix': 'histedit'},
1340 repopath=repo.path)
1355 repopath=repo.path)
1341
1356
1342 # Save edit rules in .hg/histedit-last-edit.txt in case
1357 # Save edit rules in .hg/histedit-last-edit.txt in case
1343 # the user needs to ask for help after something
1358 # the user needs to ask for help after something
1344 # surprising happens.
1359 # surprising happens.
1345 f = open(repo.join('histedit-last-edit.txt'), 'w')
1360 f = open(repo.join('histedit-last-edit.txt'), 'w')
1346 f.write(rules)
1361 f.write(rules)
1347 f.close()
1362 f.close()
1348
1363
1349 return rules
1364 return rules
1350
1365
1351 def parserules(rules, state):
1366 def parserules(rules, state):
1352 """Read the histedit rules string and return list of action objects """
1367 """Read the histedit rules string and return list of action objects """
1353 rules = [l for l in (r.strip() for r in rules.splitlines())
1368 rules = [l for l in (r.strip() for r in rules.splitlines())
1354 if l and not l.startswith('#')]
1369 if l and not l.startswith('#')]
1355 actions = []
1370 actions = []
1356 for r in rules:
1371 for r in rules:
1357 if ' ' not in r:
1372 if ' ' not in r:
1358 raise error.ParseError(_('malformed line "%s"') % r)
1373 raise error.ParseError(_('malformed line "%s"') % r)
1359 verb, rest = r.split(' ', 1)
1374 verb, rest = r.split(' ', 1)
1360
1375
1361 if verb not in actiontable:
1376 if verb not in actiontable:
1362 raise error.ParseError(_('unknown action "%s"') % verb)
1377 raise error.ParseError(_('unknown action "%s"') % verb)
1363
1378
1364 action = actiontable[verb].fromrule(state, rest)
1379 action = actiontable[verb].fromrule(state, rest)
1365 actions.append(action)
1380 actions.append(action)
1366 return actions
1381 return actions
1367
1382
1368 def warnverifyactions(ui, repo, actions, state, ctxs):
1383 def warnverifyactions(ui, repo, actions, state, ctxs):
1369 try:
1384 try:
1370 verifyactions(actions, state, ctxs)
1385 verifyactions(actions, state, ctxs)
1371 except error.ParseError:
1386 except error.ParseError:
1372 if repo.vfs.exists('histedit-last-edit.txt'):
1387 if repo.vfs.exists('histedit-last-edit.txt'):
1373 ui.warn(_('warning: histedit rules saved '
1388 ui.warn(_('warning: histedit rules saved '
1374 'to: .hg/histedit-last-edit.txt\n'))
1389 'to: .hg/histedit-last-edit.txt\n'))
1375 raise
1390 raise
1376
1391
1377 def verifyactions(actions, state, ctxs):
1392 def verifyactions(actions, state, ctxs):
1378 """Verify that there exists exactly one action per given changeset and
1393 """Verify that there exists exactly one action per given changeset and
1379 other constraints.
1394 other constraints.
1380
1395
1381 Will abort if there are to many or too few rules, a malformed rule,
1396 Will abort if there are to many or too few rules, a malformed rule,
1382 or a rule on a changeset outside of the user-given range.
1397 or a rule on a changeset outside of the user-given range.
1383 """
1398 """
1384 expected = set(c.node() for c in ctxs)
1399 expected = set(c.node() for c in ctxs)
1385 seen = set()
1400 seen = set()
1386 prev = None
1401 prev = None
1387 for action in actions:
1402 for action in actions:
1388 action.verify(prev, expected, seen)
1403 action.verify(prev, expected, seen)
1389 prev = action
1404 prev = action
1390 if action.node is not None:
1405 if action.node is not None:
1391 seen.add(action.node)
1406 seen.add(action.node)
1392 missing = sorted(expected - seen) # sort to stabilize output
1407 missing = sorted(expected - seen) # sort to stabilize output
1393
1408
1394 if state.repo.ui.configbool('histedit', 'dropmissing'):
1409 if state.repo.ui.configbool('histedit', 'dropmissing'):
1395 if len(actions) == 0:
1410 if len(actions) == 0:
1396 raise error.ParseError(_('no rules provided'),
1411 raise error.ParseError(_('no rules provided'),
1397 hint=_('use strip extension to remove commits'))
1412 hint=_('use strip extension to remove commits'))
1398
1413
1399 drops = [drop(state, n) for n in missing]
1414 drops = [drop(state, n) for n in missing]
1400 # put the in the beginning so they execute immediately and
1415 # put the in the beginning so they execute immediately and
1401 # don't show in the edit-plan in the future
1416 # don't show in the edit-plan in the future
1402 actions[:0] = drops
1417 actions[:0] = drops
1403 elif missing:
1418 elif missing:
1404 raise error.ParseError(_('missing rules for changeset %s') %
1419 raise error.ParseError(_('missing rules for changeset %s') %
1405 node.short(missing[0]),
1420 node.short(missing[0]),
1406 hint=_('use "drop %s" to discard, see also: '
1421 hint=_('use "drop %s" to discard, see also: '
1407 "'hg help -e histedit.config'")
1422 "'hg help -e histedit.config'")
1408 % node.short(missing[0]))
1423 % node.short(missing[0]))
1409
1424
1410 def adjustreplacementsfrommarkers(repo, oldreplacements):
1425 def adjustreplacementsfrommarkers(repo, oldreplacements):
1411 """Adjust replacements from obsolescence markers
1426 """Adjust replacements from obsolescence markers
1412
1427
1413 Replacements structure is originally generated based on
1428 Replacements structure is originally generated based on
1414 histedit's state and does not account for changes that are
1429 histedit's state and does not account for changes that are
1415 not recorded there. This function fixes that by adding
1430 not recorded there. This function fixes that by adding
1416 data read from obsolescence markers"""
1431 data read from obsolescence markers"""
1417 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1432 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1418 return oldreplacements
1433 return oldreplacements
1419
1434
1420 unfi = repo.unfiltered()
1435 unfi = repo.unfiltered()
1421 nm = unfi.changelog.nodemap
1436 nm = unfi.changelog.nodemap
1422 obsstore = repo.obsstore
1437 obsstore = repo.obsstore
1423 newreplacements = list(oldreplacements)
1438 newreplacements = list(oldreplacements)
1424 oldsuccs = [r[1] for r in oldreplacements]
1439 oldsuccs = [r[1] for r in oldreplacements]
1425 # successors that have already been added to succstocheck once
1440 # successors that have already been added to succstocheck once
1426 seensuccs = set().union(*oldsuccs) # create a set from an iterable of tuples
1441 seensuccs = set().union(*oldsuccs) # create a set from an iterable of tuples
1427 succstocheck = list(seensuccs)
1442 succstocheck = list(seensuccs)
1428 while succstocheck:
1443 while succstocheck:
1429 n = succstocheck.pop()
1444 n = succstocheck.pop()
1430 missing = nm.get(n) is None
1445 missing = nm.get(n) is None
1431 markers = obsstore.successors.get(n, ())
1446 markers = obsstore.successors.get(n, ())
1432 if missing and not markers:
1447 if missing and not markers:
1433 # dead end, mark it as such
1448 # dead end, mark it as such
1434 newreplacements.append((n, ()))
1449 newreplacements.append((n, ()))
1435 for marker in markers:
1450 for marker in markers:
1436 nsuccs = marker[1]
1451 nsuccs = marker[1]
1437 newreplacements.append((n, nsuccs))
1452 newreplacements.append((n, nsuccs))
1438 for nsucc in nsuccs:
1453 for nsucc in nsuccs:
1439 if nsucc not in seensuccs:
1454 if nsucc not in seensuccs:
1440 seensuccs.add(nsucc)
1455 seensuccs.add(nsucc)
1441 succstocheck.append(nsucc)
1456 succstocheck.append(nsucc)
1442
1457
1443 return newreplacements
1458 return newreplacements
1444
1459
1445 def processreplacement(state):
1460 def processreplacement(state):
1446 """process the list of replacements to return
1461 """process the list of replacements to return
1447
1462
1448 1) the final mapping between original and created nodes
1463 1) the final mapping between original and created nodes
1449 2) the list of temporary node created by histedit
1464 2) the list of temporary node created by histedit
1450 3) the list of new commit created by histedit"""
1465 3) the list of new commit created by histedit"""
1451 replacements = adjustreplacementsfrommarkers(state.repo, state.replacements)
1466 replacements = adjustreplacementsfrommarkers(state.repo, state.replacements)
1452 allsuccs = set()
1467 allsuccs = set()
1453 replaced = set()
1468 replaced = set()
1454 fullmapping = {}
1469 fullmapping = {}
1455 # initialize basic set
1470 # initialize basic set
1456 # fullmapping records all operations recorded in replacement
1471 # fullmapping records all operations recorded in replacement
1457 for rep in replacements:
1472 for rep in replacements:
1458 allsuccs.update(rep[1])
1473 allsuccs.update(rep[1])
1459 replaced.add(rep[0])
1474 replaced.add(rep[0])
1460 fullmapping.setdefault(rep[0], set()).update(rep[1])
1475 fullmapping.setdefault(rep[0], set()).update(rep[1])
1461 new = allsuccs - replaced
1476 new = allsuccs - replaced
1462 tmpnodes = allsuccs & replaced
1477 tmpnodes = allsuccs & replaced
1463 # Reduce content fullmapping into direct relation between original nodes
1478 # Reduce content fullmapping into direct relation between original nodes
1464 # and final node created during history edition
1479 # and final node created during history edition
1465 # Dropped changeset are replaced by an empty list
1480 # Dropped changeset are replaced by an empty list
1466 toproceed = set(fullmapping)
1481 toproceed = set(fullmapping)
1467 final = {}
1482 final = {}
1468 while toproceed:
1483 while toproceed:
1469 for x in list(toproceed):
1484 for x in list(toproceed):
1470 succs = fullmapping[x]
1485 succs = fullmapping[x]
1471 for s in list(succs):
1486 for s in list(succs):
1472 if s in toproceed:
1487 if s in toproceed:
1473 # non final node with unknown closure
1488 # non final node with unknown closure
1474 # We can't process this now
1489 # We can't process this now
1475 break
1490 break
1476 elif s in final:
1491 elif s in final:
1477 # non final node, replace with closure
1492 # non final node, replace with closure
1478 succs.remove(s)
1493 succs.remove(s)
1479 succs.update(final[s])
1494 succs.update(final[s])
1480 else:
1495 else:
1481 final[x] = succs
1496 final[x] = succs
1482 toproceed.remove(x)
1497 toproceed.remove(x)
1483 # remove tmpnodes from final mapping
1498 # remove tmpnodes from final mapping
1484 for n in tmpnodes:
1499 for n in tmpnodes:
1485 del final[n]
1500 del final[n]
1486 # we expect all changes involved in final to exist in the repo
1501 # we expect all changes involved in final to exist in the repo
1487 # turn `final` into list (topologically sorted)
1502 # turn `final` into list (topologically sorted)
1488 nm = state.repo.changelog.nodemap
1503 nm = state.repo.changelog.nodemap
1489 for prec, succs in final.items():
1504 for prec, succs in final.items():
1490 final[prec] = sorted(succs, key=nm.get)
1505 final[prec] = sorted(succs, key=nm.get)
1491
1506
1492 # computed topmost element (necessary for bookmark)
1507 # computed topmost element (necessary for bookmark)
1493 if new:
1508 if new:
1494 newtopmost = sorted(new, key=state.repo.changelog.rev)[-1]
1509 newtopmost = sorted(new, key=state.repo.changelog.rev)[-1]
1495 elif not final:
1510 elif not final:
1496 # Nothing rewritten at all. we won't need `newtopmost`
1511 # Nothing rewritten at all. we won't need `newtopmost`
1497 # It is the same as `oldtopmost` and `processreplacement` know it
1512 # It is the same as `oldtopmost` and `processreplacement` know it
1498 newtopmost = None
1513 newtopmost = None
1499 else:
1514 else:
1500 # every body died. The newtopmost is the parent of the root.
1515 # every body died. The newtopmost is the parent of the root.
1501 r = state.repo.changelog.rev
1516 r = state.repo.changelog.rev
1502 newtopmost = state.repo[sorted(final, key=r)[0]].p1().node()
1517 newtopmost = state.repo[sorted(final, key=r)[0]].p1().node()
1503
1518
1504 return final, tmpnodes, new, newtopmost
1519 return final, tmpnodes, new, newtopmost
1505
1520
1506 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
1521 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
1507 """Move bookmark from old to newly created node"""
1522 """Move bookmark from old to newly created node"""
1508 if not mapping:
1523 if not mapping:
1509 # if nothing got rewritten there is not purpose for this function
1524 # if nothing got rewritten there is not purpose for this function
1510 return
1525 return
1511 moves = []
1526 moves = []
1512 for bk, old in sorted(repo._bookmarks.iteritems()):
1527 for bk, old in sorted(repo._bookmarks.iteritems()):
1513 if old == oldtopmost:
1528 if old == oldtopmost:
1514 # special case ensure bookmark stay on tip.
1529 # special case ensure bookmark stay on tip.
1515 #
1530 #
1516 # This is arguably a feature and we may only want that for the
1531 # This is arguably a feature and we may only want that for the
1517 # active bookmark. But the behavior is kept compatible with the old
1532 # active bookmark. But the behavior is kept compatible with the old
1518 # version for now.
1533 # version for now.
1519 moves.append((bk, newtopmost))
1534 moves.append((bk, newtopmost))
1520 continue
1535 continue
1521 base = old
1536 base = old
1522 new = mapping.get(base, None)
1537 new = mapping.get(base, None)
1523 if new is None:
1538 if new is None:
1524 continue
1539 continue
1525 while not new:
1540 while not new:
1526 # base is killed, trying with parent
1541 # base is killed, trying with parent
1527 base = repo[base].p1().node()
1542 base = repo[base].p1().node()
1528 new = mapping.get(base, (base,))
1543 new = mapping.get(base, (base,))
1529 # nothing to move
1544 # nothing to move
1530 moves.append((bk, new[-1]))
1545 moves.append((bk, new[-1]))
1531 if moves:
1546 if moves:
1532 lock = tr = None
1547 lock = tr = None
1533 try:
1548 try:
1534 lock = repo.lock()
1549 lock = repo.lock()
1535 tr = repo.transaction('histedit')
1550 tr = repo.transaction('histedit')
1536 marks = repo._bookmarks
1551 marks = repo._bookmarks
1537 for mark, new in moves:
1552 for mark, new in moves:
1538 old = marks[mark]
1553 old = marks[mark]
1539 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
1554 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
1540 % (mark, node.short(old), node.short(new)))
1555 % (mark, node.short(old), node.short(new)))
1541 marks[mark] = new
1556 marks[mark] = new
1542 marks.recordchange(tr)
1557 marks.recordchange(tr)
1543 tr.close()
1558 tr.close()
1544 finally:
1559 finally:
1545 release(tr, lock)
1560 release(tr, lock)
1546
1561
1547 def cleanupnode(ui, repo, name, nodes):
1562 def cleanupnode(ui, repo, name, nodes):
1548 """strip a group of nodes from the repository
1563 """strip a group of nodes from the repository
1549
1564
1550 The set of node to strip may contains unknown nodes."""
1565 The set of node to strip may contains unknown nodes."""
1551 ui.debug('should strip %s nodes %s\n' %
1566 ui.debug('should strip %s nodes %s\n' %
1552 (name, ', '.join([node.short(n) for n in nodes])))
1567 (name, ', '.join([node.short(n) for n in nodes])))
1553 with repo.lock():
1568 with repo.lock():
1554 # do not let filtering get in the way of the cleanse
1569 # do not let filtering get in the way of the cleanse
1555 # we should probably get rid of obsolescence marker created during the
1570 # we should probably get rid of obsolescence marker created during the
1556 # histedit, but we currently do not have such information.
1571 # histedit, but we currently do not have such information.
1557 repo = repo.unfiltered()
1572 repo = repo.unfiltered()
1558 # Find all nodes that need to be stripped
1573 # Find all nodes that need to be stripped
1559 # (we use %lr instead of %ln to silently ignore unknown items)
1574 # (we use %lr instead of %ln to silently ignore unknown items)
1560 nm = repo.changelog.nodemap
1575 nm = repo.changelog.nodemap
1561 nodes = sorted(n for n in nodes if n in nm)
1576 nodes = sorted(n for n in nodes if n in nm)
1562 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
1577 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
1563 for c in roots:
1578 for c in roots:
1564 # We should process node in reverse order to strip tip most first.
1579 # We should process node in reverse order to strip tip most first.
1565 # but this trigger a bug in changegroup hook.
1580 # but this trigger a bug in changegroup hook.
1566 # This would reduce bundle overhead
1581 # This would reduce bundle overhead
1567 repair.strip(ui, repo, c)
1582 repair.strip(ui, repo, c)
1568
1583
1569 def stripwrapper(orig, ui, repo, nodelist, *args, **kwargs):
1584 def stripwrapper(orig, ui, repo, nodelist, *args, **kwargs):
1570 if isinstance(nodelist, str):
1585 if isinstance(nodelist, str):
1571 nodelist = [nodelist]
1586 nodelist = [nodelist]
1572 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
1587 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
1573 state = histeditstate(repo)
1588 state = histeditstate(repo)
1574 state.read()
1589 state.read()
1575 histedit_nodes = set([action.node for action
1590 histedit_nodes = set([action.node for action
1576 in state.actions if action.node])
1591 in state.actions if action.node])
1577 common_nodes = histedit_nodes & set(nodelist)
1592 common_nodes = histedit_nodes & set(nodelist)
1578 if common_nodes:
1593 if common_nodes:
1579 raise error.Abort(_("histedit in progress, can't strip %s")
1594 raise error.Abort(_("histedit in progress, can't strip %s")
1580 % ', '.join(node.short(x) for x in common_nodes))
1595 % ', '.join(node.short(x) for x in common_nodes))
1581 return orig(ui, repo, nodelist, *args, **kwargs)
1596 return orig(ui, repo, nodelist, *args, **kwargs)
1582
1597
1583 extensions.wrapfunction(repair, 'strip', stripwrapper)
1598 extensions.wrapfunction(repair, 'strip', stripwrapper)
1584
1599
1585 def summaryhook(ui, repo):
1600 def summaryhook(ui, repo):
1586 if not os.path.exists(repo.join('histedit-state')):
1601 if not os.path.exists(repo.join('histedit-state')):
1587 return
1602 return
1588 state = histeditstate(repo)
1603 state = histeditstate(repo)
1589 state.read()
1604 state.read()
1590 if state.actions:
1605 if state.actions:
1591 # i18n: column positioning for "hg summary"
1606 # i18n: column positioning for "hg summary"
1592 ui.write(_('hist: %s (histedit --continue)\n') %
1607 ui.write(_('hist: %s (histedit --continue)\n') %
1593 (ui.label(_('%d remaining'), 'histedit.remaining') %
1608 (ui.label(_('%d remaining'), 'histedit.remaining') %
1594 len(state.actions)))
1609 len(state.actions)))
1595
1610
1596 def extsetup(ui):
1611 def extsetup(ui):
1597 cmdutil.summaryhooks.add('histedit', summaryhook)
1612 cmdutil.summaryhooks.add('histedit', summaryhook)
1598 cmdutil.unfinishedstates.append(
1613 cmdutil.unfinishedstates.append(
1599 ['histedit-state', False, True, _('histedit in progress'),
1614 ['histedit-state', False, True, _('histedit in progress'),
1600 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
1615 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
1601 cmdutil.afterresolvedstates.append(
1616 cmdutil.afterresolvedstates.append(
1602 ['histedit-state', _('hg histedit --continue')])
1617 ['histedit-state', _('hg histedit --continue')])
1603 if ui.configbool("experimental", "histeditng"):
1618 if ui.configbool("experimental", "histeditng"):
1604 globals()['base'] = action(['base', 'b'],
1619 globals()['base'] = action(['base', 'b'],
1605 _('checkout changeset and apply further changesets from there')
1620 _('checkout changeset and apply further changesets from there')
1606 )(base)
1621 )(base)
@@ -1,550 +1,550
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 # You can reorder changesets by reordering the lines
66 # You can reorder changesets by reordering the lines
67 #
67 #
68 # Commands:
68 # Commands:
69 #
69 #
70 # e, edit = use commit, but stop for amending
70 # e, edit = use commit, but stop for amending
71 # m, mess = edit commit message without changing commit content
71 # m, mess = edit commit message without changing commit content
72 # p, pick = use commit
72 # p, pick = use commit
73 # d, drop = remove commit from history
73 # d, drop = remove commit from history
74 # f, fold = use commit, but combine it with the one above
74 # f, fold = use commit, but combine it with the one above
75 # r, roll = like fold, but discard this commit's description
75 # r, roll = like fold, but discard this commit's description and date
76 #
76 #
77
77
78 Run on a revision not ancestors of the current working directory.
78 Run on a revision not ancestors of the current working directory.
79 --------------------------------------------------------------------
79 --------------------------------------------------------------------
80
80
81 $ hg up 2
81 $ hg up 2
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 $ hg histedit -r 4
83 $ hg histedit -r 4
84 abort: 08d98a8350f3 is not an ancestor of working directory
84 abort: 08d98a8350f3 is not an ancestor of working directory
85 [255]
85 [255]
86 $ hg up --quiet
86 $ hg up --quiet
87
87
88
88
89 Test that we pick the minimum of a revrange
89 Test that we pick the minimum of a revrange
90 ---------------------------------------
90 ---------------------------------------
91
91
92 $ HGEDITOR=cat hg histedit '2::' --commands - << EOF
92 $ HGEDITOR=cat hg histedit '2::' --commands - << EOF
93 > pick eb57da33312f 2 three
93 > pick eb57da33312f 2 three
94 > pick c8e68270e35a 3 four
94 > pick c8e68270e35a 3 four
95 > pick 08d98a8350f3 4 five
95 > pick 08d98a8350f3 4 five
96 > EOF
96 > EOF
97 $ hg up --quiet
97 $ hg up --quiet
98
98
99 $ HGEDITOR=cat hg histedit 'tip:2' --commands - << EOF
99 $ HGEDITOR=cat hg histedit 'tip:2' --commands - << EOF
100 > pick eb57da33312f 2 three
100 > pick eb57da33312f 2 three
101 > pick c8e68270e35a 3 four
101 > pick c8e68270e35a 3 four
102 > pick 08d98a8350f3 4 five
102 > pick 08d98a8350f3 4 five
103 > EOF
103 > EOF
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
113
114 Run on a revision not descendants of the initial parent
114 Run on a revision not descendants of the initial parent
115 --------------------------------------------------------------------
115 --------------------------------------------------------------------
116
116
117 Test the message shown for inconsistent histedit state, which may be
117 Test the message shown for inconsistent histedit state, which may be
118 created (and forgotten) by Mercurial earlier than 2.7. This emulates
118 created (and forgotten) by Mercurial earlier than 2.7. This emulates
119 Mercurial earlier than 2.7 by renaming ".hg/histedit-state"
119 Mercurial earlier than 2.7 by renaming ".hg/histedit-state"
120 temporarily.
120 temporarily.
121
121
122 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
122 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
123 @ 4 08d9 five
123 @ 4 08d9 five
124 |
124 |
125 o 3 c8e6 four
125 o 3 c8e6 four
126 |
126 |
127 o 2 eb57 three
127 o 2 eb57 three
128 |
128 |
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 Editing (08d98a8350f3), you may commit or record as needed now.
135 Editing (08d98a8350f3), you may commit or record as needed now.
136 (hg histedit --continue to resume)
136 (hg histedit --continue to resume)
137 [1]
137 [1]
138
138
139 $ hg graft --continue
139 $ hg graft --continue
140 abort: no graft in progress
140 abort: no graft in progress
141 (continue: hg histedit --continue)
141 (continue: hg histedit --continue)
142 [255]
142 [255]
143
143
144 $ mv .hg/histedit-state .hg/histedit-state.back
144 $ mv .hg/histedit-state .hg/histedit-state.back
145 $ hg update --quiet --clean 2
145 $ hg update --quiet --clean 2
146 $ echo alpha >> alpha
146 $ echo alpha >> alpha
147 $ mv .hg/histedit-state.back .hg/histedit-state
147 $ mv .hg/histedit-state.back .hg/histedit-state
148
148
149 $ hg histedit --continue
149 $ hg histedit --continue
150 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg (glob)
150 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg (glob)
151 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
151 $ hg log -G -T '{rev} {shortest(node)} {desc}\n' -r 2::
152 @ 4 f5ed five
152 @ 4 f5ed five
153 |
153 |
154 | o 3 c8e6 four
154 | o 3 c8e6 four
155 |/
155 |/
156 o 2 eb57 three
156 o 2 eb57 three
157 |
157 |
158 ~
158 ~
159
159
160 $ hg unbundle -q $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg
160 $ hg unbundle -q $TESTTMP/foo/.hg/strip-backup/08d98a8350f3-02594089-backup.hg
161 $ hg strip -q -r f5ed --config extensions.strip=
161 $ hg strip -q -r f5ed --config extensions.strip=
162 $ hg up -q 08d98a8350f3
162 $ hg up -q 08d98a8350f3
163
163
164 Test that missing revisions are detected
164 Test that missing revisions are detected
165 ---------------------------------------
165 ---------------------------------------
166
166
167 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
167 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
168 > pick eb57da33312f 2 three
168 > pick eb57da33312f 2 three
169 > pick 08d98a8350f3 4 five
169 > pick 08d98a8350f3 4 five
170 > EOF
170 > EOF
171 hg: parse error: missing rules for changeset c8e68270e35a
171 hg: parse error: missing rules for changeset c8e68270e35a
172 (use "drop c8e68270e35a" to discard, see also: 'hg help -e histedit.config')
172 (use "drop c8e68270e35a" to discard, see also: 'hg help -e histedit.config')
173 [255]
173 [255]
174
174
175 Test that extra revisions are detected
175 Test that extra revisions are detected
176 ---------------------------------------
176 ---------------------------------------
177
177
178 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
178 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
179 > pick 6058cbb6cfd7 0 one
179 > pick 6058cbb6cfd7 0 one
180 > pick c8e68270e35a 3 four
180 > pick c8e68270e35a 3 four
181 > pick 08d98a8350f3 4 five
181 > pick 08d98a8350f3 4 five
182 > EOF
182 > EOF
183 hg: parse error: pick "6058cbb6cfd7" changeset was not a candidate
183 hg: parse error: pick "6058cbb6cfd7" changeset was not a candidate
184 (only use listed changesets)
184 (only use listed changesets)
185 [255]
185 [255]
186
186
187 Test malformed line
187 Test malformed line
188 ---------------------------------------
188 ---------------------------------------
189
189
190 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
190 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
191 > pickeb57da33312f2three
191 > pickeb57da33312f2three
192 > pick c8e68270e35a 3 four
192 > pick c8e68270e35a 3 four
193 > pick 08d98a8350f3 4 five
193 > pick 08d98a8350f3 4 five
194 > EOF
194 > EOF
195 hg: parse error: malformed line "pickeb57da33312f2three"
195 hg: parse error: malformed line "pickeb57da33312f2three"
196 [255]
196 [255]
197
197
198 Test unknown changeset
198 Test unknown changeset
199 ---------------------------------------
199 ---------------------------------------
200
200
201 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
201 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
202 > pick 0123456789ab 2 three
202 > pick 0123456789ab 2 three
203 > pick c8e68270e35a 3 four
203 > pick c8e68270e35a 3 four
204 > pick 08d98a8350f3 4 five
204 > pick 08d98a8350f3 4 five
205 > EOF
205 > EOF
206 hg: parse error: unknown changeset 0123456789ab listed
206 hg: parse error: unknown changeset 0123456789ab listed
207 [255]
207 [255]
208
208
209 Test unknown command
209 Test unknown command
210 ---------------------------------------
210 ---------------------------------------
211
211
212 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
212 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
213 > coin eb57da33312f 2 three
213 > coin eb57da33312f 2 three
214 > pick c8e68270e35a 3 four
214 > pick c8e68270e35a 3 four
215 > pick 08d98a8350f3 4 five
215 > pick 08d98a8350f3 4 five
216 > EOF
216 > EOF
217 hg: parse error: unknown action "coin"
217 hg: parse error: unknown action "coin"
218 [255]
218 [255]
219
219
220 Test duplicated changeset
220 Test duplicated changeset
221 ---------------------------------------
221 ---------------------------------------
222
222
223 So one is missing and one appear twice.
223 So one is missing and one appear twice.
224
224
225 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
225 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
226 > pick eb57da33312f 2 three
226 > pick eb57da33312f 2 three
227 > pick eb57da33312f 2 three
227 > pick eb57da33312f 2 three
228 > pick 08d98a8350f3 4 five
228 > pick 08d98a8350f3 4 five
229 > EOF
229 > EOF
230 hg: parse error: duplicated command for changeset eb57da33312f
230 hg: parse error: duplicated command for changeset eb57da33312f
231 [255]
231 [255]
232
232
233 Test bogus rev
233 Test bogus rev
234 ---------------------------------------
234 ---------------------------------------
235
235
236 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
236 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
237 > pick eb57da33312f 2 three
237 > pick eb57da33312f 2 three
238 > pick 0
238 > pick 0
239 > pick 08d98a8350f3 4 five
239 > pick 08d98a8350f3 4 five
240 > EOF
240 > EOF
241 hg: parse error: invalid changeset 0
241 hg: parse error: invalid changeset 0
242 [255]
242 [255]
243
243
244 Test short version of command
244 Test short version of command
245 ---------------------------------------
245 ---------------------------------------
246
246
247 Note: we use varying amounts of white space between command name and changeset
247 Note: we use varying amounts of white space between command name and changeset
248 short hash. This tests issue3893.
248 short hash. This tests issue3893.
249
249
250 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
250 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
251 > pick eb57da33312f 2 three
251 > pick eb57da33312f 2 three
252 > p c8e68270e35a 3 four
252 > p c8e68270e35a 3 four
253 > f 08d98a8350f3 4 five
253 > f 08d98a8350f3 4 five
254 > EOF
254 > EOF
255 four
255 four
256 ***
256 ***
257 five
257 five
258
258
259
259
260
260
261 HG: Enter commit message. Lines beginning with 'HG:' are removed.
261 HG: Enter commit message. Lines beginning with 'HG:' are removed.
262 HG: Leave message empty to abort commit.
262 HG: Leave message empty to abort commit.
263 HG: --
263 HG: --
264 HG: user: test
264 HG: user: test
265 HG: branch 'default'
265 HG: branch 'default'
266 HG: changed alpha
266 HG: changed alpha
267 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
267 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
268 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
268 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
269
269
270 $ hg update -q 2
270 $ hg update -q 2
271 $ echo x > x
271 $ echo x > x
272 $ hg add x
272 $ hg add x
273 $ hg commit -m'x' x
273 $ hg commit -m'x' x
274 created new head
274 created new head
275 $ hg histedit -r 'heads(all())'
275 $ hg histedit -r 'heads(all())'
276 abort: The specified revisions must have exactly one common root
276 abort: The specified revisions must have exactly one common root
277 [255]
277 [255]
278
278
279 Test that trimming description using multi-byte characters
279 Test that trimming description using multi-byte characters
280 --------------------------------------------------------------------
280 --------------------------------------------------------------------
281
281
282 $ python <<EOF
282 $ python <<EOF
283 > fp = open('logfile', 'w')
283 > fp = open('logfile', 'w')
284 > fp.write('12345678901234567890123456789012345678901234567890' +
284 > fp.write('12345678901234567890123456789012345678901234567890' +
285 > '12345') # there are 5 more columns for 80 columns
285 > '12345') # there are 5 more columns for 80 columns
286 >
286 >
287 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
287 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
288 > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
288 > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
289 >
289 >
290 > fp.close()
290 > fp.close()
291 > EOF
291 > EOF
292 $ echo xx >> x
292 $ echo xx >> x
293 $ hg --encoding utf-8 commit --logfile logfile
293 $ hg --encoding utf-8 commit --logfile logfile
294
294
295 $ HGEDITOR=cat hg --encoding utf-8 histedit tip
295 $ HGEDITOR=cat hg --encoding utf-8 histedit tip
296 pick 3d3ea1f3a10b 5 1234567890123456789012345678901234567890123456789012345\xe3\x81\x82... (esc)
296 pick 3d3ea1f3a10b 5 1234567890123456789012345678901234567890123456789012345\xe3\x81\x82... (esc)
297
297
298 # Edit history between 3d3ea1f3a10b and 3d3ea1f3a10b
298 # Edit history between 3d3ea1f3a10b and 3d3ea1f3a10b
299 #
299 #
300 # Commits are listed from least to most recent
300 # Commits are listed from least to most recent
301 #
301 #
302 # You can reorder changesets by reordering the lines
302 # You can reorder changesets by reordering the lines
303 #
303 #
304 # Commands:
304 # Commands:
305 #
305 #
306 # e, edit = use commit, but stop for amending
306 # e, edit = use commit, but stop for amending
307 # m, mess = edit commit message without changing commit content
307 # m, mess = edit commit message without changing commit content
308 # p, pick = use commit
308 # p, pick = use commit
309 # d, drop = remove commit from history
309 # d, drop = remove commit from history
310 # f, fold = use commit, but combine it with the one above
310 # f, fold = use commit, but combine it with the one above
311 # r, roll = like fold, but discard this commit's description
311 # r, roll = like fold, but discard this commit's description and date
312 #
312 #
313
313
314 Test --continue with --keep
314 Test --continue with --keep
315
315
316 $ hg strip -q -r . --config extensions.strip=
316 $ hg strip -q -r . --config extensions.strip=
317 $ hg histedit '.^' -q --keep --commands - << EOF
317 $ hg histedit '.^' -q --keep --commands - << EOF
318 > edit eb57da33312f 2 three
318 > edit eb57da33312f 2 three
319 > pick f3cfcca30c44 4 x
319 > pick f3cfcca30c44 4 x
320 > EOF
320 > EOF
321 Editing (eb57da33312f), you may commit or record as needed now.
321 Editing (eb57da33312f), you may commit or record as needed now.
322 (hg histedit --continue to resume)
322 (hg histedit --continue to resume)
323 [1]
323 [1]
324 $ echo edit >> alpha
324 $ echo edit >> alpha
325 $ hg histedit -q --continue
325 $ hg histedit -q --continue
326 $ hg log -G -T '{rev}:{node|short} {desc}'
326 $ hg log -G -T '{rev}:{node|short} {desc}'
327 @ 6:8fda0c726bf2 x
327 @ 6:8fda0c726bf2 x
328 |
328 |
329 o 5:63379946892c three
329 o 5:63379946892c three
330 |
330 |
331 | o 4:f3cfcca30c44 x
331 | o 4:f3cfcca30c44 x
332 | |
332 | |
333 | | o 3:2a30f3cfee78 four
333 | | o 3:2a30f3cfee78 four
334 | |/ ***
334 | |/ ***
335 | | five
335 | | five
336 | o 2:eb57da33312f three
336 | o 2:eb57da33312f three
337 |/
337 |/
338 o 1:579e40513370 two
338 o 1:579e40513370 two
339 |
339 |
340 o 0:6058cbb6cfd7 one
340 o 0:6058cbb6cfd7 one
341
341
342
342
343 Test that abort fails gracefully on exception
343 Test that abort fails gracefully on exception
344 ----------------------------------------------
344 ----------------------------------------------
345 $ hg histedit . -q --commands - << EOF
345 $ hg histedit . -q --commands - << EOF
346 > edit 8fda0c726bf2 6 x
346 > edit 8fda0c726bf2 6 x
347 > EOF
347 > EOF
348 Editing (8fda0c726bf2), you may commit or record as needed now.
348 Editing (8fda0c726bf2), you may commit or record as needed now.
349 (hg histedit --continue to resume)
349 (hg histedit --continue to resume)
350 [1]
350 [1]
351 Corrupt histedit state file
351 Corrupt histedit state file
352 $ sed 's/8fda0c726bf2/123456789012/' .hg/histedit-state > ../corrupt-histedit
352 $ sed 's/8fda0c726bf2/123456789012/' .hg/histedit-state > ../corrupt-histedit
353 $ mv ../corrupt-histedit .hg/histedit-state
353 $ mv ../corrupt-histedit .hg/histedit-state
354 $ hg histedit --abort
354 $ hg histedit --abort
355 warning: encountered an exception during histedit --abort; the repository may not have been completely cleaned up
355 warning: encountered an exception during histedit --abort; the repository may not have been completely cleaned up
356 abort: .*(No such file or directory:|The system cannot find the file specified).* (re)
356 abort: .*(No such file or directory:|The system cannot find the file specified).* (re)
357 [255]
357 [255]
358 Histedit state has been exited
358 Histedit state has been exited
359 $ hg summary -q
359 $ hg summary -q
360 parent: 5:63379946892c
360 parent: 5:63379946892c
361 commit: 1 added, 1 unknown (new branch head)
361 commit: 1 added, 1 unknown (new branch head)
362 update: 4 new changesets (update)
362 update: 4 new changesets (update)
363
363
364 $ cd ..
364 $ cd ..
365
365
366 Set up default base revision tests
366 Set up default base revision tests
367
367
368 $ hg init defaultbase
368 $ hg init defaultbase
369 $ cd defaultbase
369 $ cd defaultbase
370 $ touch foo
370 $ touch foo
371 $ hg -q commit -A -m root
371 $ hg -q commit -A -m root
372 $ echo 1 > foo
372 $ echo 1 > foo
373 $ hg commit -m 'public 1'
373 $ hg commit -m 'public 1'
374 $ hg phase --force --public -r .
374 $ hg phase --force --public -r .
375 $ echo 2 > foo
375 $ echo 2 > foo
376 $ hg commit -m 'draft after public'
376 $ hg commit -m 'draft after public'
377 $ hg -q up -r 1
377 $ hg -q up -r 1
378 $ echo 3 > foo
378 $ echo 3 > foo
379 $ hg commit -m 'head 1 public'
379 $ hg commit -m 'head 1 public'
380 created new head
380 created new head
381 $ hg phase --force --public -r .
381 $ hg phase --force --public -r .
382 $ echo 4 > foo
382 $ echo 4 > foo
383 $ hg commit -m 'head 1 draft 1'
383 $ hg commit -m 'head 1 draft 1'
384 $ echo 5 > foo
384 $ echo 5 > foo
385 $ hg commit -m 'head 1 draft 2'
385 $ hg commit -m 'head 1 draft 2'
386 $ hg -q up -r 2
386 $ hg -q up -r 2
387 $ echo 6 > foo
387 $ echo 6 > foo
388 $ hg commit -m 'head 2 commit 1'
388 $ hg commit -m 'head 2 commit 1'
389 $ echo 7 > foo
389 $ echo 7 > foo
390 $ hg commit -m 'head 2 commit 2'
390 $ hg commit -m 'head 2 commit 2'
391 $ hg -q up -r 2
391 $ hg -q up -r 2
392 $ echo 8 > foo
392 $ echo 8 > foo
393 $ hg commit -m 'head 3'
393 $ hg commit -m 'head 3'
394 created new head
394 created new head
395 $ hg -q up -r 2
395 $ hg -q up -r 2
396 $ echo 9 > foo
396 $ echo 9 > foo
397 $ hg commit -m 'head 4'
397 $ hg commit -m 'head 4'
398 created new head
398 created new head
399 $ hg merge --tool :local -r 8
399 $ hg merge --tool :local -r 8
400 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
400 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
401 (branch merge, don't forget to commit)
401 (branch merge, don't forget to commit)
402 $ hg commit -m 'merge head 3 into head 4'
402 $ hg commit -m 'merge head 3 into head 4'
403 $ echo 11 > foo
403 $ echo 11 > foo
404 $ hg commit -m 'commit 1 after merge'
404 $ hg commit -m 'commit 1 after merge'
405 $ echo 12 > foo
405 $ echo 12 > foo
406 $ hg commit -m 'commit 2 after merge'
406 $ hg commit -m 'commit 2 after merge'
407
407
408 $ hg log -G -T '{rev}:{node|short} {phase} {desc}\n'
408 $ hg log -G -T '{rev}:{node|short} {phase} {desc}\n'
409 @ 12:8cde254db839 draft commit 2 after merge
409 @ 12:8cde254db839 draft commit 2 after merge
410 |
410 |
411 o 11:6f2f0241f119 draft commit 1 after merge
411 o 11:6f2f0241f119 draft commit 1 after merge
412 |
412 |
413 o 10:90506cc76b00 draft merge head 3 into head 4
413 o 10:90506cc76b00 draft merge head 3 into head 4
414 |\
414 |\
415 | o 9:f8607a373a97 draft head 4
415 | o 9:f8607a373a97 draft head 4
416 | |
416 | |
417 o | 8:0da92be05148 draft head 3
417 o | 8:0da92be05148 draft head 3
418 |/
418 |/
419 | o 7:4c35cdf97d5e draft head 2 commit 2
419 | o 7:4c35cdf97d5e draft head 2 commit 2
420 | |
420 | |
421 | o 6:931820154288 draft head 2 commit 1
421 | o 6:931820154288 draft head 2 commit 1
422 |/
422 |/
423 | o 5:8cdc02b9bc63 draft head 1 draft 2
423 | o 5:8cdc02b9bc63 draft head 1 draft 2
424 | |
424 | |
425 | o 4:463b8c0d2973 draft head 1 draft 1
425 | o 4:463b8c0d2973 draft head 1 draft 1
426 | |
426 | |
427 | o 3:23a0c4eefcbf public head 1 public
427 | o 3:23a0c4eefcbf public head 1 public
428 | |
428 | |
429 o | 2:4117331c3abb draft draft after public
429 o | 2:4117331c3abb draft draft after public
430 |/
430 |/
431 o 1:4426d359ea59 public public 1
431 o 1:4426d359ea59 public public 1
432 |
432 |
433 o 0:54136a8ddf32 public root
433 o 0:54136a8ddf32 public root
434
434
435
435
436 Default base revision should stop at public changesets
436 Default base revision should stop at public changesets
437
437
438 $ hg -q up 8cdc02b9bc63
438 $ hg -q up 8cdc02b9bc63
439 $ hg histedit --commands - <<EOF
439 $ hg histedit --commands - <<EOF
440 > pick 463b8c0d2973
440 > pick 463b8c0d2973
441 > pick 8cdc02b9bc63
441 > pick 8cdc02b9bc63
442 > EOF
442 > EOF
443
443
444 Default base revision should stop at branchpoint
444 Default base revision should stop at branchpoint
445
445
446 $ hg -q up 4c35cdf97d5e
446 $ hg -q up 4c35cdf97d5e
447 $ hg histedit --commands - <<EOF
447 $ hg histedit --commands - <<EOF
448 > pick 931820154288
448 > pick 931820154288
449 > pick 4c35cdf97d5e
449 > pick 4c35cdf97d5e
450 > EOF
450 > EOF
451
451
452 Default base revision should stop at merge commit
452 Default base revision should stop at merge commit
453
453
454 $ hg -q up 8cde254db839
454 $ hg -q up 8cde254db839
455 $ hg histedit --commands - <<EOF
455 $ hg histedit --commands - <<EOF
456 > pick 6f2f0241f119
456 > pick 6f2f0241f119
457 > pick 8cde254db839
457 > pick 8cde254db839
458 > EOF
458 > EOF
459
459
460 commit --amend should abort if histedit is in progress
460 commit --amend should abort if histedit is in progress
461 (issue4800) and markers are not being created.
461 (issue4800) and markers are not being created.
462 Eventually, histedit could perhaps look at `source` extra,
462 Eventually, histedit could perhaps look at `source` extra,
463 in which case this test should be revisited.
463 in which case this test should be revisited.
464
464
465 $ hg -q up 8cde254db839
465 $ hg -q up 8cde254db839
466 $ hg histedit 6f2f0241f119 --commands - <<EOF
466 $ hg histedit 6f2f0241f119 --commands - <<EOF
467 > pick 8cde254db839
467 > pick 8cde254db839
468 > edit 6f2f0241f119
468 > edit 6f2f0241f119
469 > EOF
469 > EOF
470 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
471 merging foo
471 merging foo
472 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
472 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
473 Fix up the change (pick 8cde254db839)
473 Fix up the change (pick 8cde254db839)
474 (hg histedit --continue to resume)
474 (hg histedit --continue to resume)
475 [1]
475 [1]
476 $ hg resolve -m --all
476 $ hg resolve -m --all
477 (no more unresolved files)
477 (no more unresolved files)
478 continue: hg histedit --continue
478 continue: hg histedit --continue
479 $ hg histedit --cont
479 $ hg histedit --cont
480 merging foo
480 merging foo
481 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
481 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
482 Editing (6f2f0241f119), you may commit or record as needed now.
482 Editing (6f2f0241f119), you may commit or record as needed now.
483 (hg histedit --continue to resume)
483 (hg histedit --continue to resume)
484 [1]
484 [1]
485 $ hg resolve -m --all
485 $ hg resolve -m --all
486 (no more unresolved files)
486 (no more unresolved files)
487 continue: hg histedit --continue
487 continue: hg histedit --continue
488 $ hg commit --amend -m 'reject this fold'
488 $ hg commit --amend -m 'reject this fold'
489 abort: histedit in progress
489 abort: histedit in progress
490 (use 'hg histedit --continue' or 'hg histedit --abort')
490 (use 'hg histedit --continue' or 'hg histedit --abort')
491 [255]
491 [255]
492
492
493 With markers enabled, histedit does not get confused, and
493 With markers enabled, histedit does not get confused, and
494 amend should not be blocked by the ongoing histedit.
494 amend should not be blocked by the ongoing histedit.
495
495
496 $ cat >>$HGRCPATH <<EOF
496 $ cat >>$HGRCPATH <<EOF
497 > [experimental]
497 > [experimental]
498 > evolution=createmarkers,allowunstable
498 > evolution=createmarkers,allowunstable
499 > EOF
499 > EOF
500 $ hg commit --amend -m 'allow this fold'
500 $ hg commit --amend -m 'allow this fold'
501 $ hg histedit --continue
501 $ hg histedit --continue
502
502
503 $ cd ..
503 $ cd ..
504
504
505 Test autoverb feature
505 Test autoverb feature
506
506
507 $ hg init autoverb
507 $ hg init autoverb
508 $ cd autoverb
508 $ cd autoverb
509 $ echo alpha >> alpha
509 $ echo alpha >> alpha
510 $ hg ci -qAm one
510 $ hg ci -qAm one
511 $ echo alpha >> alpha
511 $ echo alpha >> alpha
512 $ hg ci -qm two
512 $ hg ci -qm two
513 $ echo beta >> beta
513 $ echo beta >> beta
514 $ hg ci -qAm "roll! one"
514 $ hg ci -qAm "roll! one"
515
515
516 $ hg log --style compact --graph
516 $ hg log --style compact --graph
517 @ 2[tip] 4f34d0f8b5fa 1970-01-01 00:00 +0000 test
517 @ 2[tip] 4f34d0f8b5fa 1970-01-01 00:00 +0000 test
518 | roll! one
518 | roll! one
519 |
519 |
520 o 1 579e40513370 1970-01-01 00:00 +0000 test
520 o 1 579e40513370 1970-01-01 00:00 +0000 test
521 | two
521 | two
522 |
522 |
523 o 0 6058cbb6cfd7 1970-01-01 00:00 +0000 test
523 o 0 6058cbb6cfd7 1970-01-01 00:00 +0000 test
524 one
524 one
525
525
526
526
527 Check that 'roll' is selected by default
527 Check that 'roll' is selected by default
528
528
529 $ HGEDITOR=cat hg histedit 0 --config experimental.histedit.autoverb=True
529 $ HGEDITOR=cat hg histedit 0 --config experimental.histedit.autoverb=True
530 pick 6058cbb6cfd7 0 one
530 pick 6058cbb6cfd7 0 one
531 roll 4f34d0f8b5fa 2 roll! one
531 roll 4f34d0f8b5fa 2 roll! one
532 pick 579e40513370 1 two
532 pick 579e40513370 1 two
533
533
534 # Edit history between 6058cbb6cfd7 and 4f34d0f8b5fa
534 # Edit history between 6058cbb6cfd7 and 4f34d0f8b5fa
535 #
535 #
536 # Commits are listed from least to most recent
536 # Commits are listed from least to most recent
537 #
537 #
538 # You can reorder changesets by reordering the lines
538 # You can reorder changesets by reordering the lines
539 #
539 #
540 # Commands:
540 # Commands:
541 #
541 #
542 # e, edit = use commit, but stop for amending
542 # e, edit = use commit, but stop for amending
543 # m, mess = edit commit message without changing commit content
543 # m, mess = edit commit message without changing commit content
544 # p, pick = use commit
544 # p, pick = use commit
545 # d, drop = remove commit from history
545 # d, drop = remove commit from history
546 # f, fold = use commit, but combine it with the one above
546 # f, fold = use commit, but combine it with the one above
547 # r, roll = like fold, but discard this commit's description
547 # r, roll = like fold, but discard this commit's description and date
548 #
548 #
549
549
550 $ cd ..
550 $ cd ..
@@ -1,186 +1,186
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 # You can reorder changesets by reordering the lines
72 # You can reorder changesets by reordering the lines
73 #
73 #
74 # Commands:
74 # Commands:
75 #
75 #
76 # e, edit = use commit, but stop for amending
76 # e, edit = use commit, but stop for amending
77 # m, mess = edit commit message without changing commit content
77 # m, mess = edit commit message without changing commit content
78 # p, pick = use commit
78 # p, pick = use commit
79 # d, drop = remove commit from history
79 # d, drop = remove commit from history
80 # f, fold = use commit, but combine it with the one above
80 # f, fold = use commit, but combine it with the one above
81 # r, roll = like fold, but discard this commit's description
81 # r, roll = like fold, but discard this commit's description and date
82 #
82 #
83 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
83 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
84 > pick 177f92b77385 2 c
84 > pick 177f92b77385 2 c
85 > drop d2ae7f538514 1 b
85 > drop d2ae7f538514 1 b
86 > pick 055a42cdd887 3 d
86 > pick 055a42cdd887 3 d
87 > fold e860deea161a 4 e
87 > fold e860deea161a 4 e
88 > pick 652413bf663e 5 f
88 > pick 652413bf663e 5 f
89 > EOF
89 > EOF
90 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-3c6c5d92-backup.hg (glob)
90 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-3c6c5d92-backup.hg (glob)
91 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
91 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
92 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
92 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
93 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
93 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
94 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
94 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
95 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
95 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
96 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
96 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
97 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-48787b8d-backup.hg (glob)
97 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-48787b8d-backup.hg (glob)
98 $ hg log --graph
98 $ hg log --graph
99 @ changeset: 3:cacdfd884a93
99 @ changeset: 3:cacdfd884a93
100 | bookmark: five
100 | bookmark: five
101 | tag: tip
101 | tag: tip
102 | user: test
102 | user: test
103 | date: Thu Jan 01 00:00:00 1970 +0000
103 | date: Thu Jan 01 00:00:00 1970 +0000
104 | summary: f
104 | summary: f
105 |
105 |
106 o changeset: 2:59d9f330561f
106 o changeset: 2:59d9f330561f
107 | bookmark: four
107 | bookmark: four
108 | bookmark: three
108 | bookmark: three
109 | user: test
109 | user: test
110 | date: Thu Jan 01 00:00:00 1970 +0000
110 | date: Thu Jan 01 00:00:00 1970 +0000
111 | summary: d
111 | summary: d
112 |
112 |
113 o changeset: 1:b346ab9a313d
113 o changeset: 1:b346ab9a313d
114 | bookmark: also-two
114 | bookmark: also-two
115 | bookmark: two
115 | bookmark: two
116 | user: test
116 | user: test
117 | date: Thu Jan 01 00:00:00 1970 +0000
117 | date: Thu Jan 01 00:00:00 1970 +0000
118 | summary: c
118 | summary: c
119 |
119 |
120 o changeset: 0:cb9a9f314b8b
120 o changeset: 0:cb9a9f314b8b
121 bookmark: will-move-backwards
121 bookmark: will-move-backwards
122 user: test
122 user: test
123 date: Thu Jan 01 00:00:00 1970 +0000
123 date: Thu Jan 01 00:00:00 1970 +0000
124 summary: a
124 summary: a
125
125
126 $ HGEDITOR=cat hg histedit 1
126 $ HGEDITOR=cat hg histedit 1
127 pick b346ab9a313d 1 c
127 pick b346ab9a313d 1 c
128 pick 59d9f330561f 2 d
128 pick 59d9f330561f 2 d
129 pick cacdfd884a93 3 f
129 pick cacdfd884a93 3 f
130
130
131 # Edit history between b346ab9a313d and cacdfd884a93
131 # Edit history between b346ab9a313d and cacdfd884a93
132 #
132 #
133 # Commits are listed from least to most recent
133 # Commits are listed from least to most recent
134 #
134 #
135 # You can reorder changesets by reordering the lines
135 # You can reorder changesets by reordering the lines
136 #
136 #
137 # Commands:
137 # Commands:
138 #
138 #
139 # e, edit = use commit, but stop for amending
139 # e, edit = use commit, but stop for amending
140 # m, mess = edit commit message without changing commit content
140 # m, mess = edit commit message without changing commit content
141 # p, pick = use commit
141 # p, pick = use commit
142 # d, drop = remove commit from history
142 # d, drop = remove commit from history
143 # f, fold = use commit, but combine it with the one above
143 # f, fold = use commit, but combine it with the one above
144 # r, roll = like fold, but discard this commit's description
144 # r, roll = like fold, but discard this commit's description and date
145 #
145 #
146 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
146 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
147 > pick b346ab9a313d 1 c
147 > pick b346ab9a313d 1 c
148 > pick cacdfd884a93 3 f
148 > pick cacdfd884a93 3 f
149 > pick 59d9f330561f 2 d
149 > pick 59d9f330561f 2 d
150 > EOF
150 > EOF
151 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
151 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
152 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
152 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
153 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
153 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
154 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-073008af-backup.hg (glob)
154 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-073008af-backup.hg (glob)
155
155
156 We expect 'five' to stay at tip, since the tipmost bookmark is most
156 We expect 'five' to stay at tip, since the tipmost bookmark is most
157 likely the useful signal.
157 likely the useful signal.
158
158
159 $ hg log --graph
159 $ hg log --graph
160 @ changeset: 3:c04e50810e4b
160 @ changeset: 3:c04e50810e4b
161 | bookmark: five
161 | bookmark: five
162 | bookmark: four
162 | bookmark: four
163 | bookmark: three
163 | bookmark: three
164 | tag: tip
164 | tag: tip
165 | user: test
165 | user: test
166 | date: Thu Jan 01 00:00:00 1970 +0000
166 | date: Thu Jan 01 00:00:00 1970 +0000
167 | summary: d
167 | summary: d
168 |
168 |
169 o changeset: 2:c13eb81022ca
169 o changeset: 2:c13eb81022ca
170 | user: test
170 | user: test
171 | date: Thu Jan 01 00:00:00 1970 +0000
171 | date: Thu Jan 01 00:00:00 1970 +0000
172 | summary: f
172 | summary: f
173 |
173 |
174 o changeset: 1:b346ab9a313d
174 o changeset: 1:b346ab9a313d
175 | bookmark: also-two
175 | bookmark: also-two
176 | bookmark: two
176 | bookmark: two
177 | user: test
177 | user: test
178 | date: Thu Jan 01 00:00:00 1970 +0000
178 | date: Thu Jan 01 00:00:00 1970 +0000
179 | summary: c
179 | summary: c
180 |
180 |
181 o changeset: 0:cb9a9f314b8b
181 o changeset: 0:cb9a9f314b8b
182 bookmark: will-move-backwards
182 bookmark: will-move-backwards
183 user: test
183 user: test
184 date: Thu Jan 01 00:00:00 1970 +0000
184 date: Thu Jan 01 00:00:00 1970 +0000
185 summary: a
185 summary: a
186
186
@@ -1,454 +1,454
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 # You can reorder changesets by reordering the lines
66 # You can reorder changesets by reordering the lines
67 #
67 #
68 # Commands:
68 # Commands:
69 #
69 #
70 # e, edit = use commit, but stop for amending
70 # e, edit = use commit, but stop for amending
71 # m, mess = edit commit message without changing commit content
71 # m, mess = edit commit message without changing commit content
72 # p, pick = use commit
72 # p, pick = use commit
73 # d, drop = remove commit from history
73 # d, drop = remove commit from history
74 # f, fold = use commit, but combine it with the one above
74 # f, fold = use commit, but combine it with the one above
75 # r, roll = like fold, but discard this commit's description
75 # r, roll = like fold, but discard this commit's description and date
76 #
76 #
77
77
78 edit the history
78 edit the history
79 (use a hacky editor to check histedit-last-edit.txt backup)
79 (use a hacky editor to check histedit-last-edit.txt backup)
80
80
81 $ EDITED="$TESTTMP/editedhistory"
81 $ EDITED="$TESTTMP/editedhistory"
82 $ cat > $EDITED <<EOF
82 $ cat > $EDITED <<EOF
83 > edit 177f92b77385 c
83 > edit 177f92b77385 c
84 > pick e860deea161a e
84 > pick e860deea161a e
85 > pick 652413bf663e f
85 > pick 652413bf663e f
86 > pick 055a42cdd887 d
86 > pick 055a42cdd887 d
87 > EOF
87 > EOF
88 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
88 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
89 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
89 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
90 Editing (177f92b77385), you may commit or record as needed now.
90 Editing (177f92b77385), you may commit or record as needed now.
91 (hg histedit --continue to resume)
91 (hg histedit --continue to resume)
92
92
93 rules should end up in .hg/histedit-last-edit.txt:
93 rules should end up in .hg/histedit-last-edit.txt:
94 $ cat .hg/histedit-last-edit.txt
94 $ cat .hg/histedit-last-edit.txt
95 edit 177f92b77385 c
95 edit 177f92b77385 c
96 pick e860deea161a e
96 pick e860deea161a e
97 pick 652413bf663e f
97 pick 652413bf663e f
98 pick 055a42cdd887 d
98 pick 055a42cdd887 d
99
99
100 $ hg histedit --abort
100 $ hg histedit --abort
101 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 $ cat > $EDITED <<EOF
102 $ cat > $EDITED <<EOF
103 > pick 177f92b77385 c
103 > pick 177f92b77385 c
104 > pick e860deea161a e
104 > pick e860deea161a e
105 > pick 652413bf663e f
105 > pick 652413bf663e f
106 > pick 055a42cdd887 d
106 > pick 055a42cdd887 d
107 > EOF
107 > EOF
108 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
108 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
109
109
110 log after edit
110 log after edit
111 $ hg log --graph
111 $ hg log --graph
112 @ changeset: 5:07114f51870f
112 @ changeset: 5:07114f51870f
113 | tag: tip
113 | tag: tip
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: d
116 | summary: d
117 |
117 |
118 o changeset: 4:8ade9693061e
118 o changeset: 4:8ade9693061e
119 | user: test
119 | user: test
120 | date: Thu Jan 01 00:00:00 1970 +0000
120 | date: Thu Jan 01 00:00:00 1970 +0000
121 | summary: f
121 | summary: f
122 |
122 |
123 o changeset: 3:d8249471110a
123 o changeset: 3:d8249471110a
124 | user: test
124 | user: test
125 | date: Thu Jan 01 00:00:00 1970 +0000
125 | date: Thu Jan 01 00:00:00 1970 +0000
126 | summary: e
126 | summary: e
127 |
127 |
128 o changeset: 2:177f92b77385
128 o changeset: 2:177f92b77385
129 | user: test
129 | user: test
130 | date: Thu Jan 01 00:00:00 1970 +0000
130 | date: Thu Jan 01 00:00:00 1970 +0000
131 | summary: c
131 | summary: c
132 |
132 |
133 o changeset: 1:d2ae7f538514
133 o changeset: 1:d2ae7f538514
134 | user: test
134 | user: test
135 | date: Thu Jan 01 00:00:00 1970 +0000
135 | date: Thu Jan 01 00:00:00 1970 +0000
136 | summary: b
136 | summary: b
137 |
137 |
138 o changeset: 0:cb9a9f314b8b
138 o changeset: 0:cb9a9f314b8b
139 user: test
139 user: test
140 date: Thu Jan 01 00:00:00 1970 +0000
140 date: Thu Jan 01 00:00:00 1970 +0000
141 summary: a
141 summary: a
142
142
143
143
144 put things back
144 put things back
145
145
146 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF | fixbundle
146 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF | fixbundle
147 > pick 177f92b77385 c
147 > pick 177f92b77385 c
148 > pick 07114f51870f d
148 > pick 07114f51870f d
149 > pick d8249471110a e
149 > pick d8249471110a e
150 > pick 8ade9693061e f
150 > pick 8ade9693061e f
151 > EOF
151 > EOF
152
152
153 $ hg log --graph
153 $ hg log --graph
154 @ changeset: 5:7eca9b5b1148
154 @ changeset: 5:7eca9b5b1148
155 | tag: tip
155 | tag: tip
156 | user: test
156 | user: test
157 | date: Thu Jan 01 00:00:00 1970 +0000
157 | date: Thu Jan 01 00:00:00 1970 +0000
158 | summary: f
158 | summary: f
159 |
159 |
160 o changeset: 4:915da888f2de
160 o changeset: 4:915da888f2de
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: e
163 | summary: e
164 |
164 |
165 o changeset: 3:10517e47bbbb
165 o changeset: 3:10517e47bbbb
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: d
168 | summary: d
169 |
169 |
170 o changeset: 2:177f92b77385
170 o changeset: 2:177f92b77385
171 | user: test
171 | user: test
172 | date: Thu Jan 01 00:00:00 1970 +0000
172 | date: Thu Jan 01 00:00:00 1970 +0000
173 | summary: c
173 | summary: c
174 |
174 |
175 o changeset: 1:d2ae7f538514
175 o changeset: 1:d2ae7f538514
176 | user: test
176 | user: test
177 | date: Thu Jan 01 00:00:00 1970 +0000
177 | date: Thu Jan 01 00:00:00 1970 +0000
178 | summary: b
178 | summary: b
179 |
179 |
180 o changeset: 0:cb9a9f314b8b
180 o changeset: 0:cb9a9f314b8b
181 user: test
181 user: test
182 date: Thu Jan 01 00:00:00 1970 +0000
182 date: Thu Jan 01 00:00:00 1970 +0000
183 summary: a
183 summary: a
184
184
185
185
186 slightly different this time
186 slightly different this time
187
187
188 $ hg histedit 177f92b77385 --commands - << EOF 2>&1 | fixbundle
188 $ hg histedit 177f92b77385 --commands - << EOF 2>&1 | fixbundle
189 > pick 10517e47bbbb d
189 > pick 10517e47bbbb d
190 > pick 7eca9b5b1148 f
190 > pick 7eca9b5b1148 f
191 > pick 915da888f2de e
191 > pick 915da888f2de e
192 > pick 177f92b77385 c
192 > pick 177f92b77385 c
193 > EOF
193 > EOF
194 $ hg log --graph
194 $ hg log --graph
195 @ changeset: 5:38b92f448761
195 @ changeset: 5:38b92f448761
196 | tag: tip
196 | tag: tip
197 | user: test
197 | user: test
198 | date: Thu Jan 01 00:00:00 1970 +0000
198 | date: Thu Jan 01 00:00:00 1970 +0000
199 | summary: c
199 | summary: c
200 |
200 |
201 o changeset: 4:de71b079d9ce
201 o changeset: 4:de71b079d9ce
202 | user: test
202 | user: test
203 | date: Thu Jan 01 00:00:00 1970 +0000
203 | date: Thu Jan 01 00:00:00 1970 +0000
204 | summary: e
204 | summary: e
205 |
205 |
206 o changeset: 3:be9ae3a309c6
206 o changeset: 3:be9ae3a309c6
207 | user: test
207 | user: test
208 | date: Thu Jan 01 00:00:00 1970 +0000
208 | date: Thu Jan 01 00:00:00 1970 +0000
209 | summary: f
209 | summary: f
210 |
210 |
211 o changeset: 2:799205341b6b
211 o changeset: 2:799205341b6b
212 | user: test
212 | user: test
213 | date: Thu Jan 01 00:00:00 1970 +0000
213 | date: Thu Jan 01 00:00:00 1970 +0000
214 | summary: d
214 | summary: d
215 |
215 |
216 o changeset: 1:d2ae7f538514
216 o changeset: 1:d2ae7f538514
217 | user: test
217 | user: test
218 | date: Thu Jan 01 00:00:00 1970 +0000
218 | date: Thu Jan 01 00:00:00 1970 +0000
219 | summary: b
219 | summary: b
220 |
220 |
221 o changeset: 0:cb9a9f314b8b
221 o changeset: 0:cb9a9f314b8b
222 user: test
222 user: test
223 date: Thu Jan 01 00:00:00 1970 +0000
223 date: Thu Jan 01 00:00:00 1970 +0000
224 summary: a
224 summary: a
225
225
226
226
227 keep prevents stripping dead revs
227 keep prevents stripping dead revs
228 $ hg histedit 799205341b6b --keep --commands - 2>&1 << EOF | fixbundle
228 $ hg histedit 799205341b6b --keep --commands - 2>&1 << EOF | fixbundle
229 > pick 799205341b6b d
229 > pick 799205341b6b d
230 > pick be9ae3a309c6 f
230 > pick be9ae3a309c6 f
231 > pick 38b92f448761 c
231 > pick 38b92f448761 c
232 > pick de71b079d9ce e
232 > pick de71b079d9ce e
233 > EOF
233 > EOF
234 $ hg log --graph
234 $ hg log --graph
235 @ changeset: 7:803ef1c6fcfd
235 @ changeset: 7:803ef1c6fcfd
236 | tag: tip
236 | tag: tip
237 | user: test
237 | user: test
238 | date: Thu Jan 01 00:00:00 1970 +0000
238 | date: Thu Jan 01 00:00:00 1970 +0000
239 | summary: e
239 | summary: e
240 |
240 |
241 o changeset: 6:ece0b8d93dda
241 o changeset: 6:ece0b8d93dda
242 | parent: 3:be9ae3a309c6
242 | parent: 3:be9ae3a309c6
243 | user: test
243 | user: test
244 | date: Thu Jan 01 00:00:00 1970 +0000
244 | date: Thu Jan 01 00:00:00 1970 +0000
245 | summary: c
245 | summary: c
246 |
246 |
247 | o changeset: 5:38b92f448761
247 | o changeset: 5:38b92f448761
248 | | user: test
248 | | user: test
249 | | date: Thu Jan 01 00:00:00 1970 +0000
249 | | date: Thu Jan 01 00:00:00 1970 +0000
250 | | summary: c
250 | | summary: c
251 | |
251 | |
252 | o changeset: 4:de71b079d9ce
252 | o changeset: 4:de71b079d9ce
253 |/ user: test
253 |/ user: test
254 | date: Thu Jan 01 00:00:00 1970 +0000
254 | date: Thu Jan 01 00:00:00 1970 +0000
255 | summary: e
255 | summary: e
256 |
256 |
257 o changeset: 3:be9ae3a309c6
257 o changeset: 3:be9ae3a309c6
258 | user: test
258 | user: test
259 | date: Thu Jan 01 00:00:00 1970 +0000
259 | date: Thu Jan 01 00:00:00 1970 +0000
260 | summary: f
260 | summary: f
261 |
261 |
262 o changeset: 2:799205341b6b
262 o changeset: 2:799205341b6b
263 | user: test
263 | user: test
264 | date: Thu Jan 01 00:00:00 1970 +0000
264 | date: Thu Jan 01 00:00:00 1970 +0000
265 | summary: d
265 | summary: d
266 |
266 |
267 o changeset: 1:d2ae7f538514
267 o changeset: 1:d2ae7f538514
268 | user: test
268 | user: test
269 | date: Thu Jan 01 00:00:00 1970 +0000
269 | date: Thu Jan 01 00:00:00 1970 +0000
270 | summary: b
270 | summary: b
271 |
271 |
272 o changeset: 0:cb9a9f314b8b
272 o changeset: 0:cb9a9f314b8b
273 user: test
273 user: test
274 date: Thu Jan 01 00:00:00 1970 +0000
274 date: Thu Jan 01 00:00:00 1970 +0000
275 summary: a
275 summary: a
276
276
277
277
278 try with --rev
278 try with --rev
279 $ hg histedit --commands - --rev -2 2>&1 <<EOF | fixbundle
279 $ hg histedit --commands - --rev -2 2>&1 <<EOF | fixbundle
280 > pick de71b079d9ce e
280 > pick de71b079d9ce e
281 > pick 38b92f448761 c
281 > pick 38b92f448761 c
282 > EOF
282 > EOF
283 hg: parse error: pick "de71b079d9ce" changeset was not a candidate
283 hg: parse error: pick "de71b079d9ce" changeset was not a candidate
284 (only use listed changesets)
284 (only use listed changesets)
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 # You can reorder changesets by reordering the lines
344 # You can reorder changesets by reordering the lines
345 #
345 #
346 # Commands:
346 # Commands:
347 #
347 #
348 # e, edit = use commit, but stop for amending
348 # e, edit = use commit, but stop for amending
349 # m, mess = edit commit message without changing commit content
349 # m, mess = edit commit message without changing commit content
350 # p, pick = use commit
350 # p, pick = use commit
351 # d, drop = remove commit from history
351 # d, drop = remove commit from history
352 # f, fold = use commit, but combine it with the one above
352 # f, fold = use commit, but combine it with the one above
353 # r, roll = like fold, but discard this commit's description
353 # r, roll = like fold, but discard this commit's description and date
354 #
354 #
355
355
356 should also work if a commit message is missing
356 should also work if a commit message is missing
357 $ BUNDLE="$TESTDIR/missing-comment.hg"
357 $ BUNDLE="$TESTDIR/missing-comment.hg"
358 $ hg init missing
358 $ hg init missing
359 $ cd missing
359 $ cd missing
360 $ hg unbundle $BUNDLE
360 $ hg unbundle $BUNDLE
361 adding changesets
361 adding changesets
362 adding manifests
362 adding manifests
363 adding file changes
363 adding file changes
364 added 3 changesets with 3 changes to 1 files
364 added 3 changesets with 3 changes to 1 files
365 (run 'hg update' to get a working copy)
365 (run 'hg update' to get a working copy)
366 $ hg co tip
366 $ hg co tip
367 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
367 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
368 $ hg log --graph
368 $ hg log --graph
369 @ changeset: 2:bd22688093b3
369 @ changeset: 2:bd22688093b3
370 | tag: tip
370 | tag: tip
371 | user: Robert Altman <robert.altman@telventDTN.com>
371 | user: Robert Altman <robert.altman@telventDTN.com>
372 | date: Mon Nov 28 16:40:04 2011 +0000
372 | date: Mon Nov 28 16:40:04 2011 +0000
373 | summary: Update file.
373 | summary: Update file.
374 |
374 |
375 o changeset: 1:3b3e956f9171
375 o changeset: 1:3b3e956f9171
376 | user: Robert Altman <robert.altman@telventDTN.com>
376 | user: Robert Altman <robert.altman@telventDTN.com>
377 | date: Mon Nov 28 16:37:57 2011 +0000
377 | date: Mon Nov 28 16:37:57 2011 +0000
378 |
378 |
379 o changeset: 0:141947992243
379 o changeset: 0:141947992243
380 user: Robert Altman <robert.altman@telventDTN.com>
380 user: Robert Altman <robert.altman@telventDTN.com>
381 date: Mon Nov 28 16:35:28 2011 +0000
381 date: Mon Nov 28 16:35:28 2011 +0000
382 summary: Checked in text file
382 summary: Checked in text file
383
383
384 $ hg histedit 0
384 $ hg histedit 0
385 $ cd ..
385 $ cd ..
386
386
387 $ cd ..
387 $ cd ..
388
388
389
389
390 Test to make sure folding renames doesn't cause bogus conflicts (issue4251):
390 Test to make sure folding renames doesn't cause bogus conflicts (issue4251):
391 $ hg init issue4251
391 $ hg init issue4251
392 $ cd issue4251
392 $ cd issue4251
393
393
394 $ mkdir initial-dir
394 $ mkdir initial-dir
395 $ echo foo > initial-dir/initial-file
395 $ echo foo > initial-dir/initial-file
396 $ hg add initial-dir/initial-file
396 $ hg add initial-dir/initial-file
397 $ hg commit -m "initial commit"
397 $ hg commit -m "initial commit"
398
398
399 Move the file to a new directory, and in the same commit, change its content:
399 Move the file to a new directory, and in the same commit, change its content:
400 $ mkdir another-dir
400 $ mkdir another-dir
401 $ hg mv initial-dir/initial-file another-dir/
401 $ hg mv initial-dir/initial-file another-dir/
402 $ echo changed > another-dir/initial-file
402 $ echo changed > another-dir/initial-file
403 $ hg commit -m "moved and changed"
403 $ hg commit -m "moved and changed"
404
404
405 Rename the file:
405 Rename the file:
406 $ hg mv another-dir/initial-file another-dir/renamed-file
406 $ hg mv another-dir/initial-file another-dir/renamed-file
407 $ hg commit -m "renamed"
407 $ hg commit -m "renamed"
408
408
409 Now, let's try to fold the second commit into the first:
409 Now, let's try to fold the second commit into the first:
410 $ cat > editor.sh <<EOF
410 $ cat > editor.sh <<EOF
411 > #!/bin/sh
411 > #!/bin/sh
412 > cat > \$1 <<ENDOF
412 > cat > \$1 <<ENDOF
413 > pick b0f4233702ca 0 initial commit
413 > pick b0f4233702ca 0 initial commit
414 > fold 5e8704a8f2d2 1 moved and changed
414 > fold 5e8704a8f2d2 1 moved and changed
415 > pick 40e7299e8fa7 2 renamed
415 > pick 40e7299e8fa7 2 renamed
416 > ENDOF
416 > ENDOF
417 > EOF
417 > EOF
418
418
419 $ HGEDITOR="sh ./editor.sh" hg histedit 0
419 $ HGEDITOR="sh ./editor.sh" hg histedit 0
420 saved backup bundle to $TESTTMP/issue4251/.hg/strip-backup/*-backup.hg (glob)
420 saved backup bundle to $TESTTMP/issue4251/.hg/strip-backup/*-backup.hg (glob)
421 saved backup bundle to $TESTTMP/issue4251/.hg/strip-backup/*-backup.hg (glob)
421 saved backup bundle to $TESTTMP/issue4251/.hg/strip-backup/*-backup.hg (glob)
422
422
423 $ hg --config diff.git=yes export 0
423 $ hg --config diff.git=yes export 0
424 # HG changeset patch
424 # HG changeset patch
425 # User test
425 # User test
426 # Date 0 0
426 # Date 0 0
427 # Thu Jan 01 00:00:00 1970 +0000
427 # Thu Jan 01 00:00:00 1970 +0000
428 # Node ID fffadc26f8f85623ce60b028a3f1ccc3730f8530
428 # Node ID fffadc26f8f85623ce60b028a3f1ccc3730f8530
429 # Parent 0000000000000000000000000000000000000000
429 # Parent 0000000000000000000000000000000000000000
430 pick b0f4233702ca 0 initial commit
430 pick b0f4233702ca 0 initial commit
431 fold 5e8704a8f2d2 1 moved and changed
431 fold 5e8704a8f2d2 1 moved and changed
432 pick 40e7299e8fa7 2 renamed
432 pick 40e7299e8fa7 2 renamed
433
433
434 diff --git a/another-dir/initial-file b/another-dir/initial-file
434 diff --git a/another-dir/initial-file b/another-dir/initial-file
435 new file mode 100644
435 new file mode 100644
436 --- /dev/null
436 --- /dev/null
437 +++ b/another-dir/initial-file
437 +++ b/another-dir/initial-file
438 @@ -0,0 +1,1 @@
438 @@ -0,0 +1,1 @@
439 +changed
439 +changed
440
440
441 $ hg --config diff.git=yes export 1
441 $ hg --config diff.git=yes export 1
442 # HG changeset patch
442 # HG changeset patch
443 # User test
443 # User test
444 # Date 0 0
444 # Date 0 0
445 # Thu Jan 01 00:00:00 1970 +0000
445 # Thu Jan 01 00:00:00 1970 +0000
446 # Node ID 9b730d82b00af8a2766facebfa47cc124405a118
446 # Node ID 9b730d82b00af8a2766facebfa47cc124405a118
447 # Parent fffadc26f8f85623ce60b028a3f1ccc3730f8530
447 # Parent fffadc26f8f85623ce60b028a3f1ccc3730f8530
448 renamed
448 renamed
449
449
450 diff --git a/another-dir/initial-file b/another-dir/renamed-file
450 diff --git a/another-dir/initial-file b/another-dir/renamed-file
451 rename from another-dir/initial-file
451 rename from another-dir/initial-file
452 rename to another-dir/renamed-file
452 rename to another-dir/renamed-file
453
453
454 $ cd ..
454 $ cd ..
@@ -1,482 +1,482
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 > strip=
6 > strip=
7 > EOF
7 > EOF
8
8
9 $ initrepo ()
9 $ initrepo ()
10 > {
10 > {
11 > hg init r
11 > hg init r
12 > cd r
12 > cd r
13 > for x in a b c d e f g; do
13 > for x in a b c d e f g; do
14 > echo $x > $x
14 > echo $x > $x
15 > hg add $x
15 > hg add $x
16 > hg ci -m $x
16 > hg ci -m $x
17 > done
17 > done
18 > }
18 > }
19
19
20 $ initrepo
20 $ initrepo
21
21
22 log before edit
22 log before edit
23 $ hg log --graph
23 $ hg log --graph
24 @ changeset: 6:3c6a8ed2ebe8
24 @ changeset: 6:3c6a8ed2ebe8
25 | tag: tip
25 | tag: tip
26 | user: test
26 | user: test
27 | date: Thu Jan 01 00:00:00 1970 +0000
27 | date: Thu Jan 01 00:00:00 1970 +0000
28 | summary: g
28 | summary: g
29 |
29 |
30 o changeset: 5:652413bf663e
30 o changeset: 5:652413bf663e
31 | user: test
31 | user: test
32 | date: Thu Jan 01 00:00:00 1970 +0000
32 | date: Thu Jan 01 00:00:00 1970 +0000
33 | summary: f
33 | summary: f
34 |
34 |
35 o changeset: 4:e860deea161a
35 o changeset: 4:e860deea161a
36 | user: test
36 | user: test
37 | date: Thu Jan 01 00:00:00 1970 +0000
37 | date: Thu Jan 01 00:00:00 1970 +0000
38 | summary: e
38 | summary: e
39 |
39 |
40 o changeset: 3:055a42cdd887
40 o changeset: 3:055a42cdd887
41 | user: test
41 | user: test
42 | date: Thu Jan 01 00:00:00 1970 +0000
42 | date: Thu Jan 01 00:00:00 1970 +0000
43 | summary: d
43 | summary: d
44 |
44 |
45 o changeset: 2:177f92b77385
45 o changeset: 2:177f92b77385
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 | user: test
51 | user: test
52 | date: Thu Jan 01 00:00:00 1970 +0000
52 | date: Thu Jan 01 00:00:00 1970 +0000
53 | summary: b
53 | summary: b
54 |
54 |
55 o changeset: 0:cb9a9f314b8b
55 o changeset: 0:cb9a9f314b8b
56 user: test
56 user: test
57 date: Thu Jan 01 00:00:00 1970 +0000
57 date: Thu Jan 01 00:00:00 1970 +0000
58 summary: a
58 summary: a
59
59
60 dirty a file
60 dirty a file
61 $ echo a > g
61 $ echo a > g
62 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF
62 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF
63 > EOF
63 > EOF
64 abort: uncommitted changes
64 abort: uncommitted changes
65 [255]
65 [255]
66 $ echo g > g
66 $ echo g > g
67
67
68 edit the history
68 edit the history
69 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle
69 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF| fixbundle
70 > pick 177f92b77385 c
70 > pick 177f92b77385 c
71 > pick 055a42cdd887 d
71 > pick 055a42cdd887 d
72 > edit e860deea161a e
72 > edit e860deea161a e
73 > pick 652413bf663e f
73 > pick 652413bf663e f
74 > pick 3c6a8ed2ebe8 g
74 > pick 3c6a8ed2ebe8 g
75 > EOF
75 > EOF
76 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
76 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
77 Editing (e860deea161a), you may commit or record as needed now.
77 Editing (e860deea161a), you may commit or record as needed now.
78 (hg histedit --continue to resume)
78 (hg histedit --continue to resume)
79
79
80 try to update and get an error
80 try to update and get an error
81 $ hg update tip
81 $ hg update tip
82 abort: histedit in progress
82 abort: histedit in progress
83 (use 'hg histedit --continue' or 'hg histedit --abort')
83 (use 'hg histedit --continue' or 'hg histedit --abort')
84 [255]
84 [255]
85
85
86 edit the plan via the editor
86 edit the plan via the editor
87 $ cat >> $TESTTMP/editplan.sh <<EOF
87 $ cat >> $TESTTMP/editplan.sh <<EOF
88 > cat > \$1 <<EOF2
88 > cat > \$1 <<EOF2
89 > drop e860deea161a e
89 > drop e860deea161a e
90 > drop 652413bf663e f
90 > drop 652413bf663e f
91 > drop 3c6a8ed2ebe8 g
91 > drop 3c6a8ed2ebe8 g
92 > EOF2
92 > EOF2
93 > EOF
93 > EOF
94 $ HGEDITOR="sh $TESTTMP/editplan.sh" hg histedit --edit-plan
94 $ HGEDITOR="sh $TESTTMP/editplan.sh" hg histedit --edit-plan
95 $ cat .hg/histedit-state
95 $ cat .hg/histedit-state
96 v1
96 v1
97 055a42cdd88768532f9cf79daa407fc8d138de9b
97 055a42cdd88768532f9cf79daa407fc8d138de9b
98 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
98 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
99 False
99 False
100 3
100 3
101 drop
101 drop
102 e860deea161a2f77de56603b340ebbb4536308ae
102 e860deea161a2f77de56603b340ebbb4536308ae
103 drop
103 drop
104 652413bf663ef2a641cab26574e46d5f5a64a55a
104 652413bf663ef2a641cab26574e46d5f5a64a55a
105 drop
105 drop
106 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
106 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
107 0
107 0
108 strip-backup/177f92b77385-0ebe6a8f-histedit.hg
108 strip-backup/177f92b77385-0ebe6a8f-histedit.hg
109
109
110 edit the plan via --commands
110 edit the plan via --commands
111 $ hg histedit --edit-plan --commands - 2>&1 << EOF
111 $ hg histedit --edit-plan --commands - 2>&1 << EOF
112 > edit e860deea161a e
112 > edit e860deea161a e
113 > pick 652413bf663e f
113 > pick 652413bf663e f
114 > drop 3c6a8ed2ebe8 g
114 > drop 3c6a8ed2ebe8 g
115 > EOF
115 > EOF
116 $ cat .hg/histedit-state
116 $ cat .hg/histedit-state
117 v1
117 v1
118 055a42cdd88768532f9cf79daa407fc8d138de9b
118 055a42cdd88768532f9cf79daa407fc8d138de9b
119 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
119 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
120 False
120 False
121 3
121 3
122 edit
122 edit
123 e860deea161a2f77de56603b340ebbb4536308ae
123 e860deea161a2f77de56603b340ebbb4536308ae
124 pick
124 pick
125 652413bf663ef2a641cab26574e46d5f5a64a55a
125 652413bf663ef2a641cab26574e46d5f5a64a55a
126 drop
126 drop
127 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
127 3c6a8ed2ebe862cc949d2caa30775dd6f16fb799
128 0
128 0
129 strip-backup/177f92b77385-0ebe6a8f-histedit.hg
129 strip-backup/177f92b77385-0ebe6a8f-histedit.hg
130
130
131 Go at a random point and try to continue
131 Go at a random point and try to continue
132
132
133 $ hg id -n
133 $ hg id -n
134 3+
134 3+
135 $ hg up 0
135 $ hg up 0
136 abort: histedit in progress
136 abort: histedit in progress
137 (use 'hg histedit --continue' or 'hg histedit --abort')
137 (use 'hg histedit --continue' or 'hg histedit --abort')
138 [255]
138 [255]
139
139
140 Try to delete necessary commit
140 Try to delete necessary commit
141 $ hg strip -r 652413b
141 $ hg strip -r 652413b
142 abort: histedit in progress, can't strip 652413bf663e
142 abort: histedit in progress, can't strip 652413bf663e
143 [255]
143 [255]
144
144
145 commit, then edit the revision
145 commit, then edit the revision
146 $ hg ci -m 'wat'
146 $ hg ci -m 'wat'
147 created new head
147 created new head
148 $ echo a > e
148 $ echo a > e
149
149
150 qnew should fail while we're in the middle of the edit step
150 qnew should fail while we're in the middle of the edit step
151
151
152 $ hg --config extensions.mq= qnew please-fail
152 $ hg --config extensions.mq= qnew please-fail
153 abort: histedit in progress
153 abort: histedit in progress
154 (use 'hg histedit --continue' or 'hg histedit --abort')
154 (use 'hg histedit --continue' or 'hg histedit --abort')
155 [255]
155 [255]
156 $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle
156 $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle
157
157
158 $ hg log --graph
158 $ hg log --graph
159 @ changeset: 6:b5f70786f9b0
159 @ changeset: 6:b5f70786f9b0
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: f
163 | summary: f
164 |
164 |
165 o changeset: 5:a5e1ba2f7afb
165 o changeset: 5:a5e1ba2f7afb
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: foobaz
168 | summary: foobaz
169 |
169 |
170 o changeset: 4:1a60820cd1f6
170 o changeset: 4:1a60820cd1f6
171 | user: test
171 | user: test
172 | date: Thu Jan 01 00:00:00 1970 +0000
172 | date: Thu Jan 01 00:00:00 1970 +0000
173 | summary: wat
173 | summary: wat
174 |
174 |
175 o changeset: 3:055a42cdd887
175 o changeset: 3:055a42cdd887
176 | user: test
176 | user: test
177 | date: Thu Jan 01 00:00:00 1970 +0000
177 | date: Thu Jan 01 00:00:00 1970 +0000
178 | summary: d
178 | summary: d
179 |
179 |
180 o changeset: 2:177f92b77385
180 o changeset: 2:177f92b77385
181 | user: test
181 | user: test
182 | date: Thu Jan 01 00:00:00 1970 +0000
182 | date: Thu Jan 01 00:00:00 1970 +0000
183 | summary: c
183 | summary: c
184 |
184 |
185 o changeset: 1:d2ae7f538514
185 o changeset: 1:d2ae7f538514
186 | user: test
186 | user: test
187 | date: Thu Jan 01 00:00:00 1970 +0000
187 | date: Thu Jan 01 00:00:00 1970 +0000
188 | summary: b
188 | summary: b
189 |
189 |
190 o changeset: 0:cb9a9f314b8b
190 o changeset: 0:cb9a9f314b8b
191 user: test
191 user: test
192 date: Thu Jan 01 00:00:00 1970 +0000
192 date: Thu Jan 01 00:00:00 1970 +0000
193 summary: a
193 summary: a
194
194
195
195
196 $ hg cat e
196 $ hg cat e
197 a
197 a
198
198
199 Stripping necessary commits should not break --abort
199 Stripping necessary commits should not break --abort
200
200
201 $ hg histedit 1a60820cd1f6 --commands - 2>&1 << EOF| fixbundle
201 $ hg histedit 1a60820cd1f6 --commands - 2>&1 << EOF| fixbundle
202 > edit 1a60820cd1f6 wat
202 > edit 1a60820cd1f6 wat
203 > pick a5e1ba2f7afb foobaz
203 > pick a5e1ba2f7afb foobaz
204 > pick b5f70786f9b0 g
204 > pick b5f70786f9b0 g
205 > EOF
205 > EOF
206 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
206 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
207 Editing (1a60820cd1f6), you may commit or record as needed now.
207 Editing (1a60820cd1f6), you may commit or record as needed now.
208 (hg histedit --continue to resume)
208 (hg histedit --continue to resume)
209
209
210 $ mv .hg/histedit-state .hg/histedit-state.bak
210 $ mv .hg/histedit-state .hg/histedit-state.bak
211 $ hg strip -q -r b5f70786f9b0
211 $ hg strip -q -r b5f70786f9b0
212 $ mv .hg/histedit-state.bak .hg/histedit-state
212 $ mv .hg/histedit-state.bak .hg/histedit-state
213 $ hg histedit --abort
213 $ hg histedit --abort
214 adding changesets
214 adding changesets
215 adding manifests
215 adding manifests
216 adding file changes
216 adding file changes
217 added 1 changesets with 1 changes to 3 files
217 added 1 changesets with 1 changes to 3 files
218 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
218 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 $ hg log -r .
219 $ hg log -r .
220 changeset: 6:b5f70786f9b0
220 changeset: 6:b5f70786f9b0
221 tag: tip
221 tag: tip
222 user: test
222 user: test
223 date: Thu Jan 01 00:00:00 1970 +0000
223 date: Thu Jan 01 00:00:00 1970 +0000
224 summary: f
224 summary: f
225
225
226
226
227 check histedit_source
227 check histedit_source
228
228
229 $ hg log --debug --rev 5
229 $ hg log --debug --rev 5
230 changeset: 5:a5e1ba2f7afb899ef1581cea528fd885d2fca70d
230 changeset: 5:a5e1ba2f7afb899ef1581cea528fd885d2fca70d
231 phase: draft
231 phase: draft
232 parent: 4:1a60820cd1f6004a362aa622ebc47d59bc48eb34
232 parent: 4:1a60820cd1f6004a362aa622ebc47d59bc48eb34
233 parent: -1:0000000000000000000000000000000000000000
233 parent: -1:0000000000000000000000000000000000000000
234 manifest: 5:5ad3be8791f39117565557781f5464363b918a45
234 manifest: 5:5ad3be8791f39117565557781f5464363b918a45
235 user: test
235 user: test
236 date: Thu Jan 01 00:00:00 1970 +0000
236 date: Thu Jan 01 00:00:00 1970 +0000
237 files: e
237 files: e
238 extra: branch=default
238 extra: branch=default
239 extra: histedit_source=e860deea161a2f77de56603b340ebbb4536308ae
239 extra: histedit_source=e860deea161a2f77de56603b340ebbb4536308ae
240 description:
240 description:
241 foobaz
241 foobaz
242
242
243
243
244
244
245 $ hg histedit tip --commands - 2>&1 <<EOF| fixbundle
245 $ hg histedit tip --commands - 2>&1 <<EOF| fixbundle
246 > edit b5f70786f9b0 f
246 > edit b5f70786f9b0 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 Editing (b5f70786f9b0), you may commit or record as needed now.
249 Editing (b5f70786f9b0), you may commit or record as needed now.
250 (hg histedit --continue to resume)
250 (hg histedit --continue to resume)
251 $ hg status
251 $ hg status
252 A f
252 A f
253
253
254 $ hg summary
254 $ hg summary
255 parent: 5:a5e1ba2f7afb
255 parent: 5:a5e1ba2f7afb
256 foobaz
256 foobaz
257 branch: default
257 branch: default
258 commit: 1 added (new branch head)
258 commit: 1 added (new branch head)
259 update: 1 new changesets (update)
259 update: 1 new changesets (update)
260 phases: 7 draft
260 phases: 7 draft
261 hist: 1 remaining (histedit --continue)
261 hist: 1 remaining (histedit --continue)
262
262
263 (test also that editor is invoked if histedit is continued for
263 (test also that editor is invoked if histedit is continued for
264 "edit" action)
264 "edit" action)
265
265
266 $ HGEDITOR='cat' hg histedit --continue
266 $ HGEDITOR='cat' hg histedit --continue
267 f
267 f
268
268
269
269
270 HG: Enter commit message. Lines beginning with 'HG:' are removed.
270 HG: Enter commit message. Lines beginning with 'HG:' are removed.
271 HG: Leave message empty to abort commit.
271 HG: Leave message empty to abort commit.
272 HG: --
272 HG: --
273 HG: user: test
273 HG: user: test
274 HG: branch 'default'
274 HG: branch 'default'
275 HG: added f
275 HG: added f
276 saved backup bundle to $TESTTMP/r/.hg/strip-backup/b5f70786f9b0-c28d9c86-backup.hg (glob)
276 saved backup bundle to $TESTTMP/r/.hg/strip-backup/b5f70786f9b0-c28d9c86-backup.hg (glob)
277
277
278 $ hg status
278 $ hg status
279
279
280 log after edit
280 log after edit
281 $ hg log --limit 1
281 $ hg log --limit 1
282 changeset: 6:a107ee126658
282 changeset: 6:a107ee126658
283 tag: tip
283 tag: tip
284 user: test
284 user: test
285 date: Thu Jan 01 00:00:00 1970 +0000
285 date: Thu Jan 01 00:00:00 1970 +0000
286 summary: f
286 summary: f
287
287
288
288
289 say we'll change the message, but don't.
289 say we'll change the message, but don't.
290 $ cat > ../edit.sh <<EOF
290 $ cat > ../edit.sh <<EOF
291 > cat "\$1" | sed s/pick/mess/ > tmp
291 > cat "\$1" | sed s/pick/mess/ > tmp
292 > mv tmp "\$1"
292 > mv tmp "\$1"
293 > EOF
293 > EOF
294 $ HGEDITOR="sh ../edit.sh" hg histedit tip 2>&1 | fixbundle
294 $ HGEDITOR="sh ../edit.sh" hg histedit tip 2>&1 | fixbundle
295 $ hg status
295 $ hg status
296 $ hg log --limit 1
296 $ hg log --limit 1
297 changeset: 6:1fd3b2fe7754
297 changeset: 6:1fd3b2fe7754
298 tag: tip
298 tag: tip
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: f
301 summary: f
302
302
303
303
304 modify the message
304 modify the message
305
305
306 check saving last-message.txt, at first
306 check saving last-message.txt, at first
307
307
308 $ cat > $TESTTMP/commitfailure.py <<EOF
308 $ cat > $TESTTMP/commitfailure.py <<EOF
309 > from mercurial import error
309 > from mercurial import error
310 > def reposetup(ui, repo):
310 > def reposetup(ui, repo):
311 > class commitfailure(repo.__class__):
311 > class commitfailure(repo.__class__):
312 > def commit(self, *args, **kwargs):
312 > def commit(self, *args, **kwargs):
313 > raise error.Abort('emulating unexpected abort')
313 > raise error.Abort('emulating unexpected abort')
314 > repo.__class__ = commitfailure
314 > repo.__class__ = commitfailure
315 > EOF
315 > EOF
316 $ cat >> .hg/hgrc <<EOF
316 $ cat >> .hg/hgrc <<EOF
317 > [extensions]
317 > [extensions]
318 > # this failure occurs before editor invocation
318 > # this failure occurs before editor invocation
319 > commitfailure = $TESTTMP/commitfailure.py
319 > commitfailure = $TESTTMP/commitfailure.py
320 > EOF
320 > EOF
321
321
322 $ cat > $TESTTMP/editor.sh <<EOF
322 $ cat > $TESTTMP/editor.sh <<EOF
323 > echo "==== before editing"
323 > echo "==== before editing"
324 > cat \$1
324 > cat \$1
325 > echo "===="
325 > echo "===="
326 > echo "check saving last-message.txt" >> \$1
326 > echo "check saving last-message.txt" >> \$1
327 > EOF
327 > EOF
328
328
329 (test that editor is not invoked before transaction starting)
329 (test that editor is not invoked before transaction starting)
330
330
331 $ rm -f .hg/last-message.txt
331 $ rm -f .hg/last-message.txt
332 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF | fixbundle
332 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF | fixbundle
333 > mess 1fd3b2fe7754 f
333 > mess 1fd3b2fe7754 f
334 > EOF
334 > EOF
335 abort: emulating unexpected abort
335 abort: emulating unexpected abort
336 $ test -f .hg/last-message.txt
336 $ test -f .hg/last-message.txt
337 [1]
337 [1]
338
338
339 $ cat >> .hg/hgrc <<EOF
339 $ cat >> .hg/hgrc <<EOF
340 > [extensions]
340 > [extensions]
341 > commitfailure = !
341 > commitfailure = !
342 > EOF
342 > EOF
343 $ hg histedit --abort -q
343 $ hg histedit --abort -q
344
344
345 (test that editor is invoked and commit message is saved into
345 (test that editor is invoked and commit message is saved into
346 "last-message.txt")
346 "last-message.txt")
347
347
348 $ cat >> .hg/hgrc <<EOF
348 $ cat >> .hg/hgrc <<EOF
349 > [hooks]
349 > [hooks]
350 > # this failure occurs after editor invocation
350 > # this failure occurs after editor invocation
351 > pretxncommit.unexpectedabort = false
351 > pretxncommit.unexpectedabort = false
352 > EOF
352 > EOF
353
353
354 $ hg status --rev '1fd3b2fe7754^1' --rev 1fd3b2fe7754
354 $ hg status --rev '1fd3b2fe7754^1' --rev 1fd3b2fe7754
355 A f
355 A f
356
356
357 $ rm -f .hg/last-message.txt
357 $ rm -f .hg/last-message.txt
358 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF
358 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit tip --commands - 2>&1 << EOF
359 > mess 1fd3b2fe7754 f
359 > mess 1fd3b2fe7754 f
360 > EOF
360 > EOF
361 ==== before editing
361 ==== before editing
362 f
362 f
363
363
364
364
365 HG: Enter commit message. Lines beginning with 'HG:' are removed.
365 HG: Enter commit message. Lines beginning with 'HG:' are removed.
366 HG: Leave message empty to abort commit.
366 HG: Leave message empty to abort commit.
367 HG: --
367 HG: --
368 HG: user: test
368 HG: user: test
369 HG: branch 'default'
369 HG: branch 'default'
370 HG: added f
370 HG: added f
371 ====
371 ====
372 note: commit message saved in .hg/last-message.txt
372 note: commit message saved in .hg/last-message.txt
373 transaction abort!
373 transaction abort!
374 rollback completed
374 rollback completed
375 abort: pretxncommit.unexpectedabort hook exited with status 1
375 abort: pretxncommit.unexpectedabort hook exited with status 1
376 [255]
376 [255]
377 $ cat .hg/last-message.txt
377 $ cat .hg/last-message.txt
378 f
378 f
379
379
380
380
381 check saving last-message.txt
381 check saving last-message.txt
382
382
383 (test also that editor is invoked if histedit is continued for "message"
383 (test also that editor is invoked if histedit is continued for "message"
384 action)
384 action)
385
385
386 $ HGEDITOR=cat hg histedit --continue
386 $ HGEDITOR=cat hg histedit --continue
387 f
387 f
388
388
389
389
390 HG: Enter commit message. Lines beginning with 'HG:' are removed.
390 HG: Enter commit message. Lines beginning with 'HG:' are removed.
391 HG: Leave message empty to abort commit.
391 HG: Leave message empty to abort commit.
392 HG: --
392 HG: --
393 HG: user: test
393 HG: user: test
394 HG: branch 'default'
394 HG: branch 'default'
395 HG: added f
395 HG: added f
396 note: commit message saved in .hg/last-message.txt
396 note: commit message saved in .hg/last-message.txt
397 transaction abort!
397 transaction abort!
398 rollback completed
398 rollback completed
399 abort: pretxncommit.unexpectedabort hook exited with status 1
399 abort: pretxncommit.unexpectedabort hook exited with status 1
400 [255]
400 [255]
401
401
402 $ cat >> .hg/hgrc <<EOF
402 $ cat >> .hg/hgrc <<EOF
403 > [hooks]
403 > [hooks]
404 > pretxncommit.unexpectedabort =
404 > pretxncommit.unexpectedabort =
405 > EOF
405 > EOF
406 $ hg histedit --abort -q
406 $ hg histedit --abort -q
407
407
408 then, check "modify the message" itself
408 then, check "modify the message" itself
409
409
410 $ hg histedit tip --commands - 2>&1 << EOF | fixbundle
410 $ hg histedit tip --commands - 2>&1 << EOF | fixbundle
411 > mess 1fd3b2fe7754 f
411 > mess 1fd3b2fe7754 f
412 > EOF
412 > EOF
413 $ hg status
413 $ hg status
414 $ hg log --limit 1
414 $ hg log --limit 1
415 changeset: 6:62feedb1200e
415 changeset: 6:62feedb1200e
416 tag: tip
416 tag: tip
417 user: test
417 user: test
418 date: Thu Jan 01 00:00:00 1970 +0000
418 date: Thu Jan 01 00:00:00 1970 +0000
419 summary: f
419 summary: f
420
420
421
421
422 rollback should not work after a histedit
422 rollback should not work after a histedit
423 $ hg rollback
423 $ hg rollback
424 no rollback information available
424 no rollback information available
425 [1]
425 [1]
426
426
427 $ cd ..
427 $ cd ..
428 $ hg clone -qr0 r r0
428 $ hg clone -qr0 r r0
429 $ cd r0
429 $ cd r0
430 $ hg phase -fdr0
430 $ hg phase -fdr0
431 $ hg histedit --commands - 0 2>&1 << EOF
431 $ hg histedit --commands - 0 2>&1 << EOF
432 > edit cb9a9f314b8b a > $EDITED
432 > edit cb9a9f314b8b a > $EDITED
433 > EOF
433 > EOF
434 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
434 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
435 adding a
435 adding a
436 Editing (cb9a9f314b8b), you may commit or record as needed now.
436 Editing (cb9a9f314b8b), you may commit or record as needed now.
437 (hg histedit --continue to resume)
437 (hg histedit --continue to resume)
438 [1]
438 [1]
439 $ HGEDITOR=true hg histedit --continue
439 $ HGEDITOR=true hg histedit --continue
440 saved backup bundle to $TESTTMP/r0/.hg/strip-backup/cb9a9f314b8b-cc5ccb0b-backup.hg (glob)
440 saved backup bundle to $TESTTMP/r0/.hg/strip-backup/cb9a9f314b8b-cc5ccb0b-backup.hg (glob)
441
441
442 $ hg log -G
442 $ hg log -G
443 @ changeset: 0:0efcea34f18a
443 @ changeset: 0:0efcea34f18a
444 tag: tip
444 tag: tip
445 user: test
445 user: test
446 date: Thu Jan 01 00:00:00 1970 +0000
446 date: Thu Jan 01 00:00:00 1970 +0000
447 summary: a
447 summary: a
448
448
449 $ echo foo >> b
449 $ echo foo >> b
450 $ hg addr
450 $ hg addr
451 adding b
451 adding b
452 $ hg ci -m 'add b'
452 $ hg ci -m 'add b'
453 $ echo foo >> a
453 $ echo foo >> a
454 $ hg ci -m 'extend a'
454 $ hg ci -m 'extend a'
455 $ hg phase --public 1
455 $ hg phase --public 1
456 Attempting to fold a change into a public change should not work:
456 Attempting to fold a change into a public change should not work:
457 $ cat > ../edit.sh <<EOF
457 $ cat > ../edit.sh <<EOF
458 > cat "\$1" | sed s/pick/fold/ > tmp
458 > cat "\$1" | sed s/pick/fold/ > tmp
459 > mv tmp "\$1"
459 > mv tmp "\$1"
460 > EOF
460 > EOF
461 $ HGEDITOR="sh ../edit.sh" hg histedit 2
461 $ HGEDITOR="sh ../edit.sh" hg histedit 2
462 warning: histedit rules saved to: .hg/histedit-last-edit.txt
462 warning: histedit rules saved to: .hg/histedit-last-edit.txt
463 hg: parse error: cannot fold into public change 18aa70c8ad22
463 hg: parse error: cannot fold into public change 18aa70c8ad22
464 [255]
464 [255]
465 $ cat .hg/histedit-last-edit.txt
465 $ cat .hg/histedit-last-edit.txt
466 fold 0012be4a27ea 2 extend a
466 fold 0012be4a27ea 2 extend a
467
467
468 # Edit history between 0012be4a27ea and 0012be4a27ea
468 # Edit history between 0012be4a27ea and 0012be4a27ea
469 #
469 #
470 # Commits are listed from least to most recent
470 # Commits are listed from least to most recent
471 #
471 #
472 # You can reorder changesets by reordering the lines
472 # You can reorder changesets by reordering the lines
473 #
473 #
474 # Commands:
474 # Commands:
475 #
475 #
476 # e, edit = use commit, but stop for amending
476 # e, edit = use commit, but stop for amending
477 # m, mess = edit commit message without changing commit content
477 # m, mess = edit commit message without changing commit content
478 # p, fold = use commit
478 # p, fold = use commit
479 # d, drop = remove commit from history
479 # d, drop = remove commit from history
480 # f, fold = use commit, but combine it with the one above
480 # f, fold = use commit, but combine it with the one above
481 # r, roll = like fold, but discard this commit's description
481 # r, roll = like fold, but discard this commit's description and date
482 #
482 #
@@ -1,344 +1,344
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 $ modwithdate ()
8 $ modwithdate ()
9 > {
9 > {
10 > echo $1 > $1
10 > echo $1 > $1
11 > hg ci -m $1 -d "$2 0"
11 > hg ci -m $1 -d "$2 0"
12 > }
12 > }
13
13
14 $ initrepo ()
14 $ initrepo ()
15 > {
15 > {
16 > hg init $1
16 > hg init $1
17 > cd $1
17 > cd $1
18 > for x in a b c d e f ; do
18 > for x in a b c d e f ; do
19 > echo $x$x$x$x$x > $x
19 > echo $x$x$x$x$x > $x
20 > hg add $x
20 > hg add $x
21 > done
21 > done
22 > hg ci -m 'Initial commit'
22 > hg ci -m 'Initial commit'
23 > modwithdate a 1
23 > modwithdate a 1
24 > modwithdate b 2
24 > modwithdate b 2
25 > modwithdate c 3
25 > modwithdate c 3
26 > modwithdate d 4
26 > modwithdate d 4
27 > modwithdate e 5
27 > modwithdate e 5
28 > modwithdate f 6
28 > modwithdate f 6
29 > echo 'I can haz no commute' > e
29 > echo 'I can haz no commute' > e
30 > hg ci -m 'does not commute with e' -d '7 0'
30 > hg ci -m 'does not commute with e' -d '7 0'
31 > cd ..
31 > cd ..
32 > }
32 > }
33
33
34 $ initrepo r
34 $ initrepo r
35 $ cd r
35 $ cd r
36 Initial generation of the command files
36 Initial generation of the command files
37
37
38 $ EDITED="$TESTTMP/editedhistory"
38 $ EDITED="$TESTTMP/editedhistory"
39 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
39 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
40 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
40 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
41 $ hg log --template 'fold {node|short} {rev} {desc}\n' -r 7 >> $EDITED
41 $ hg log --template 'fold {node|short} {rev} {desc}\n' -r 7 >> $EDITED
42 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
42 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
43 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
43 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
44 $ cat $EDITED
44 $ cat $EDITED
45 pick 092e4ce14829 3 c
45 pick 092e4ce14829 3 c
46 pick ae78f4c9d74f 4 d
46 pick ae78f4c9d74f 4 d
47 fold 42abbb61bede 7 does not commute with e
47 fold 42abbb61bede 7 does not commute with e
48 pick 7f3755409b00 5 e
48 pick 7f3755409b00 5 e
49 pick dd184f2faeb0 6 f
49 pick dd184f2faeb0 6 f
50
50
51 log before edit
51 log before edit
52 $ hg log --graph
52 $ hg log --graph
53 @ changeset: 7:42abbb61bede
53 @ changeset: 7:42abbb61bede
54 | tag: tip
54 | tag: tip
55 | user: test
55 | user: test
56 | date: Thu Jan 01 00:00:07 1970 +0000
56 | date: Thu Jan 01 00:00:07 1970 +0000
57 | summary: does not commute with e
57 | summary: does not commute with e
58 |
58 |
59 o changeset: 6:dd184f2faeb0
59 o changeset: 6:dd184f2faeb0
60 | user: test
60 | user: test
61 | date: Thu Jan 01 00:00:06 1970 +0000
61 | date: Thu Jan 01 00:00:06 1970 +0000
62 | summary: f
62 | summary: f
63 |
63 |
64 o changeset: 5:7f3755409b00
64 o changeset: 5:7f3755409b00
65 | user: test
65 | user: test
66 | date: Thu Jan 01 00:00:05 1970 +0000
66 | date: Thu Jan 01 00:00:05 1970 +0000
67 | summary: e
67 | summary: e
68 |
68 |
69 o changeset: 4:ae78f4c9d74f
69 o changeset: 4:ae78f4c9d74f
70 | user: test
70 | user: test
71 | date: Thu Jan 01 00:00:04 1970 +0000
71 | date: Thu Jan 01 00:00:04 1970 +0000
72 | summary: d
72 | summary: d
73 |
73 |
74 o changeset: 3:092e4ce14829
74 o changeset: 3:092e4ce14829
75 | user: test
75 | user: test
76 | date: Thu Jan 01 00:00:03 1970 +0000
76 | date: Thu Jan 01 00:00:03 1970 +0000
77 | summary: c
77 | summary: c
78 |
78 |
79 o changeset: 2:40ccdd8beb95
79 o changeset: 2:40ccdd8beb95
80 | user: test
80 | user: test
81 | date: Thu Jan 01 00:00:02 1970 +0000
81 | date: Thu Jan 01 00:00:02 1970 +0000
82 | summary: b
82 | summary: b
83 |
83 |
84 o changeset: 1:cd997a145b29
84 o changeset: 1:cd997a145b29
85 | user: test
85 | user: test
86 | date: Thu Jan 01 00:00:01 1970 +0000
86 | date: Thu Jan 01 00:00:01 1970 +0000
87 | summary: a
87 | summary: a
88 |
88 |
89 o changeset: 0:1715188a53c7
89 o changeset: 0:1715188a53c7
90 user: test
90 user: test
91 date: Thu Jan 01 00:00:00 1970 +0000
91 date: Thu Jan 01 00:00:00 1970 +0000
92 summary: Initial commit
92 summary: Initial commit
93
93
94
94
95 edit the history
95 edit the history
96 $ hg histedit 3 --commands $EDITED 2>&1 | fixbundle
96 $ hg histedit 3 --commands $EDITED 2>&1 | fixbundle
97 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 merging e
98 merging e
99 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
99 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
100 Fix up the change (fold 42abbb61bede)
100 Fix up the change (fold 42abbb61bede)
101 (hg histedit --continue to resume)
101 (hg histedit --continue to resume)
102
102
103 fix up
103 fix up
104 $ echo 'I can haz no commute' > e
104 $ echo 'I can haz no commute' > e
105 $ hg resolve --mark e
105 $ hg resolve --mark e
106 (no more unresolved files)
106 (no more unresolved files)
107 continue: hg histedit --continue
107 continue: hg histedit --continue
108 $ HGEDITOR=cat hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
108 $ HGEDITOR=cat hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
109 d
109 d
110 ***
110 ***
111 does not commute with e
111 does not commute with e
112
112
113
113
114
114
115 HG: Enter commit message. Lines beginning with 'HG:' are removed.
115 HG: Enter commit message. Lines beginning with 'HG:' are removed.
116 HG: Leave message empty to abort commit.
116 HG: Leave message empty to abort commit.
117 HG: --
117 HG: --
118 HG: user: test
118 HG: user: test
119 HG: branch 'default'
119 HG: branch 'default'
120 HG: changed d
120 HG: changed d
121 HG: changed e
121 HG: changed e
122 merging e
122 merging e
123 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
123 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
124 Fix up the change (pick 7f3755409b00)
124 Fix up the change (pick 7f3755409b00)
125 (hg histedit --continue to resume)
125 (hg histedit --continue to resume)
126
126
127 just continue this time
127 just continue this time
128 keep the non-commuting change, and thus the pending change will be dropped
128 keep the non-commuting change, and thus the pending change will be dropped
129 $ hg revert -r 'p1()' e
129 $ hg revert -r 'p1()' e
130 $ hg resolve --mark e
130 $ hg resolve --mark e
131 (no more unresolved files)
131 (no more unresolved files)
132 continue: hg histedit --continue
132 continue: hg histedit --continue
133 $ hg diff
133 $ hg diff
134 $ hg histedit --continue 2>&1 | fixbundle
134 $ hg histedit --continue 2>&1 | fixbundle
135 7f3755409b00: skipping changeset (no changes)
135 7f3755409b00: skipping changeset (no changes)
136
136
137 log after edit
137 log after edit
138 $ hg log --graph
138 $ hg log --graph
139 @ changeset: 5:1300355b1a54
139 @ changeset: 5:1300355b1a54
140 | tag: tip
140 | tag: tip
141 | user: test
141 | user: test
142 | date: Thu Jan 01 00:00:06 1970 +0000
142 | date: Thu Jan 01 00:00:06 1970 +0000
143 | summary: f
143 | summary: f
144 |
144 |
145 o changeset: 4:e2ac33269083
145 o changeset: 4:e2ac33269083
146 | user: test
146 | user: test
147 | date: Thu Jan 01 00:00:07 1970 +0000
147 | date: Thu Jan 01 00:00:07 1970 +0000
148 | summary: d
148 | summary: d
149 |
149 |
150 o changeset: 3:092e4ce14829
150 o changeset: 3:092e4ce14829
151 | user: test
151 | user: test
152 | date: Thu Jan 01 00:00:03 1970 +0000
152 | date: Thu Jan 01 00:00:03 1970 +0000
153 | summary: c
153 | summary: c
154 |
154 |
155 o changeset: 2:40ccdd8beb95
155 o changeset: 2:40ccdd8beb95
156 | user: test
156 | user: test
157 | date: Thu Jan 01 00:00:02 1970 +0000
157 | date: Thu Jan 01 00:00:02 1970 +0000
158 | summary: b
158 | summary: b
159 |
159 |
160 o changeset: 1:cd997a145b29
160 o changeset: 1:cd997a145b29
161 | user: test
161 | user: test
162 | date: Thu Jan 01 00:00:01 1970 +0000
162 | date: Thu Jan 01 00:00:01 1970 +0000
163 | summary: a
163 | summary: a
164 |
164 |
165 o changeset: 0:1715188a53c7
165 o changeset: 0:1715188a53c7
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: Initial commit
168 summary: Initial commit
169
169
170
170
171 contents of e
171 contents of e
172 $ hg cat e
172 $ hg cat e
173 I can haz no commute
173 I can haz no commute
174
174
175 manifest
175 manifest
176 $ hg manifest
176 $ hg manifest
177 a
177 a
178 b
178 b
179 c
179 c
180 d
180 d
181 e
181 e
182 f
182 f
183
183
184 $ cd ..
184 $ cd ..
185
185
186 Repeat test using "roll", not "fold". "roll" folds in changes but drops message
186 Repeat test using "roll", not "fold". "roll" folds in changes but drops message and date
187
187
188 $ initrepo r2
188 $ initrepo r2
189 $ cd r2
189 $ cd r2
190
190
191 Initial generation of the command files
191 Initial generation of the command files
192
192
193 $ EDITED="$TESTTMP/editedhistory.2"
193 $ EDITED="$TESTTMP/editedhistory.2"
194 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
194 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
195 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
195 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
196 $ hg log --template 'roll {node|short} {rev} {desc}\n' -r 7 >> $EDITED
196 $ hg log --template 'roll {node|short} {rev} {desc}\n' -r 7 >> $EDITED
197 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
197 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
198 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
198 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
199 $ cat $EDITED
199 $ cat $EDITED
200 pick 092e4ce14829 3 c
200 pick 092e4ce14829 3 c
201 pick ae78f4c9d74f 4 d
201 pick ae78f4c9d74f 4 d
202 roll 42abbb61bede 7 does not commute with e
202 roll 42abbb61bede 7 does not commute with e
203 pick 7f3755409b00 5 e
203 pick 7f3755409b00 5 e
204 pick dd184f2faeb0 6 f
204 pick dd184f2faeb0 6 f
205
205
206 log before edit
206 log before edit
207 $ hg log --graph
207 $ hg log --graph
208 @ changeset: 7:42abbb61bede
208 @ changeset: 7:42abbb61bede
209 | tag: tip
209 | tag: tip
210 | user: test
210 | user: test
211 | date: Thu Jan 01 00:00:07 1970 +0000
211 | date: Thu Jan 01 00:00:07 1970 +0000
212 | summary: does not commute with e
212 | summary: does not commute with e
213 |
213 |
214 o changeset: 6:dd184f2faeb0
214 o changeset: 6:dd184f2faeb0
215 | user: test
215 | user: test
216 | date: Thu Jan 01 00:00:06 1970 +0000
216 | date: Thu Jan 01 00:00:06 1970 +0000
217 | summary: f
217 | summary: f
218 |
218 |
219 o changeset: 5:7f3755409b00
219 o changeset: 5:7f3755409b00
220 | user: test
220 | user: test
221 | date: Thu Jan 01 00:00:05 1970 +0000
221 | date: Thu Jan 01 00:00:05 1970 +0000
222 | summary: e
222 | summary: e
223 |
223 |
224 o changeset: 4:ae78f4c9d74f
224 o changeset: 4:ae78f4c9d74f
225 | user: test
225 | user: test
226 | date: Thu Jan 01 00:00:04 1970 +0000
226 | date: Thu Jan 01 00:00:04 1970 +0000
227 | summary: d
227 | summary: d
228 |
228 |
229 o changeset: 3:092e4ce14829
229 o changeset: 3:092e4ce14829
230 | user: test
230 | user: test
231 | date: Thu Jan 01 00:00:03 1970 +0000
231 | date: Thu Jan 01 00:00:03 1970 +0000
232 | summary: c
232 | summary: c
233 |
233 |
234 o changeset: 2:40ccdd8beb95
234 o changeset: 2:40ccdd8beb95
235 | user: test
235 | user: test
236 | date: Thu Jan 01 00:00:02 1970 +0000
236 | date: Thu Jan 01 00:00:02 1970 +0000
237 | summary: b
237 | summary: b
238 |
238 |
239 o changeset: 1:cd997a145b29
239 o changeset: 1:cd997a145b29
240 | user: test
240 | user: test
241 | date: Thu Jan 01 00:00:01 1970 +0000
241 | date: Thu Jan 01 00:00:01 1970 +0000
242 | summary: a
242 | summary: a
243 |
243 |
244 o changeset: 0:1715188a53c7
244 o changeset: 0:1715188a53c7
245 user: test
245 user: test
246 date: Thu Jan 01 00:00:00 1970 +0000
246 date: Thu Jan 01 00:00:00 1970 +0000
247 summary: Initial commit
247 summary: Initial commit
248
248
249
249
250 edit the history
250 edit the history
251 $ hg histedit 3 --commands $EDITED 2>&1 | fixbundle
251 $ hg histedit 3 --commands $EDITED 2>&1 | fixbundle
252 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
252 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 merging e
253 merging e
254 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
254 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
255 Fix up the change (roll 42abbb61bede)
255 Fix up the change (roll 42abbb61bede)
256 (hg histedit --continue to resume)
256 (hg histedit --continue to resume)
257
257
258 fix up
258 fix up
259 $ echo 'I can haz no commute' > e
259 $ echo 'I can haz no commute' > e
260 $ hg resolve --mark e
260 $ hg resolve --mark e
261 (no more unresolved files)
261 (no more unresolved files)
262 continue: hg histedit --continue
262 continue: hg histedit --continue
263 $ hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
263 $ hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
264 merging e
264 merging e
265 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
265 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
266 Fix up the change (pick 7f3755409b00)
266 Fix up the change (pick 7f3755409b00)
267 (hg histedit --continue to resume)
267 (hg histedit --continue to resume)
268
268
269 just continue this time
269 just continue this time
270 $ hg revert -r 'p1()' e
270 $ hg revert -r 'p1()' e
271 $ hg resolve --mark e
271 $ hg resolve --mark e
272 (no more unresolved files)
272 (no more unresolved files)
273 continue: hg histedit --continue
273 continue: hg histedit --continue
274 $ hg histedit --continue 2>&1 | fixbundle
274 $ hg histedit --continue 2>&1 | fixbundle
275 7f3755409b00: skipping changeset (no changes)
275 7f3755409b00: skipping changeset (no changes)
276
276
277 log after edit
277 log after edit
278 $ hg log --graph
278 $ hg log --graph
279 @ changeset: 5:162978f027fb
279 @ changeset: 5:b538bcb461be
280 | tag: tip
280 | tag: tip
281 | user: test
281 | user: test
282 | date: Thu Jan 01 00:00:06 1970 +0000
282 | date: Thu Jan 01 00:00:06 1970 +0000
283 | summary: f
283 | summary: f
284 |
284 |
285 o changeset: 4:74e5e6c6c32f
285 o changeset: 4:317e37cb6d66
286 | user: test
286 | user: test
287 | date: Thu Jan 01 00:00:07 1970 +0000
287 | date: Thu Jan 01 00:00:04 1970 +0000
288 | summary: d
288 | summary: d
289 |
289 |
290 o changeset: 3:092e4ce14829
290 o changeset: 3:092e4ce14829
291 | user: test
291 | user: test
292 | date: Thu Jan 01 00:00:03 1970 +0000
292 | date: Thu Jan 01 00:00:03 1970 +0000
293 | summary: c
293 | summary: c
294 |
294 |
295 o changeset: 2:40ccdd8beb95
295 o changeset: 2:40ccdd8beb95
296 | user: test
296 | user: test
297 | date: Thu Jan 01 00:00:02 1970 +0000
297 | date: Thu Jan 01 00:00:02 1970 +0000
298 | summary: b
298 | summary: b
299 |
299 |
300 o changeset: 1:cd997a145b29
300 o changeset: 1:cd997a145b29
301 | user: test
301 | user: test
302 | date: Thu Jan 01 00:00:01 1970 +0000
302 | date: Thu Jan 01 00:00:01 1970 +0000
303 | summary: a
303 | summary: a
304 |
304 |
305 o changeset: 0:1715188a53c7
305 o changeset: 0:1715188a53c7
306 user: test
306 user: test
307 date: Thu Jan 01 00:00:00 1970 +0000
307 date: Thu Jan 01 00:00:00 1970 +0000
308 summary: Initial commit
308 summary: Initial commit
309
309
310
310
311 contents of e
311 contents of e
312 $ hg cat e
312 $ hg cat e
313 I can haz no commute
313 I can haz no commute
314
314
315 manifest
315 manifest
316 $ hg manifest
316 $ hg manifest
317 a
317 a
318 b
318 b
319 c
319 c
320 d
320 d
321 e
321 e
322 f
322 f
323
323
324 description is taken from rollup target commit
324 description is taken from rollup target commit
325
325
326 $ hg log --debug --rev 4
326 $ hg log --debug --rev 4
327 changeset: 4:74e5e6c6c32fa39f0eeed43302fd48633ea5926f
327 changeset: 4:317e37cb6d66c1c84628c00e5bf4c8c292831951
328 phase: draft
328 phase: draft
329 parent: 3:092e4ce14829f4974399ce4316d59f64ef0b6725
329 parent: 3:092e4ce14829f4974399ce4316d59f64ef0b6725
330 parent: -1:0000000000000000000000000000000000000000
330 parent: -1:0000000000000000000000000000000000000000
331 manifest: 4:b068a323d969f22af1296ec6a5ea9384cef437ac
331 manifest: 4:b068a323d969f22af1296ec6a5ea9384cef437ac
332 user: test
332 user: test
333 date: Thu Jan 01 00:00:07 1970 +0000
333 date: Thu Jan 01 00:00:04 1970 +0000
334 files: d e
334 files: d e
335 extra: branch=default
335 extra: branch=default
336 extra: histedit_source=ae78f4c9d74ffa4b6cb5045001c303fe9204e890,42abbb61bede6f4366fa1e74a664343e5d558a70
336 extra: histedit_source=ae78f4c9d74ffa4b6cb5045001c303fe9204e890,42abbb61bede6f4366fa1e74a664343e5d558a70
337 description:
337 description:
338 d
338 d
339
339
340
340
341
341
342 done with repo r2
342 done with repo r2
343
343
344 $ cd ..
344 $ cd ..
@@ -1,543 +1,543
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 $ addwithdate ()
23 $ addwithdate ()
24 > {
24 > {
25 > echo $1 > $1
25 > echo $1 > $1
26 > hg add $1
26 > hg add $1
27 > hg ci -m $1 -d "$2 0"
27 > hg ci -m $1 -d "$2 0"
28 > }
28 > }
29
29
30 $ initrepo ()
30 $ initrepo ()
31 > {
31 > {
32 > hg init r
32 > hg init r
33 > cd r
33 > cd r
34 > addwithdate a 1
34 > addwithdate a 1
35 > addwithdate b 2
35 > addwithdate b 2
36 > addwithdate c 3
36 > addwithdate c 3
37 > addwithdate d 4
37 > addwithdate d 4
38 > addwithdate e 5
38 > addwithdate e 5
39 > addwithdate f 6
39 > addwithdate f 6
40 > }
40 > }
41
41
42 $ initrepo
42 $ initrepo
43
43
44 log before edit
44 log before edit
45 $ hg logt --graph
45 $ hg logt --graph
46 @ 5:178e35e0ce73 f
46 @ 5:178e35e0ce73 f
47 |
47 |
48 o 4:1ddb6c90f2ee e
48 o 4:1ddb6c90f2ee e
49 |
49 |
50 o 3:532247a8969b d
50 o 3:532247a8969b d
51 |
51 |
52 o 2:ff2c9fa2018b c
52 o 2:ff2c9fa2018b c
53 |
53 |
54 o 1:97d72e5f12c7 b
54 o 1:97d72e5f12c7 b
55 |
55 |
56 o 0:8580ff50825a a
56 o 0:8580ff50825a a
57
57
58
58
59 $ hg histedit ff2c9fa2018b --commands - 2>&1 <<EOF | fixbundle
59 $ hg histedit ff2c9fa2018b --commands - 2>&1 <<EOF | fixbundle
60 > pick 1ddb6c90f2ee e
60 > pick 1ddb6c90f2ee e
61 > pick 178e35e0ce73 f
61 > pick 178e35e0ce73 f
62 > fold ff2c9fa2018b c
62 > fold ff2c9fa2018b c
63 > pick 532247a8969b d
63 > pick 532247a8969b d
64 > EOF
64 > EOF
65
65
66 log after edit
66 log after edit
67 $ hg logt --graph
67 $ hg logt --graph
68 @ 4:c4d7f3def76d d
68 @ 4:c4d7f3def76d d
69 |
69 |
70 o 3:575228819b7e f
70 o 3:575228819b7e f
71 |
71 |
72 o 2:505a591af19e e
72 o 2:505a591af19e e
73 |
73 |
74 o 1:97d72e5f12c7 b
74 o 1:97d72e5f12c7 b
75 |
75 |
76 o 0:8580ff50825a a
76 o 0:8580ff50825a a
77
77
78
78
79 post-fold manifest
79 post-fold manifest
80 $ hg manifest
80 $ hg manifest
81 a
81 a
82 b
82 b
83 c
83 c
84 d
84 d
85 e
85 e
86 f
86 f
87
87
88
88
89 check histedit_source, including that it uses the later date, from the first changeset
89 check histedit_source, including that it uses the later date, from the first changeset
90
90
91 $ hg log --debug --rev 3
91 $ hg log --debug --rev 3
92 changeset: 3:575228819b7e6ed69e8c0a6a383ee59a80db7358
92 changeset: 3:575228819b7e6ed69e8c0a6a383ee59a80db7358
93 phase: draft
93 phase: draft
94 parent: 2:505a591af19eed18f560af827b9e03d2076773dc
94 parent: 2:505a591af19eed18f560af827b9e03d2076773dc
95 parent: -1:0000000000000000000000000000000000000000
95 parent: -1:0000000000000000000000000000000000000000
96 manifest: 3:81eede616954057198ead0b2c73b41d1f392829a
96 manifest: 3:81eede616954057198ead0b2c73b41d1f392829a
97 user: test
97 user: test
98 date: Thu Jan 01 00:00:06 1970 +0000
98 date: Thu Jan 01 00:00:06 1970 +0000
99 files+: c f
99 files+: c f
100 extra: branch=default
100 extra: branch=default
101 extra: histedit_source=7cad1d7030207872dfd1c3a7cb430f24f2884086,ff2c9fa2018b15fa74b33363bda9527323e2a99f
101 extra: histedit_source=7cad1d7030207872dfd1c3a7cb430f24f2884086,ff2c9fa2018b15fa74b33363bda9527323e2a99f
102 description:
102 description:
103 f
103 f
104 ***
104 ***
105 c
105 c
106
106
107
107
108
108
109 rollup will fold without preserving the folded commit's message
109 rollup will fold without preserving the folded commit's message or date
110
110
111 $ OLDHGEDITOR=$HGEDITOR
111 $ OLDHGEDITOR=$HGEDITOR
112 $ HGEDITOR=false
112 $ HGEDITOR=false
113 $ hg histedit 97d72e5f12c7 --commands - 2>&1 <<EOF | fixbundle
113 $ hg histedit 97d72e5f12c7 --commands - 2>&1 <<EOF | fixbundle
114 > pick 97d72e5f12c7 b
114 > pick 97d72e5f12c7 b
115 > roll 505a591af19e e
115 > roll 505a591af19e e
116 > pick 575228819b7e f
116 > pick 575228819b7e f
117 > pick c4d7f3def76d d
117 > pick c4d7f3def76d d
118 > EOF
118 > EOF
119
119
120 $ HGEDITOR=$OLDHGEDITOR
120 $ HGEDITOR=$OLDHGEDITOR
121
121
122 log after edit
122 log after edit
123 $ hg logt --graph
123 $ hg logt --graph
124 @ 3:fb13f1f49340 d
124 @ 3:bab801520cec d
125 |
125 |
126 o 2:6d4bc3727566 f
126 o 2:58c8f2bfc151 f
127 |
127 |
128 o 1:563995ddbe65 b
128 o 1:5d939c56c72e b
129 |
129 |
130 o 0:8580ff50825a a
130 o 0:8580ff50825a a
131
131
132
132
133 description is taken from rollup target commit
133 description is taken from rollup target commit
134
134
135 $ hg log --debug --rev 1
135 $ hg log --debug --rev 1
136 changeset: 1:563995ddbe650c0e6b0e1c1d75f0a197b61cec50
136 changeset: 1:5d939c56c72e77e29f5167696218e2131a40f5cf
137 phase: draft
137 phase: draft
138 parent: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
138 parent: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
139 parent: -1:0000000000000000000000000000000000000000
139 parent: -1:0000000000000000000000000000000000000000
140 manifest: 1:b5e112a3a8354e269b1524729f0918662d847c38
140 manifest: 1:b5e112a3a8354e269b1524729f0918662d847c38
141 user: test
141 user: test
142 date: Thu Jan 01 00:00:05 1970 +0000
142 date: Thu Jan 01 00:00:02 1970 +0000
143 files+: b e
143 files+: b e
144 extra: branch=default
144 extra: branch=default
145 extra: histedit_source=97d72e5f12c7e84f85064aa72e5a297142c36ed9,505a591af19eed18f560af827b9e03d2076773dc
145 extra: histedit_source=97d72e5f12c7e84f85064aa72e5a297142c36ed9,505a591af19eed18f560af827b9e03d2076773dc
146 description:
146 description:
147 b
147 b
148
148
149
149
150
150
151 check saving last-message.txt
151 check saving last-message.txt
152
152
153 $ cat > $TESTTMP/abortfolding.py <<EOF
153 $ cat > $TESTTMP/abortfolding.py <<EOF
154 > from mercurial import util
154 > from mercurial import util
155 > def abortfolding(ui, repo, hooktype, **kwargs):
155 > def abortfolding(ui, repo, hooktype, **kwargs):
156 > ctx = repo[kwargs.get('node')]
156 > ctx = repo[kwargs.get('node')]
157 > if set(ctx.files()) == set(['c', 'd', 'f']):
157 > if set(ctx.files()) == set(['c', 'd', 'f']):
158 > return True # abort folding commit only
158 > return True # abort folding commit only
159 > ui.warn('allow non-folding commit\\n')
159 > ui.warn('allow non-folding commit\\n')
160 > EOF
160 > EOF
161 $ cat > .hg/hgrc <<EOF
161 $ cat > .hg/hgrc <<EOF
162 > [hooks]
162 > [hooks]
163 > pretxncommit.abortfolding = python:$TESTTMP/abortfolding.py:abortfolding
163 > pretxncommit.abortfolding = python:$TESTTMP/abortfolding.py:abortfolding
164 > EOF
164 > EOF
165
165
166 $ cat > $TESTTMP/editor.sh << EOF
166 $ cat > $TESTTMP/editor.sh << EOF
167 > echo "==== before editing"
167 > echo "==== before editing"
168 > cat \$1
168 > cat \$1
169 > echo "===="
169 > echo "===="
170 > echo "check saving last-message.txt" >> \$1
170 > echo "check saving last-message.txt" >> \$1
171 > EOF
171 > EOF
172
172
173 $ rm -f .hg/last-message.txt
173 $ rm -f .hg/last-message.txt
174 $ hg status --rev '6d4bc3727566^1::fb13f1f49340'
174 $ hg status --rev '58c8f2bfc151^1::bab801520cec'
175 A c
175 A c
176 A d
176 A d
177 A f
177 A f
178 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 6d4bc3727566 --commands - 2>&1 <<EOF
178 $ HGEDITOR="sh $TESTTMP/editor.sh" hg histedit 58c8f2bfc151 --commands - 2>&1 <<EOF
179 > pick 6d4bc3727566 f
179 > pick 58c8f2bfc151 f
180 > fold fb13f1f49340 d
180 > fold bab801520cec d
181 > EOF
181 > EOF
182 allow non-folding commit
182 allow non-folding commit
183 ==== before editing
183 ==== before editing
184 f
184 f
185 ***
185 ***
186 c
186 c
187 ***
187 ***
188 d
188 d
189
189
190
190
191
191
192 HG: Enter commit message. Lines beginning with 'HG:' are removed.
192 HG: Enter commit message. Lines beginning with 'HG:' are removed.
193 HG: Leave message empty to abort commit.
193 HG: Leave message empty to abort commit.
194 HG: --
194 HG: --
195 HG: user: test
195 HG: user: test
196 HG: branch 'default'
196 HG: branch 'default'
197 HG: added c
197 HG: added c
198 HG: added d
198 HG: added d
199 HG: added f
199 HG: added f
200 ====
200 ====
201 transaction abort!
201 transaction abort!
202 rollback completed
202 rollback completed
203 abort: pretxncommit.abortfolding hook failed
203 abort: pretxncommit.abortfolding hook failed
204 [255]
204 [255]
205
205
206 $ cat .hg/last-message.txt
206 $ cat .hg/last-message.txt
207 f
207 f
208 ***
208 ***
209 c
209 c
210 ***
210 ***
211 d
211 d
212
212
213
213
214
214
215 check saving last-message.txt
215 check saving last-message.txt
216
216
217 $ cd ..
217 $ cd ..
218 $ rm -r r
218 $ rm -r r
219
219
220 folding preserves initial author but uses later date
220 folding preserves initial author but uses later date
221 ----------------------------------------------------
221 ----------------------------------------------------
222
222
223 $ initrepo
223 $ initrepo
224
224
225 $ hg ci -d '7 0' --user "someone else" --amend --quiet
225 $ hg ci -d '7 0' --user "someone else" --amend --quiet
226
226
227 tip before edit
227 tip before edit
228 $ hg log --rev .
228 $ hg log --rev .
229 changeset: 5:10c36dd37515
229 changeset: 5:10c36dd37515
230 tag: tip
230 tag: tip
231 user: someone else
231 user: someone else
232 date: Thu Jan 01 00:00:07 1970 +0000
232 date: Thu Jan 01 00:00:07 1970 +0000
233 summary: f
233 summary: f
234
234
235
235
236 $ hg --config progress.debug=1 --debug \
236 $ hg --config progress.debug=1 --debug \
237 > histedit 1ddb6c90f2ee --commands - 2>&1 <<EOF | \
237 > histedit 1ddb6c90f2ee --commands - 2>&1 <<EOF | \
238 > egrep 'editing|unresolved'
238 > egrep 'editing|unresolved'
239 > pick 1ddb6c90f2ee e
239 > pick 1ddb6c90f2ee e
240 > fold 10c36dd37515 f
240 > fold 10c36dd37515 f
241 > EOF
241 > EOF
242 editing: pick 1ddb6c90f2ee 4 e 1/2 changes (50.00%)
242 editing: pick 1ddb6c90f2ee 4 e 1/2 changes (50.00%)
243 editing: fold 10c36dd37515 5 f 2/2 changes (100.00%)
243 editing: fold 10c36dd37515 5 f 2/2 changes (100.00%)
244
244
245 tip after edit, which should use the later date, from the second changeset
245 tip after edit, which should use the later date, from the second changeset
246 $ hg log --rev .
246 $ hg log --rev .
247 changeset: 4:e4f3ec5d0b40
247 changeset: 4:e4f3ec5d0b40
248 tag: tip
248 tag: tip
249 user: test
249 user: test
250 date: Thu Jan 01 00:00:07 1970 +0000
250 date: Thu Jan 01 00:00:07 1970 +0000
251 summary: e
251 summary: e
252
252
253
253
254 $ cd ..
254 $ cd ..
255 $ rm -r r
255 $ rm -r r
256
256
257 folding and creating no new change doesn't break:
257 folding and creating no new change doesn't break:
258 -------------------------------------------------
258 -------------------------------------------------
259
259
260 folded content is dropped during a merge. The folded commit should properly disappear.
260 folded content is dropped during a merge. The folded commit should properly disappear.
261
261
262 $ mkdir fold-to-empty-test
262 $ mkdir fold-to-empty-test
263 $ cd fold-to-empty-test
263 $ cd fold-to-empty-test
264 $ hg init
264 $ hg init
265 $ printf "1\n2\n3\n" > file
265 $ printf "1\n2\n3\n" > file
266 $ hg add file
266 $ hg add file
267 $ hg commit -m '1+2+3'
267 $ hg commit -m '1+2+3'
268 $ echo 4 >> file
268 $ echo 4 >> file
269 $ hg commit -m '+4'
269 $ hg commit -m '+4'
270 $ echo 5 >> file
270 $ echo 5 >> file
271 $ hg commit -m '+5'
271 $ hg commit -m '+5'
272 $ echo 6 >> file
272 $ echo 6 >> file
273 $ hg commit -m '+6'
273 $ hg commit -m '+6'
274 $ hg logt --graph
274 $ hg logt --graph
275 @ 3:251d831eeec5 +6
275 @ 3:251d831eeec5 +6
276 |
276 |
277 o 2:888f9082bf99 +5
277 o 2:888f9082bf99 +5
278 |
278 |
279 o 1:617f94f13c0f +4
279 o 1:617f94f13c0f +4
280 |
280 |
281 o 0:0189ba417d34 1+2+3
281 o 0:0189ba417d34 1+2+3
282
282
283
283
284 $ hg histedit 1 --commands - << EOF
284 $ hg histedit 1 --commands - << EOF
285 > pick 617f94f13c0f 1 +4
285 > pick 617f94f13c0f 1 +4
286 > drop 888f9082bf99 2 +5
286 > drop 888f9082bf99 2 +5
287 > fold 251d831eeec5 3 +6
287 > fold 251d831eeec5 3 +6
288 > EOF
288 > EOF
289 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
289 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 merging file
290 merging file
291 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
291 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
292 Fix up the change (fold 251d831eeec5)
292 Fix up the change (fold 251d831eeec5)
293 (hg histedit --continue to resume)
293 (hg histedit --continue to resume)
294 [1]
294 [1]
295 There were conflicts, we keep P1 content. This
295 There were conflicts, we keep P1 content. This
296 should effectively drop the changes from +6.
296 should effectively drop the changes from +6.
297 $ hg status
297 $ hg status
298 M file
298 M file
299 ? file.orig
299 ? file.orig
300 $ hg resolve -l
300 $ hg resolve -l
301 U file
301 U file
302 $ hg revert -r 'p1()' file
302 $ hg revert -r 'p1()' file
303 $ hg resolve --mark file
303 $ hg resolve --mark file
304 (no more unresolved files)
304 (no more unresolved files)
305 continue: hg histedit --continue
305 continue: hg histedit --continue
306 $ hg histedit --continue
306 $ hg histedit --continue
307 251d831eeec5: empty changeset
307 251d831eeec5: empty changeset
308 saved backup bundle to $TESTTMP/*-backup.hg (glob)
308 saved backup bundle to $TESTTMP/*-backup.hg (glob)
309 $ hg logt --graph
309 $ hg logt --graph
310 @ 1:617f94f13c0f +4
310 @ 1:617f94f13c0f +4
311 |
311 |
312 o 0:0189ba417d34 1+2+3
312 o 0:0189ba417d34 1+2+3
313
313
314
314
315 $ cd ..
315 $ cd ..
316
316
317
317
318 Test fold through dropped
318 Test fold through dropped
319 -------------------------
319 -------------------------
320
320
321
321
322 Test corner case where folded revision is separated from its parent by a
322 Test corner case where folded revision is separated from its parent by a
323 dropped revision.
323 dropped revision.
324
324
325
325
326 $ hg init fold-with-dropped
326 $ hg init fold-with-dropped
327 $ cd fold-with-dropped
327 $ cd fold-with-dropped
328 $ printf "1\n2\n3\n" > file
328 $ printf "1\n2\n3\n" > file
329 $ hg commit -Am '1+2+3'
329 $ hg commit -Am '1+2+3'
330 adding file
330 adding file
331 $ echo 4 >> file
331 $ echo 4 >> file
332 $ hg commit -m '+4'
332 $ hg commit -m '+4'
333 $ echo 5 >> file
333 $ echo 5 >> file
334 $ hg commit -m '+5'
334 $ hg commit -m '+5'
335 $ echo 6 >> file
335 $ echo 6 >> file
336 $ hg commit -m '+6'
336 $ hg commit -m '+6'
337 $ hg logt -G
337 $ hg logt -G
338 @ 3:251d831eeec5 +6
338 @ 3:251d831eeec5 +6
339 |
339 |
340 o 2:888f9082bf99 +5
340 o 2:888f9082bf99 +5
341 |
341 |
342 o 1:617f94f13c0f +4
342 o 1:617f94f13c0f +4
343 |
343 |
344 o 0:0189ba417d34 1+2+3
344 o 0:0189ba417d34 1+2+3
345
345
346 $ hg histedit 1 --commands - << EOF
346 $ hg histedit 1 --commands - << EOF
347 > pick 617f94f13c0f 1 +4
347 > pick 617f94f13c0f 1 +4
348 > drop 888f9082bf99 2 +5
348 > drop 888f9082bf99 2 +5
349 > fold 251d831eeec5 3 +6
349 > fold 251d831eeec5 3 +6
350 > EOF
350 > EOF
351 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
352 merging file
352 merging file
353 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
353 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
354 Fix up the change (fold 251d831eeec5)
354 Fix up the change (fold 251d831eeec5)
355 (hg histedit --continue to resume)
355 (hg histedit --continue to resume)
356 [1]
356 [1]
357 $ cat > file << EOF
357 $ cat > file << EOF
358 > 1
358 > 1
359 > 2
359 > 2
360 > 3
360 > 3
361 > 4
361 > 4
362 > 5
362 > 5
363 > EOF
363 > EOF
364 $ hg resolve --mark file
364 $ hg resolve --mark file
365 (no more unresolved files)
365 (no more unresolved files)
366 continue: hg histedit --continue
366 continue: hg histedit --continue
367 $ hg commit -m '+5.2'
367 $ hg commit -m '+5.2'
368 created new head
368 created new head
369 $ echo 6 >> file
369 $ echo 6 >> file
370 $ HGEDITOR=cat hg histedit --continue
370 $ HGEDITOR=cat hg histedit --continue
371 +4
371 +4
372 ***
372 ***
373 +5.2
373 +5.2
374 ***
374 ***
375 +6
375 +6
376
376
377
377
378
378
379 HG: Enter commit message. Lines beginning with 'HG:' are removed.
379 HG: Enter commit message. Lines beginning with 'HG:' are removed.
380 HG: Leave message empty to abort commit.
380 HG: Leave message empty to abort commit.
381 HG: --
381 HG: --
382 HG: user: test
382 HG: user: test
383 HG: branch 'default'
383 HG: branch 'default'
384 HG: changed file
384 HG: changed file
385 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/55c8d8dc79ce-4066cd98-backup.hg (glob)
385 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/55c8d8dc79ce-4066cd98-backup.hg (glob)
386 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-a35700fc-backup.hg (glob)
386 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-a35700fc-backup.hg (glob)
387 $ hg logt -G
387 $ hg logt -G
388 @ 1:10c647b2cdd5 +4
388 @ 1:10c647b2cdd5 +4
389 |
389 |
390 o 0:0189ba417d34 1+2+3
390 o 0:0189ba417d34 1+2+3
391
391
392 $ hg export tip
392 $ hg export tip
393 # HG changeset patch
393 # HG changeset patch
394 # User test
394 # User test
395 # Date 0 0
395 # Date 0 0
396 # Thu Jan 01 00:00:00 1970 +0000
396 # Thu Jan 01 00:00:00 1970 +0000
397 # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
397 # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
398 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
398 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
399 +4
399 +4
400 ***
400 ***
401 +5.2
401 +5.2
402 ***
402 ***
403 +6
403 +6
404
404
405 diff -r 0189ba417d34 -r 10c647b2cdd5 file
405 diff -r 0189ba417d34 -r 10c647b2cdd5 file
406 --- a/file Thu Jan 01 00:00:00 1970 +0000
406 --- a/file Thu Jan 01 00:00:00 1970 +0000
407 +++ b/file Thu Jan 01 00:00:00 1970 +0000
407 +++ b/file Thu Jan 01 00:00:00 1970 +0000
408 @@ -1,3 +1,6 @@
408 @@ -1,3 +1,6 @@
409 1
409 1
410 2
410 2
411 3
411 3
412 +4
412 +4
413 +5
413 +5
414 +6
414 +6
415 $ cd ..
415 $ cd ..
416
416
417
417
418 Folding with initial rename (issue3729)
418 Folding with initial rename (issue3729)
419 ---------------------------------------
419 ---------------------------------------
420
420
421 $ hg init fold-rename
421 $ hg init fold-rename
422 $ cd fold-rename
422 $ cd fold-rename
423 $ echo a > a.txt
423 $ echo a > a.txt
424 $ hg add a.txt
424 $ hg add a.txt
425 $ hg commit -m a
425 $ hg commit -m a
426 $ hg rename a.txt b.txt
426 $ hg rename a.txt b.txt
427 $ hg commit -m rename
427 $ hg commit -m rename
428 $ echo b >> b.txt
428 $ echo b >> b.txt
429 $ hg commit -m b
429 $ hg commit -m b
430
430
431 $ hg logt --follow b.txt
431 $ hg logt --follow b.txt
432 2:e0371e0426bc b
432 2:e0371e0426bc b
433 1:1c4f440a8085 rename
433 1:1c4f440a8085 rename
434 0:6c795aa153cb a
434 0:6c795aa153cb a
435
435
436 $ hg histedit 1c4f440a8085 --commands - 2>&1 << EOF | fixbundle
436 $ hg histedit 1c4f440a8085 --commands - 2>&1 << EOF | fixbundle
437 > pick 1c4f440a8085 rename
437 > pick 1c4f440a8085 rename
438 > fold e0371e0426bc b
438 > fold e0371e0426bc b
439 > EOF
439 > EOF
440
440
441 $ hg logt --follow b.txt
441 $ hg logt --follow b.txt
442 1:cf858d235c76 rename
442 1:cf858d235c76 rename
443 0:6c795aa153cb a
443 0:6c795aa153cb a
444
444
445 $ cd ..
445 $ cd ..
446
446
447 Folding with swapping
447 Folding with swapping
448 ---------------------
448 ---------------------
449
449
450 This is an excuse to test hook with histedit temporary commit (issue4422)
450 This is an excuse to test hook with histedit temporary commit (issue4422)
451
451
452
452
453 $ hg init issue4422
453 $ hg init issue4422
454 $ cd issue4422
454 $ cd issue4422
455 $ echo a > a.txt
455 $ echo a > a.txt
456 $ hg add a.txt
456 $ hg add a.txt
457 $ hg commit -m a
457 $ hg commit -m a
458 $ echo b > b.txt
458 $ echo b > b.txt
459 $ hg add b.txt
459 $ hg add b.txt
460 $ hg commit -m b
460 $ hg commit -m b
461 $ echo c > c.txt
461 $ echo c > c.txt
462 $ hg add c.txt
462 $ hg add c.txt
463 $ hg commit -m c
463 $ hg commit -m c
464
464
465 $ hg logt
465 $ hg logt
466 2:a1a953ffb4b0 c
466 2:a1a953ffb4b0 c
467 1:199b6bb90248 b
467 1:199b6bb90248 b
468 0:6c795aa153cb a
468 0:6c795aa153cb a
469
469
470 Setup the proper environment variable symbol for the platform, to be subbed
470 Setup the proper environment variable symbol for the platform, to be subbed
471 into the hook command.
471 into the hook command.
472 #if windows
472 #if windows
473 $ NODE="%HG_NODE%"
473 $ NODE="%HG_NODE%"
474 #else
474 #else
475 $ NODE="\$HG_NODE"
475 $ NODE="\$HG_NODE"
476 #endif
476 #endif
477 $ hg histedit 6c795aa153cb --config hooks.commit="echo commit $NODE" --commands - 2>&1 << EOF | fixbundle
477 $ hg histedit 6c795aa153cb --config hooks.commit="echo commit $NODE" --commands - 2>&1 << EOF | fixbundle
478 > pick 199b6bb90248 b
478 > pick 199b6bb90248 b
479 > fold a1a953ffb4b0 c
479 > fold a1a953ffb4b0 c
480 > pick 6c795aa153cb a
480 > pick 6c795aa153cb a
481 > EOF
481 > EOF
482 commit 9599899f62c05f4377548c32bf1c9f1a39634b0c
482 commit 9599899f62c05f4377548c32bf1c9f1a39634b0c
483
483
484 $ hg logt
484 $ hg logt
485 1:9599899f62c0 a
485 1:9599899f62c0 a
486 0:79b99e9c8e49 b
486 0:79b99e9c8e49 b
487
487
488 $ echo "foo" > amended.txt
488 $ echo "foo" > amended.txt
489 $ hg add amended.txt
489 $ hg add amended.txt
490 $ hg ci -q --config extensions.largefiles= --amend -I amended.txt
490 $ hg ci -q --config extensions.largefiles= --amend -I amended.txt
491
491
492 Test that folding multiple changes in a row doesn't show multiple
492 Test that folding multiple changes in a row doesn't show multiple
493 editors.
493 editors.
494
494
495 $ echo foo >> foo
495 $ echo foo >> foo
496 $ hg add foo
496 $ hg add foo
497 $ hg ci -m foo1
497 $ hg ci -m foo1
498 $ echo foo >> foo
498 $ echo foo >> foo
499 $ hg ci -m foo2
499 $ hg ci -m foo2
500 $ echo foo >> foo
500 $ echo foo >> foo
501 $ hg ci -m foo3
501 $ hg ci -m foo3
502 $ hg logt
502 $ hg logt
503 4:21679ff7675c foo3
503 4:21679ff7675c foo3
504 3:b7389cc4d66e foo2
504 3:b7389cc4d66e foo2
505 2:0e01aeef5fa8 foo1
505 2:0e01aeef5fa8 foo1
506 1:578c7455730c a
506 1:578c7455730c a
507 0:79b99e9c8e49 b
507 0:79b99e9c8e49 b
508 $ cat > "$TESTTMP/editor.sh" <<EOF
508 $ cat > "$TESTTMP/editor.sh" <<EOF
509 > echo ran editor >> "$TESTTMP/editorlog.txt"
509 > echo ran editor >> "$TESTTMP/editorlog.txt"
510 > cat \$1 >> "$TESTTMP/editorlog.txt"
510 > cat \$1 >> "$TESTTMP/editorlog.txt"
511 > echo END >> "$TESTTMP/editorlog.txt"
511 > echo END >> "$TESTTMP/editorlog.txt"
512 > echo merged foos > \$1
512 > echo merged foos > \$1
513 > EOF
513 > EOF
514 $ HGEDITOR="sh \"$TESTTMP/editor.sh\"" hg histedit 1 --commands - 2>&1 <<EOF | fixbundle
514 $ HGEDITOR="sh \"$TESTTMP/editor.sh\"" hg histedit 1 --commands - 2>&1 <<EOF | fixbundle
515 > pick 578c7455730c 1 a
515 > pick 578c7455730c 1 a
516 > pick 0e01aeef5fa8 2 foo1
516 > pick 0e01aeef5fa8 2 foo1
517 > fold b7389cc4d66e 3 foo2
517 > fold b7389cc4d66e 3 foo2
518 > fold 21679ff7675c 4 foo3
518 > fold 21679ff7675c 4 foo3
519 > EOF
519 > EOF
520 $ hg logt
520 $ hg logt
521 2:e8bedbda72c1 merged foos
521 2:e8bedbda72c1 merged foos
522 1:578c7455730c a
522 1:578c7455730c a
523 0:79b99e9c8e49 b
523 0:79b99e9c8e49 b
524 Editor should have run only once
524 Editor should have run only once
525 $ cat $TESTTMP/editorlog.txt
525 $ cat $TESTTMP/editorlog.txt
526 ran editor
526 ran editor
527 foo1
527 foo1
528 ***
528 ***
529 foo2
529 foo2
530 ***
530 ***
531 foo3
531 foo3
532
532
533
533
534
534
535 HG: Enter commit message. Lines beginning with 'HG:' are removed.
535 HG: Enter commit message. Lines beginning with 'HG:' are removed.
536 HG: Leave message empty to abort commit.
536 HG: Leave message empty to abort commit.
537 HG: --
537 HG: --
538 HG: user: test
538 HG: user: test
539 HG: branch 'default'
539 HG: branch 'default'
540 HG: added foo
540 HG: added foo
541 END
541 END
542
542
543 $ cd ..
543 $ cd ..
@@ -1,505 +1,505
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 Test that histedit learns about obsolescence not stored in histedit state
17 Test that histedit learns about obsolescence not stored in histedit state
18 $ hg init boo
18 $ hg init boo
19 $ cd boo
19 $ cd boo
20 $ echo a > a
20 $ echo a > a
21 $ hg ci -Am a
21 $ hg ci -Am a
22 adding a
22 adding a
23 $ echo a > b
23 $ echo a > b
24 $ echo a > c
24 $ echo a > c
25 $ echo a > c
25 $ echo a > c
26 $ hg ci -Am b
26 $ hg ci -Am b
27 adding b
27 adding b
28 adding c
28 adding c
29 $ echo a > d
29 $ echo a > d
30 $ hg ci -Am c
30 $ hg ci -Am c
31 adding d
31 adding d
32 $ echo "pick `hg log -r 0 -T '{node|short}'`" > plan
32 $ echo "pick `hg log -r 0 -T '{node|short}'`" > plan
33 $ echo "pick `hg log -r 2 -T '{node|short}'`" >> plan
33 $ echo "pick `hg log -r 2 -T '{node|short}'`" >> plan
34 $ echo "edit `hg log -r 1 -T '{node|short}'`" >> plan
34 $ echo "edit `hg log -r 1 -T '{node|short}'`" >> plan
35 $ hg histedit -r 'all()' --commands plan
35 $ hg histedit -r 'all()' --commands plan
36 Editing (1b2d564fad96), you may commit or record as needed now.
36 Editing (1b2d564fad96), you may commit or record as needed now.
37 (hg histedit --continue to resume)
37 (hg histedit --continue to resume)
38 [1]
38 [1]
39 $ hg st
39 $ hg st
40 A b
40 A b
41 A c
41 A c
42 ? plan
42 ? plan
43 $ hg commit --amend b
43 $ hg commit --amend b
44 $ hg histedit --continue
44 $ hg histedit --continue
45 $ hg log -G
45 $ hg log -G
46 @ 6:46abc7c4d873 b
46 @ 6:46abc7c4d873 b
47 |
47 |
48 o 5:49d44ab2be1b c
48 o 5:49d44ab2be1b c
49 |
49 |
50 o 0:cb9a9f314b8b a
50 o 0:cb9a9f314b8b a
51
51
52 $ hg debugobsolete
52 $ hg debugobsolete
53 e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
53 e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
54 3e30a45cf2f719e96ab3922dfe039cfd047956ce 0 {e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf} (*) {'user': 'test'} (glob)
54 3e30a45cf2f719e96ab3922dfe039cfd047956ce 0 {e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf} (*) {'user': 'test'} (glob)
55 1b2d564fad96311b45362f17c2aa855150efb35f 46abc7c4d8738e8563e577f7889e1b6db3da4199 0 (*) {'user': 'test'} (glob)
55 1b2d564fad96311b45362f17c2aa855150efb35f 46abc7c4d8738e8563e577f7889e1b6db3da4199 0 (*) {'user': 'test'} (glob)
56 114f4176969ef342759a8a57e6bccefc4234829b 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
56 114f4176969ef342759a8a57e6bccefc4234829b 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
57
57
58 With some node gone missing during the edit.
58 With some node gone missing during the edit.
59
59
60 $ echo "pick `hg log -r 0 -T '{node|short}'`" > plan
60 $ echo "pick `hg log -r 0 -T '{node|short}'`" > plan
61 $ echo "pick `hg log -r 6 -T '{node|short}'`" >> plan
61 $ echo "pick `hg log -r 6 -T '{node|short}'`" >> plan
62 $ echo "edit `hg log -r 5 -T '{node|short}'`" >> plan
62 $ echo "edit `hg log -r 5 -T '{node|short}'`" >> plan
63 $ hg histedit -r 'all()' --commands plan
63 $ hg histedit -r 'all()' --commands plan
64 Editing (49d44ab2be1b), you may commit or record as needed now.
64 Editing (49d44ab2be1b), you may commit or record as needed now.
65 (hg histedit --continue to resume)
65 (hg histedit --continue to resume)
66 [1]
66 [1]
67 $ hg st
67 $ hg st
68 A b
68 A b
69 A d
69 A d
70 ? plan
70 ? plan
71 $ hg commit --amend -X . -m XXXXXX
71 $ hg commit --amend -X . -m XXXXXX
72 $ hg commit --amend -X . -m b2
72 $ hg commit --amend -X . -m b2
73 $ hg --hidden --config extensions.strip= strip 'desc(XXXXXX)' --no-backup
73 $ hg --hidden --config extensions.strip= strip 'desc(XXXXXX)' --no-backup
74 $ hg histedit --continue
74 $ hg histedit --continue
75 $ hg log -G
75 $ hg log -G
76 @ 9:273c1f3b8626 c
76 @ 9:273c1f3b8626 c
77 |
77 |
78 o 8:aba7da937030 b2
78 o 8:aba7da937030 b2
79 |
79 |
80 o 0:cb9a9f314b8b a
80 o 0:cb9a9f314b8b a
81
81
82 $ hg debugobsolete
82 $ hg debugobsolete
83 e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
83 e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
84 3e30a45cf2f719e96ab3922dfe039cfd047956ce 0 {e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf} (*) {'user': 'test'} (glob)
84 3e30a45cf2f719e96ab3922dfe039cfd047956ce 0 {e72d22b19f8ecf4150ab4f91d0973fd9955d3ddf} (*) {'user': 'test'} (glob)
85 1b2d564fad96311b45362f17c2aa855150efb35f 46abc7c4d8738e8563e577f7889e1b6db3da4199 0 (*) {'user': 'test'} (glob)
85 1b2d564fad96311b45362f17c2aa855150efb35f 46abc7c4d8738e8563e577f7889e1b6db3da4199 0 (*) {'user': 'test'} (glob)
86 114f4176969ef342759a8a57e6bccefc4234829b 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
86 114f4176969ef342759a8a57e6bccefc4234829b 49d44ab2be1b67a79127568a67c9c99430633b48 0 (*) {'user': 'test'} (glob)
87 76f72745eac0643d16530e56e2f86e36e40631f1 2ca853e48edbd6453a0674dc0fe28a0974c51b9c 0 (*) {'user': 'test'} (glob)
87 76f72745eac0643d16530e56e2f86e36e40631f1 2ca853e48edbd6453a0674dc0fe28a0974c51b9c 0 (*) {'user': 'test'} (glob)
88 2ca853e48edbd6453a0674dc0fe28a0974c51b9c aba7da93703075eec9fb1dbaf143ff2bc1c49d46 0 (*) {'user': 'test'} (glob)
88 2ca853e48edbd6453a0674dc0fe28a0974c51b9c aba7da93703075eec9fb1dbaf143ff2bc1c49d46 0 (*) {'user': 'test'} (glob)
89 49d44ab2be1b67a79127568a67c9c99430633b48 273c1f3b86267ed3ec684bb13af1fa4d6ba56e02 0 (*) {'user': 'test'} (glob)
89 49d44ab2be1b67a79127568a67c9c99430633b48 273c1f3b86267ed3ec684bb13af1fa4d6ba56e02 0 (*) {'user': 'test'} (glob)
90 46abc7c4d8738e8563e577f7889e1b6db3da4199 aba7da93703075eec9fb1dbaf143ff2bc1c49d46 0 (*) {'user': 'test'} (glob)
90 46abc7c4d8738e8563e577f7889e1b6db3da4199 aba7da93703075eec9fb1dbaf143ff2bc1c49d46 0 (*) {'user': 'test'} (glob)
91 $ cd ..
91 $ cd ..
92
92
93 Base setup for the rest of the testing
93 Base setup for the rest of the testing
94 ======================================
94 ======================================
95
95
96 $ hg init base
96 $ hg init base
97 $ cd base
97 $ cd base
98
98
99 $ for x in a b c d e f ; do
99 $ for x in a b c d e f ; do
100 > echo $x > $x
100 > echo $x > $x
101 > hg add $x
101 > hg add $x
102 > hg ci -m $x
102 > hg ci -m $x
103 > done
103 > done
104
104
105 $ hg log --graph
105 $ hg log --graph
106 @ 5:652413bf663e f
106 @ 5:652413bf663e f
107 |
107 |
108 o 4:e860deea161a e
108 o 4:e860deea161a e
109 |
109 |
110 o 3:055a42cdd887 d
110 o 3:055a42cdd887 d
111 |
111 |
112 o 2:177f92b77385 c
112 o 2:177f92b77385 c
113 |
113 |
114 o 1:d2ae7f538514 b
114 o 1:d2ae7f538514 b
115 |
115 |
116 o 0:cb9a9f314b8b a
116 o 0:cb9a9f314b8b a
117
117
118
118
119 $ HGEDITOR=cat hg histedit 1
119 $ HGEDITOR=cat hg histedit 1
120 pick d2ae7f538514 1 b
120 pick d2ae7f538514 1 b
121 pick 177f92b77385 2 c
121 pick 177f92b77385 2 c
122 pick 055a42cdd887 3 d
122 pick 055a42cdd887 3 d
123 pick e860deea161a 4 e
123 pick e860deea161a 4 e
124 pick 652413bf663e 5 f
124 pick 652413bf663e 5 f
125
125
126 # Edit history between d2ae7f538514 and 652413bf663e
126 # Edit history between d2ae7f538514 and 652413bf663e
127 #
127 #
128 # Commits are listed from least to most recent
128 # Commits are listed from least to most recent
129 #
129 #
130 # You can reorder changesets by reordering the lines
130 # You can reorder changesets by reordering the lines
131 #
131 #
132 # Commands:
132 # Commands:
133 #
133 #
134 # e, edit = use commit, but stop for amending
134 # e, edit = use commit, but stop for amending
135 # m, mess = edit commit message without changing commit content
135 # m, mess = edit commit message without changing commit content
136 # p, pick = use commit
136 # p, pick = use commit
137 # d, drop = remove commit from history
137 # d, drop = remove commit from history
138 # f, fold = use commit, but combine it with the one above
138 # f, fold = use commit, but combine it with the one above
139 # r, roll = like fold, but discard this commit's description
139 # r, roll = like fold, but discard this commit's description and date
140 #
140 #
141 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
141 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
142 > pick 177f92b77385 2 c
142 > pick 177f92b77385 2 c
143 > drop d2ae7f538514 1 b
143 > drop d2ae7f538514 1 b
144 > pick 055a42cdd887 3 d
144 > pick 055a42cdd887 3 d
145 > fold e860deea161a 4 e
145 > fold e860deea161a 4 e
146 > pick 652413bf663e 5 f
146 > pick 652413bf663e 5 f
147 > EOF
147 > EOF
148 [1]
148 [1]
149 $ hg log --graph --hidden
149 $ hg log --graph --hidden
150 @ 10:cacdfd884a93 f
150 @ 10:cacdfd884a93 f
151 |
151 |
152 o 9:59d9f330561f d
152 o 9:59d9f330561f d
153 |
153 |
154 | x 8:b558abc46d09 fold-temp-revision e860deea161a
154 | x 8:b558abc46d09 fold-temp-revision e860deea161a
155 | |
155 | |
156 | x 7:96e494a2d553 d
156 | x 7:96e494a2d553 d
157 |/
157 |/
158 o 6:b346ab9a313d c
158 o 6:b346ab9a313d c
159 |
159 |
160 | x 5:652413bf663e f
160 | x 5:652413bf663e f
161 | |
161 | |
162 | x 4:e860deea161a e
162 | x 4:e860deea161a e
163 | |
163 | |
164 | x 3:055a42cdd887 d
164 | x 3:055a42cdd887 d
165 | |
165 | |
166 | x 2:177f92b77385 c
166 | x 2:177f92b77385 c
167 | |
167 | |
168 | x 1:d2ae7f538514 b
168 | x 1:d2ae7f538514 b
169 |/
169 |/
170 o 0:cb9a9f314b8b a
170 o 0:cb9a9f314b8b a
171
171
172 $ hg debugobsolete
172 $ hg debugobsolete
173 96e494a2d553dd05902ba1cee1d94d4cb7b8faed 0 {b346ab9a313db8537ecf96fca3ca3ca984ef3bd7} (*) {'user': 'test'} (glob)
173 96e494a2d553dd05902ba1cee1d94d4cb7b8faed 0 {b346ab9a313db8537ecf96fca3ca3ca984ef3bd7} (*) {'user': 'test'} (glob)
174 b558abc46d09c30f57ac31e85a8a3d64d2e906e4 0 {96e494a2d553dd05902ba1cee1d94d4cb7b8faed} (*) {'user': 'test'} (glob)
174 b558abc46d09c30f57ac31e85a8a3d64d2e906e4 0 {96e494a2d553dd05902ba1cee1d94d4cb7b8faed} (*) {'user': 'test'} (glob)
175 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b} (*) {'user': 'test'} (glob)
175 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b} (*) {'user': 'test'} (glob)
176 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 (*) {'user': 'test'} (glob)
176 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 (*) {'user': 'test'} (glob)
177 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
177 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
178 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
178 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 (*) {'user': 'test'} (glob)
179 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 (*) {'user': 'test'} (glob)
179 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 (*) {'user': 'test'} (glob)
180
180
181
181
182 Ensure hidden revision does not prevent histedit
182 Ensure hidden revision does not prevent histedit
183 -------------------------------------------------
183 -------------------------------------------------
184
184
185 create an hidden revision
185 create an hidden revision
186
186
187 $ hg histedit 6 --commands - << EOF
187 $ hg histedit 6 --commands - << EOF
188 > pick b346ab9a313d 6 c
188 > pick b346ab9a313d 6 c
189 > drop 59d9f330561f 7 d
189 > drop 59d9f330561f 7 d
190 > pick cacdfd884a93 8 f
190 > pick cacdfd884a93 8 f
191 > EOF
191 > EOF
192 $ hg log --graph
192 $ hg log --graph
193 @ 11:c13eb81022ca f
193 @ 11:c13eb81022ca f
194 |
194 |
195 o 6:b346ab9a313d c
195 o 6:b346ab9a313d c
196 |
196 |
197 o 0:cb9a9f314b8b a
197 o 0:cb9a9f314b8b a
198
198
199 check hidden revision are ignored (6 have hidden children 7 and 8)
199 check hidden revision are ignored (6 have hidden children 7 and 8)
200
200
201 $ hg histedit 6 --commands - << EOF
201 $ hg histedit 6 --commands - << EOF
202 > pick b346ab9a313d 6 c
202 > pick b346ab9a313d 6 c
203 > pick c13eb81022ca 8 f
203 > pick c13eb81022ca 8 f
204 > EOF
204 > EOF
205
205
206
206
207
207
208 Test that rewriting leaving instability behind is allowed
208 Test that rewriting leaving instability behind is allowed
209 ---------------------------------------------------------------------
209 ---------------------------------------------------------------------
210
210
211 $ hg up '.^'
211 $ hg up '.^'
212 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
212 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
213 $ hg log -r 'children(.)'
213 $ hg log -r 'children(.)'
214 11:c13eb81022ca f (no-eol)
214 11:c13eb81022ca f (no-eol)
215 $ hg histedit -r '.' --commands - <<EOF
215 $ hg histedit -r '.' --commands - <<EOF
216 > edit b346ab9a313d 6 c
216 > edit b346ab9a313d 6 c
217 > EOF
217 > EOF
218 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
218 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
219 adding c
219 adding c
220 Editing (b346ab9a313d), you may commit or record as needed now.
220 Editing (b346ab9a313d), you may commit or record as needed now.
221 (hg histedit --continue to resume)
221 (hg histedit --continue to resume)
222 [1]
222 [1]
223 $ echo c >> c
223 $ echo c >> c
224 $ hg histedit --continue
224 $ hg histedit --continue
225
225
226 $ hg log -r 'unstable()'
226 $ hg log -r 'unstable()'
227 11:c13eb81022ca f (no-eol)
227 11:c13eb81022ca f (no-eol)
228
228
229 stabilise
229 stabilise
230
230
231 $ hg rebase -r 'unstable()' -d .
231 $ hg rebase -r 'unstable()' -d .
232 rebasing 11:c13eb81022ca "f"
232 rebasing 11:c13eb81022ca "f"
233 $ hg up tip -q
233 $ hg up tip -q
234
234
235 Test dropping of changeset on the top of the stack
235 Test dropping of changeset on the top of the stack
236 -------------------------------------------------------
236 -------------------------------------------------------
237
237
238 Nothing is rewritten below, the working directory parent must be change for the
238 Nothing is rewritten below, the working directory parent must be change for the
239 dropped changeset to be hidden.
239 dropped changeset to be hidden.
240
240
241 $ cd ..
241 $ cd ..
242 $ hg clone base droplast
242 $ hg clone base droplast
243 updating to branch default
243 updating to branch default
244 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
244 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 $ cd droplast
245 $ cd droplast
246 $ hg histedit -r '40db8afa467b' --commands - << EOF
246 $ hg histedit -r '40db8afa467b' --commands - << EOF
247 > pick 40db8afa467b 10 c
247 > pick 40db8afa467b 10 c
248 > drop b449568bf7fc 11 f
248 > drop b449568bf7fc 11 f
249 > EOF
249 > EOF
250 $ hg log -G
250 $ hg log -G
251 @ 12:40db8afa467b c
251 @ 12:40db8afa467b c
252 |
252 |
253 o 0:cb9a9f314b8b a
253 o 0:cb9a9f314b8b a
254
254
255
255
256 With rewritten ancestors
256 With rewritten ancestors
257
257
258 $ echo e > e
258 $ echo e > e
259 $ hg add e
259 $ hg add e
260 $ hg commit -m g
260 $ hg commit -m g
261 $ echo f > f
261 $ echo f > f
262 $ hg add f
262 $ hg add f
263 $ hg commit -m h
263 $ hg commit -m h
264 $ hg histedit -r '40db8afa467b' --commands - << EOF
264 $ hg histedit -r '40db8afa467b' --commands - << EOF
265 > pick 47a8561c0449 12 g
265 > pick 47a8561c0449 12 g
266 > pick 40db8afa467b 10 c
266 > pick 40db8afa467b 10 c
267 > drop 1b3b05f35ff0 13 h
267 > drop 1b3b05f35ff0 13 h
268 > EOF
268 > EOF
269 $ hg log -G
269 $ hg log -G
270 @ 17:ee6544123ab8 c
270 @ 17:ee6544123ab8 c
271 |
271 |
272 o 16:269e713e9eae g
272 o 16:269e713e9eae g
273 |
273 |
274 o 0:cb9a9f314b8b a
274 o 0:cb9a9f314b8b a
275
275
276 $ cd ../base
276 $ cd ../base
277
277
278
278
279
279
280 Test phases support
280 Test phases support
281 ===========================================
281 ===========================================
282
282
283 Check that histedit respect immutability
283 Check that histedit respect immutability
284 -------------------------------------------
284 -------------------------------------------
285
285
286 $ cat >> $HGRCPATH << EOF
286 $ cat >> $HGRCPATH << EOF
287 > [ui]
287 > [ui]
288 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
288 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
289 > EOF
289 > EOF
290
290
291 $ hg ph -pv '.^'
291 $ hg ph -pv '.^'
292 phase changed for 2 changesets
292 phase changed for 2 changesets
293 $ hg log -G
293 $ hg log -G
294 @ 13:b449568bf7fc (draft) f
294 @ 13:b449568bf7fc (draft) f
295 |
295 |
296 o 12:40db8afa467b (public) c
296 o 12:40db8afa467b (public) c
297 |
297 |
298 o 0:cb9a9f314b8b (public) a
298 o 0:cb9a9f314b8b (public) a
299
299
300 $ hg histedit -r '.~2'
300 $ hg histedit -r '.~2'
301 abort: cannot edit public changeset: cb9a9f314b8b
301 abort: cannot edit public changeset: cb9a9f314b8b
302 (see 'hg help phases' for details)
302 (see 'hg help phases' for details)
303 [255]
303 [255]
304
304
305
305
306 Prepare further testing
306 Prepare further testing
307 -------------------------------------------
307 -------------------------------------------
308
308
309 $ for x in g h i j k ; do
309 $ for x in g h i j k ; do
310 > echo $x > $x
310 > echo $x > $x
311 > hg add $x
311 > hg add $x
312 > hg ci -m $x
312 > hg ci -m $x
313 > done
313 > done
314 $ hg phase --force --secret .~2
314 $ hg phase --force --secret .~2
315 $ hg log -G
315 $ hg log -G
316 @ 18:ee118ab9fa44 (secret) k
316 @ 18:ee118ab9fa44 (secret) k
317 |
317 |
318 o 17:3a6c53ee7f3d (secret) j
318 o 17:3a6c53ee7f3d (secret) j
319 |
319 |
320 o 16:b605fb7503f2 (secret) i
320 o 16:b605fb7503f2 (secret) i
321 |
321 |
322 o 15:7395e1ff83bd (draft) h
322 o 15:7395e1ff83bd (draft) h
323 |
323 |
324 o 14:6b70183d2492 (draft) g
324 o 14:6b70183d2492 (draft) g
325 |
325 |
326 o 13:b449568bf7fc (draft) f
326 o 13:b449568bf7fc (draft) f
327 |
327 |
328 o 12:40db8afa467b (public) c
328 o 12:40db8afa467b (public) c
329 |
329 |
330 o 0:cb9a9f314b8b (public) a
330 o 0:cb9a9f314b8b (public) a
331
331
332 $ cd ..
332 $ cd ..
333
333
334 simple phase conservation
334 simple phase conservation
335 -------------------------------------------
335 -------------------------------------------
336
336
337 Resulting changeset should conserve the phase of the original one whatever the
337 Resulting changeset should conserve the phase of the original one whatever the
338 phases.new-commit option is.
338 phases.new-commit option is.
339
339
340 New-commit as draft (default)
340 New-commit as draft (default)
341
341
342 $ cp -R base simple-draft
342 $ cp -R base simple-draft
343 $ cd simple-draft
343 $ cd simple-draft
344 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
344 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
345 > edit b449568bf7fc 11 f
345 > edit b449568bf7fc 11 f
346 > pick 6b70183d2492 12 g
346 > pick 6b70183d2492 12 g
347 > pick 7395e1ff83bd 13 h
347 > pick 7395e1ff83bd 13 h
348 > pick b605fb7503f2 14 i
348 > pick b605fb7503f2 14 i
349 > pick 3a6c53ee7f3d 15 j
349 > pick 3a6c53ee7f3d 15 j
350 > pick ee118ab9fa44 16 k
350 > pick ee118ab9fa44 16 k
351 > EOF
351 > EOF
352 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
352 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
353 adding f
353 adding f
354 Editing (b449568bf7fc), you may commit or record as needed now.
354 Editing (b449568bf7fc), you may commit or record as needed now.
355 (hg histedit --continue to resume)
355 (hg histedit --continue to resume)
356 [1]
356 [1]
357 $ echo f >> f
357 $ echo f >> f
358 $ hg histedit --continue
358 $ hg histedit --continue
359 $ hg log -G
359 $ hg log -G
360 @ 24:12e89af74238 (secret) k
360 @ 24:12e89af74238 (secret) k
361 |
361 |
362 o 23:636a8687b22e (secret) j
362 o 23:636a8687b22e (secret) j
363 |
363 |
364 o 22:ccaf0a38653f (secret) i
364 o 22:ccaf0a38653f (secret) i
365 |
365 |
366 o 21:11a89d1c2613 (draft) h
366 o 21:11a89d1c2613 (draft) h
367 |
367 |
368 o 20:c1dec7ca82ea (draft) g
368 o 20:c1dec7ca82ea (draft) g
369 |
369 |
370 o 19:087281e68428 (draft) f
370 o 19:087281e68428 (draft) f
371 |
371 |
372 o 12:40db8afa467b (public) c
372 o 12:40db8afa467b (public) c
373 |
373 |
374 o 0:cb9a9f314b8b (public) a
374 o 0:cb9a9f314b8b (public) a
375
375
376 $ cd ..
376 $ cd ..
377
377
378
378
379 New-commit as secret (config)
379 New-commit as secret (config)
380
380
381 $ cp -R base simple-secret
381 $ cp -R base simple-secret
382 $ cd simple-secret
382 $ cd simple-secret
383 $ cat >> .hg/hgrc << EOF
383 $ cat >> .hg/hgrc << EOF
384 > [phases]
384 > [phases]
385 > new-commit=secret
385 > new-commit=secret
386 > EOF
386 > EOF
387 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
387 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
388 > edit b449568bf7fc 11 f
388 > edit b449568bf7fc 11 f
389 > pick 6b70183d2492 12 g
389 > pick 6b70183d2492 12 g
390 > pick 7395e1ff83bd 13 h
390 > pick 7395e1ff83bd 13 h
391 > pick b605fb7503f2 14 i
391 > pick b605fb7503f2 14 i
392 > pick 3a6c53ee7f3d 15 j
392 > pick 3a6c53ee7f3d 15 j
393 > pick ee118ab9fa44 16 k
393 > pick ee118ab9fa44 16 k
394 > EOF
394 > EOF
395 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
395 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
396 adding f
396 adding f
397 Editing (b449568bf7fc), you may commit or record as needed now.
397 Editing (b449568bf7fc), you may commit or record as needed now.
398 (hg histedit --continue to resume)
398 (hg histedit --continue to resume)
399 [1]
399 [1]
400 $ echo f >> f
400 $ echo f >> f
401 $ hg histedit --continue
401 $ hg histedit --continue
402 $ hg log -G
402 $ hg log -G
403 @ 24:12e89af74238 (secret) k
403 @ 24:12e89af74238 (secret) k
404 |
404 |
405 o 23:636a8687b22e (secret) j
405 o 23:636a8687b22e (secret) j
406 |
406 |
407 o 22:ccaf0a38653f (secret) i
407 o 22:ccaf0a38653f (secret) i
408 |
408 |
409 o 21:11a89d1c2613 (draft) h
409 o 21:11a89d1c2613 (draft) h
410 |
410 |
411 o 20:c1dec7ca82ea (draft) g
411 o 20:c1dec7ca82ea (draft) g
412 |
412 |
413 o 19:087281e68428 (draft) f
413 o 19:087281e68428 (draft) f
414 |
414 |
415 o 12:40db8afa467b (public) c
415 o 12:40db8afa467b (public) c
416 |
416 |
417 o 0:cb9a9f314b8b (public) a
417 o 0:cb9a9f314b8b (public) a
418
418
419 $ cd ..
419 $ cd ..
420
420
421
421
422 Changeset reordering
422 Changeset reordering
423 -------------------------------------------
423 -------------------------------------------
424
424
425 If a secret changeset is put before a draft one, all descendant should be secret.
425 If a secret changeset is put before a draft one, all descendant should be secret.
426 It seems more important to present the secret phase.
426 It seems more important to present the secret phase.
427
427
428 $ cp -R base reorder
428 $ cp -R base reorder
429 $ cd reorder
429 $ cd reorder
430 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
430 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
431 > pick b449568bf7fc 11 f
431 > pick b449568bf7fc 11 f
432 > pick 3a6c53ee7f3d 15 j
432 > pick 3a6c53ee7f3d 15 j
433 > pick 6b70183d2492 12 g
433 > pick 6b70183d2492 12 g
434 > pick b605fb7503f2 14 i
434 > pick b605fb7503f2 14 i
435 > pick 7395e1ff83bd 13 h
435 > pick 7395e1ff83bd 13 h
436 > pick ee118ab9fa44 16 k
436 > pick ee118ab9fa44 16 k
437 > EOF
437 > EOF
438 $ hg log -G
438 $ hg log -G
439 @ 23:558246857888 (secret) k
439 @ 23:558246857888 (secret) k
440 |
440 |
441 o 22:28bd44768535 (secret) h
441 o 22:28bd44768535 (secret) h
442 |
442 |
443 o 21:d5395202aeb9 (secret) i
443 o 21:d5395202aeb9 (secret) i
444 |
444 |
445 o 20:21edda8e341b (secret) g
445 o 20:21edda8e341b (secret) g
446 |
446 |
447 o 19:5ab64f3a4832 (secret) j
447 o 19:5ab64f3a4832 (secret) j
448 |
448 |
449 o 13:b449568bf7fc (draft) f
449 o 13:b449568bf7fc (draft) f
450 |
450 |
451 o 12:40db8afa467b (public) c
451 o 12:40db8afa467b (public) c
452 |
452 |
453 o 0:cb9a9f314b8b (public) a
453 o 0:cb9a9f314b8b (public) a
454
454
455 $ cd ..
455 $ cd ..
456
456
457 Changeset folding
457 Changeset folding
458 -------------------------------------------
458 -------------------------------------------
459
459
460 Folding a secret changeset with a draft one turn the result secret (again,
460 Folding a secret changeset with a draft one turn the result secret (again,
461 better safe than sorry). Folding between same phase changeset still works
461 better safe than sorry). Folding between same phase changeset still works
462
462
463 Note that there is a few reordering in this series for more extensive test
463 Note that there is a few reordering in this series for more extensive test
464
464
465 $ cp -R base folding
465 $ cp -R base folding
466 $ cd folding
466 $ cd folding
467 $ cat >> .hg/hgrc << EOF
467 $ cat >> .hg/hgrc << EOF
468 > [phases]
468 > [phases]
469 > new-commit=secret
469 > new-commit=secret
470 > EOF
470 > EOF
471 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
471 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
472 > pick 7395e1ff83bd 13 h
472 > pick 7395e1ff83bd 13 h
473 > fold b449568bf7fc 11 f
473 > fold b449568bf7fc 11 f
474 > pick 6b70183d2492 12 g
474 > pick 6b70183d2492 12 g
475 > fold 3a6c53ee7f3d 15 j
475 > fold 3a6c53ee7f3d 15 j
476 > pick b605fb7503f2 14 i
476 > pick b605fb7503f2 14 i
477 > fold ee118ab9fa44 16 k
477 > fold ee118ab9fa44 16 k
478 > EOF
478 > EOF
479 $ hg log -G
479 $ hg log -G
480 @ 27:f9daec13fb98 (secret) i
480 @ 27:f9daec13fb98 (secret) i
481 |
481 |
482 o 24:49807617f46a (secret) g
482 o 24:49807617f46a (secret) g
483 |
483 |
484 o 21:050280826e04 (draft) h
484 o 21:050280826e04 (draft) h
485 |
485 |
486 o 12:40db8afa467b (public) c
486 o 12:40db8afa467b (public) c
487 |
487 |
488 o 0:cb9a9f314b8b (public) a
488 o 0:cb9a9f314b8b (public) a
489
489
490 $ hg co 49807617f46a
490 $ hg co 49807617f46a
491 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
491 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
492 $ echo wat >> wat
492 $ echo wat >> wat
493 $ hg add wat
493 $ hg add wat
494 $ hg ci -m 'add wat'
494 $ hg ci -m 'add wat'
495 created new head
495 created new head
496 $ hg merge f9daec13fb98
496 $ hg merge f9daec13fb98
497 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
497 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 (branch merge, don't forget to commit)
498 (branch merge, don't forget to commit)
499 $ hg ci -m 'merge'
499 $ hg ci -m 'merge'
500 $ echo not wat > wat
500 $ echo not wat > wat
501 $ hg ci -m 'modify wat'
501 $ hg ci -m 'modify wat'
502 $ hg histedit 050280826e04
502 $ hg histedit 050280826e04
503 abort: cannot edit history that contains merges
503 abort: cannot edit history that contains merges
504 [255]
504 [255]
505 $ cd ..
505 $ cd ..
@@ -1,153 +1,153
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > histedit=
3 > histedit=
4 > EOF
4 > EOF
5
5
6 $ initrepos ()
6 $ initrepos ()
7 > {
7 > {
8 > hg init r
8 > hg init r
9 > cd r
9 > cd r
10 > for x in a b c ; do
10 > for x in a b c ; do
11 > echo $x > $x
11 > echo $x > $x
12 > hg add $x
12 > hg add $x
13 > hg ci -m $x
13 > hg ci -m $x
14 > done
14 > done
15 > cd ..
15 > cd ..
16 > hg clone r r2 | grep -v updating
16 > hg clone r r2 | grep -v updating
17 > cd r2
17 > cd r2
18 > for x in d e f ; do
18 > for x in d e f ; do
19 > echo $x > $x
19 > echo $x > $x
20 > hg add $x
20 > hg add $x
21 > hg ci -m $x
21 > hg ci -m $x
22 > done
22 > done
23 > cd ..
23 > cd ..
24 > hg init r3
24 > hg init r3
25 > cd r3
25 > cd r3
26 > for x in g h i ; do
26 > for x in g h i ; do
27 > echo $x > $x
27 > echo $x > $x
28 > hg add $x
28 > hg add $x
29 > hg ci -m $x
29 > hg ci -m $x
30 > done
30 > done
31 > cd ..
31 > cd ..
32 > }
32 > }
33
33
34 $ initrepos
34 $ initrepos
35 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
35 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
36
36
37 show the edit commands offered by outgoing
37 show the edit commands offered by outgoing
38 $ cd r2
38 $ cd r2
39 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
39 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
40 pick 055a42cdd887 3 d
40 pick 055a42cdd887 3 d
41 pick e860deea161a 4 e
41 pick e860deea161a 4 e
42 pick 652413bf663e 5 f
42 pick 652413bf663e 5 f
43
43
44 # Edit history between 055a42cdd887 and 652413bf663e
44 # Edit history between 055a42cdd887 and 652413bf663e
45 #
45 #
46 # Commits are listed from least to most recent
46 # Commits are listed from least to most recent
47 #
47 #
48 # You can reorder changesets by reordering the lines
48 # You can reorder changesets by reordering the lines
49 #
49 #
50 # Commands:
50 # Commands:
51 #
51 #
52 # e, edit = use commit, but stop for amending
52 # e, edit = use commit, but stop for amending
53 # m, mess = edit commit message without changing commit content
53 # m, mess = edit commit message without changing commit content
54 # p, pick = use commit
54 # p, pick = use commit
55 # d, drop = remove commit from history
55 # d, drop = remove commit from history
56 # f, fold = use commit, but combine it with the one above
56 # f, fold = use commit, but combine it with the one above
57 # r, roll = like fold, but discard this commit's description
57 # r, roll = like fold, but discard this commit's description and date
58 #
58 #
59 $ cd ..
59 $ cd ..
60
60
61 show the error from unrelated repos
61 show the error from unrelated repos
62 $ cd r3
62 $ cd r3
63 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
63 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
64 abort: repository is unrelated
64 abort: repository is unrelated
65 [1]
65 [1]
66 $ cd ..
66 $ cd ..
67
67
68 show the error from unrelated repos
68 show the error from unrelated repos
69 $ cd r3
69 $ cd r3
70 $ HGEDITOR=cat hg histedit --force --outgoing ../r
70 $ HGEDITOR=cat hg histedit --force --outgoing ../r
71 comparing with ../r
71 comparing with ../r
72 searching for changes
72 searching for changes
73 warning: repository is unrelated
73 warning: repository is unrelated
74 pick 2a4042b45417 0 g
74 pick 2a4042b45417 0 g
75 pick 68c46b4927ce 1 h
75 pick 68c46b4927ce 1 h
76 pick 51281e65ba79 2 i
76 pick 51281e65ba79 2 i
77
77
78 # Edit history between 2a4042b45417 and 51281e65ba79
78 # Edit history between 2a4042b45417 and 51281e65ba79
79 #
79 #
80 # Commits are listed from least to most recent
80 # Commits are listed from least to most recent
81 #
81 #
82 # You can reorder changesets by reordering the lines
82 # You can reorder changesets by reordering the lines
83 #
83 #
84 # Commands:
84 # Commands:
85 #
85 #
86 # e, edit = use commit, but stop for amending
86 # e, edit = use commit, but stop for amending
87 # m, mess = edit commit message without changing commit content
87 # m, mess = edit commit message without changing commit content
88 # p, pick = use commit
88 # p, pick = use commit
89 # d, drop = remove commit from history
89 # d, drop = remove commit from history
90 # f, fold = use commit, but combine it with the one above
90 # f, fold = use commit, but combine it with the one above
91 # r, roll = like fold, but discard this commit's description
91 # r, roll = like fold, but discard this commit's description and date
92 #
92 #
93 $ cd ..
93 $ cd ..
94
94
95 test sensitivity to branch in URL:
95 test sensitivity to branch in URL:
96
96
97 $ cd r2
97 $ cd r2
98 $ hg -q update 2
98 $ hg -q update 2
99 $ hg -q branch foo
99 $ hg -q branch foo
100 $ hg commit -m 'create foo branch'
100 $ hg commit -m 'create foo branch'
101 $ HGEDITOR=cat hg histedit --outgoing '../r#foo' | grep -v comparing | grep -v searching
101 $ HGEDITOR=cat hg histedit --outgoing '../r#foo' | grep -v comparing | grep -v searching
102 pick f26599ee3441 6 create foo branch
102 pick f26599ee3441 6 create foo branch
103
103
104 # Edit history between f26599ee3441 and f26599ee3441
104 # Edit history between f26599ee3441 and f26599ee3441
105 #
105 #
106 # Commits are listed from least to most recent
106 # Commits are listed from least to most recent
107 #
107 #
108 # You can reorder changesets by reordering the lines
108 # You can reorder changesets by reordering the lines
109 #
109 #
110 # Commands:
110 # Commands:
111 #
111 #
112 # e, edit = use commit, but stop for amending
112 # e, edit = use commit, but stop for amending
113 # m, mess = edit commit message without changing commit content
113 # m, mess = edit commit message without changing commit content
114 # p, pick = use commit
114 # p, pick = use commit
115 # d, drop = remove commit from history
115 # d, drop = remove commit from history
116 # f, fold = use commit, but combine it with the one above
116 # f, fold = use commit, but combine it with the one above
117 # r, roll = like fold, but discard this commit's description
117 # r, roll = like fold, but discard this commit's description and date
118 #
118 #
119
119
120 test to check number of roots in outgoing revisions
120 test to check number of roots in outgoing revisions
121
121
122 $ hg -q outgoing -G --template '{node|short}({branch})' '../r'
122 $ hg -q outgoing -G --template '{node|short}({branch})' '../r'
123 @ f26599ee3441(foo)
123 @ f26599ee3441(foo)
124
124
125 o 652413bf663e(default)
125 o 652413bf663e(default)
126 |
126 |
127 o e860deea161a(default)
127 o e860deea161a(default)
128 |
128 |
129 o 055a42cdd887(default)
129 o 055a42cdd887(default)
130
130
131 $ HGEDITOR=cat hg -q histedit --outgoing '../r'
131 $ HGEDITOR=cat hg -q histedit --outgoing '../r'
132 abort: there are ambiguous outgoing revisions
132 abort: there are ambiguous outgoing revisions
133 (see 'hg help histedit' for more detail)
133 (see 'hg help histedit' for more detail)
134 [255]
134 [255]
135
135
136 $ hg -q update -C 2
136 $ hg -q update -C 2
137 $ echo aa >> a
137 $ echo aa >> a
138 $ hg -q commit -m 'another head on default'
138 $ hg -q commit -m 'another head on default'
139 $ hg -q outgoing -G --template '{node|short}({branch})' '../r#default'
139 $ hg -q outgoing -G --template '{node|short}({branch})' '../r#default'
140 @ 3879dc049647(default)
140 @ 3879dc049647(default)
141
141
142 o 652413bf663e(default)
142 o 652413bf663e(default)
143 |
143 |
144 o e860deea161a(default)
144 o e860deea161a(default)
145 |
145 |
146 o 055a42cdd887(default)
146 o 055a42cdd887(default)
147
147
148 $ HGEDITOR=cat hg -q histedit --outgoing '../r#default'
148 $ HGEDITOR=cat hg -q histedit --outgoing '../r#default'
149 abort: there are ambiguous outgoing revisions
149 abort: there are ambiguous outgoing revisions
150 (see 'hg help histedit' for more detail)
150 (see 'hg help histedit' for more detail)
151 [255]
151 [255]
152
152
153 $ cd ..
153 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now