##// END OF EJS Templates
histedit: shorten new fold message...
Matt Mackall -
r20511:5840da87 default
parent child Browse files
Show More
@@ -1,920 +1,920 b''
1 # histedit.py - interactive history editing for mercurial
1 # histedit.py - interactive history editing for mercurial
2 #
2 #
3 # Copyright 2009 Augie Fackler <raf@durin42.com>
3 # Copyright 2009 Augie Fackler <raf@durin42.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7 """interactive history editing
7 """interactive history editing
8
8
9 With this extension installed, Mercurial gains one new command: histedit. Usage
9 With this extension installed, Mercurial gains one new command: histedit. Usage
10 is as follows, assuming the following history::
10 is as follows, assuming the following history::
11
11
12 @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42
12 @ 3[tip] 7c2fd3b9020c 2009-04-27 18:04 -0500 durin42
13 | Add delta
13 | Add delta
14 |
14 |
15 o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42
15 o 2 030b686bedc4 2009-04-27 18:04 -0500 durin42
16 | Add gamma
16 | Add gamma
17 |
17 |
18 o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42
18 o 1 c561b4e977df 2009-04-27 18:04 -0500 durin42
19 | Add beta
19 | Add beta
20 |
20 |
21 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
21 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
22 Add alpha
22 Add alpha
23
23
24 If you were to run ``hg histedit c561b4e977df``, you would see the following
24 If you were to run ``hg histedit c561b4e977df``, you would see the following
25 file open in your editor::
25 file open in your editor::
26
26
27 pick c561b4e977df Add beta
27 pick c561b4e977df Add beta
28 pick 030b686bedc4 Add gamma
28 pick 030b686bedc4 Add gamma
29 pick 7c2fd3b9020c Add delta
29 pick 7c2fd3b9020c Add delta
30
30
31 # Edit history between c561b4e977df and 7c2fd3b9020c
31 # Edit history between c561b4e977df and 7c2fd3b9020c
32 #
32 #
33 # Commits are listed from least to most recent
33 # Commits are listed from least to most recent
34 #
34 #
35 # Commands:
35 # Commands:
36 # p, pick = use commit
36 # p, pick = use commit
37 # e, edit = use commit, but stop for amending
37 # e, edit = use commit, but stop for amending
38 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
38 # f, fold = use commit, but combine it with the one above
39 # d, drop = remove commit from history
39 # d, drop = remove commit from history
40 # m, mess = edit message without changing commit content
40 # m, mess = edit message without changing commit content
41 #
41 #
42
42
43 In this file, lines beginning with ``#`` are ignored. You must specify a rule
43 In this file, lines beginning with ``#`` are ignored. You must specify a rule
44 for each revision in your history. For example, if you had meant to add gamma
44 for each revision in your history. For example, if you had meant to add gamma
45 before beta, and then wanted to add delta in the same revision as beta, you
45 before beta, and then wanted to add delta in the same revision as beta, you
46 would reorganize the file to look like this::
46 would reorganize the file to look like this::
47
47
48 pick 030b686bedc4 Add gamma
48 pick 030b686bedc4 Add gamma
49 pick c561b4e977df Add beta
49 pick c561b4e977df Add beta
50 fold 7c2fd3b9020c Add delta
50 fold 7c2fd3b9020c Add delta
51
51
52 # Edit history between c561b4e977df and 7c2fd3b9020c
52 # Edit history between c561b4e977df and 7c2fd3b9020c
53 #
53 #
54 # Commits are listed from least to most recent
54 # Commits are listed from least to most recent
55 #
55 #
56 # Commands:
56 # Commands:
57 # p, pick = use commit
57 # p, pick = use commit
58 # e, edit = use commit, but stop for amending
58 # e, edit = use commit, but stop for amending
59 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
59 # f, fold = use commit, but combine it with the one above
60 # d, drop = remove commit from history
60 # d, drop = remove commit from history
61 # m, mess = edit message without changing commit content
61 # m, mess = edit message without changing commit content
62 #
62 #
63
63
64 At which point you close the editor and ``histedit`` starts working. When you
64 At which point you close the editor and ``histedit`` starts working. When you
65 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
65 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
66 those revisions together, offering you a chance to clean up the commit message::
66 those revisions together, offering you a chance to clean up the commit message::
67
67
68 Add beta
68 Add beta
69 ***
69 ***
70 Add delta
70 Add delta
71
71
72 Edit the commit message to your liking, then close the editor. For
72 Edit the commit message to your liking, then close the editor. For
73 this example, let's assume that the commit message was changed to
73 this example, let's assume that the commit message was changed to
74 ``Add beta and delta.`` After histedit has run and had a chance to
74 ``Add beta and delta.`` After histedit has run and had a chance to
75 remove any old or temporary revisions it needed, the history looks
75 remove any old or temporary revisions it needed, the history looks
76 like this::
76 like this::
77
77
78 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
78 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
79 | Add beta and delta.
79 | Add beta and delta.
80 |
80 |
81 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
81 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
82 | Add gamma
82 | Add gamma
83 |
83 |
84 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
84 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
85 Add alpha
85 Add alpha
86
86
87 Note that ``histedit`` does *not* remove any revisions (even its own temporary
87 Note that ``histedit`` does *not* remove any revisions (even its own temporary
88 ones) until after it has completed all the editing operations, so it will
88 ones) until after it has completed all the editing operations, so it will
89 probably perform several strip operations when it's done. For the above example,
89 probably perform several strip operations when it's done. For the above example,
90 it had to run strip twice. Strip can be slow depending on a variety of factors,
90 it had to run strip twice. Strip can be slow depending on a variety of factors,
91 so you might need to be a little patient. You can choose to keep the original
91 so you might need to be a little patient. You can choose to keep the original
92 revisions by passing the ``--keep`` flag.
92 revisions by passing the ``--keep`` flag.
93
93
94 The ``edit`` operation will drop you back to a command prompt,
94 The ``edit`` operation will drop you back to a command prompt,
95 allowing you to edit files freely, or even use ``hg record`` to commit
95 allowing you to edit files freely, or even use ``hg record`` to commit
96 some changes as a separate commit. When you're done, any remaining
96 some changes as a separate commit. When you're done, any remaining
97 uncommitted changes will be committed as well. When done, run ``hg
97 uncommitted changes will be committed as well. When done, run ``hg
98 histedit --continue`` to finish this step. You'll be prompted for a
98 histedit --continue`` to finish this step. You'll be prompted for a
99 new commit message, but the default commit message will be the
99 new commit message, but the default commit message will be the
100 original message for the ``edit`` ed revision.
100 original message for the ``edit`` ed revision.
101
101
102 The ``message`` operation will give you a chance to revise a commit
102 The ``message`` operation will give you a chance to revise a commit
103 message without changing the contents. It's a shortcut for doing
103 message without changing the contents. It's a shortcut for doing
104 ``edit`` immediately followed by `hg histedit --continue``.
104 ``edit`` immediately followed by `hg histedit --continue``.
105
105
106 If ``histedit`` encounters a conflict when moving a revision (while
106 If ``histedit`` encounters a conflict when moving a revision (while
107 handling ``pick`` or ``fold``), it'll stop in a similar manner to
107 handling ``pick`` or ``fold``), it'll stop in a similar manner to
108 ``edit`` with the difference that it won't prompt you for a commit
108 ``edit`` with the difference that it won't prompt you for a commit
109 message when done. If you decide at this point that you don't like how
109 message when done. If you decide at this point that you don't like how
110 much work it will be to rearrange history, or that you made a mistake,
110 much work it will be to rearrange history, or that you made a mistake,
111 you can use ``hg histedit --abort`` to abandon the new changes you
111 you can use ``hg histedit --abort`` to abandon the new changes you
112 have made and return to the state before you attempted to edit your
112 have made and return to the state before you attempted to edit your
113 history.
113 history.
114
114
115 If we clone the histedit-ed example repository above and add four more
115 If we clone the histedit-ed example repository above and add four more
116 changes, such that we have the following history::
116 changes, such that we have the following history::
117
117
118 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
118 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
119 | Add theta
119 | Add theta
120 |
120 |
121 o 5 140988835471 2009-04-27 18:04 -0500 stefan
121 o 5 140988835471 2009-04-27 18:04 -0500 stefan
122 | Add eta
122 | Add eta
123 |
123 |
124 o 4 122930637314 2009-04-27 18:04 -0500 stefan
124 o 4 122930637314 2009-04-27 18:04 -0500 stefan
125 | Add zeta
125 | Add zeta
126 |
126 |
127 o 3 836302820282 2009-04-27 18:04 -0500 stefan
127 o 3 836302820282 2009-04-27 18:04 -0500 stefan
128 | Add epsilon
128 | Add epsilon
129 |
129 |
130 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
130 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
131 | Add beta and delta.
131 | Add beta and delta.
132 |
132 |
133 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
133 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
134 | Add gamma
134 | Add gamma
135 |
135 |
136 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
136 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
137 Add alpha
137 Add alpha
138
138
139 If you run ``hg histedit --outgoing`` on the clone then it is the same
139 If you run ``hg histedit --outgoing`` on the clone then it is the same
140 as running ``hg histedit 836302820282``. If you need plan to push to a
140 as running ``hg histedit 836302820282``. If you need plan to push to a
141 repository that Mercurial does not detect to be related to the source
141 repository that Mercurial does not detect to be related to the source
142 repo, you can add a ``--force`` option.
142 repo, you can add a ``--force`` option.
143 """
143 """
144
144
145 try:
145 try:
146 import cPickle as pickle
146 import cPickle as pickle
147 pickle.dump # import now
147 pickle.dump # import now
148 except ImportError:
148 except ImportError:
149 import pickle
149 import pickle
150 import os
150 import os
151 import sys
151 import sys
152
152
153 from mercurial import cmdutil
153 from mercurial import cmdutil
154 from mercurial import discovery
154 from mercurial import discovery
155 from mercurial import error
155 from mercurial import error
156 from mercurial import copies
156 from mercurial import copies
157 from mercurial import context
157 from mercurial import context
158 from mercurial import hg
158 from mercurial import hg
159 from mercurial import lock as lockmod
159 from mercurial import lock as lockmod
160 from mercurial import node
160 from mercurial import node
161 from mercurial import repair
161 from mercurial import repair
162 from mercurial import scmutil
162 from mercurial import scmutil
163 from mercurial import util
163 from mercurial import util
164 from mercurial import obsolete
164 from mercurial import obsolete
165 from mercurial import merge as mergemod
165 from mercurial import merge as mergemod
166 from mercurial.lock import release
166 from mercurial.lock import release
167 from mercurial.i18n import _
167 from mercurial.i18n import _
168
168
169 cmdtable = {}
169 cmdtable = {}
170 command = cmdutil.command(cmdtable)
170 command = cmdutil.command(cmdtable)
171
171
172 testedwith = 'internal'
172 testedwith = 'internal'
173
173
174 # i18n: command names and abbreviations must remain untranslated
174 # i18n: command names and abbreviations must remain untranslated
175 editcomment = _("""# Edit history between %s and %s
175 editcomment = _("""# Edit history between %s and %s
176 #
176 #
177 # Commits are listed from least to most recent
177 # Commits are listed from least to most recent
178 #
178 #
179 # Commands:
179 # Commands:
180 # p, pick = use commit
180 # p, pick = use commit
181 # e, edit = use commit, but stop for amending
181 # e, edit = use commit, but stop for amending
182 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
182 # f, fold = use commit, but combine it with the one above
183 # d, drop = remove commit from history
183 # d, drop = remove commit from history
184 # m, mess = edit message without changing commit content
184 # m, mess = edit message without changing commit content
185 #
185 #
186 """)
186 """)
187
187
188 def commitfuncfor(repo, src):
188 def commitfuncfor(repo, src):
189 """Build a commit function for the replacement of <src>
189 """Build a commit function for the replacement of <src>
190
190
191 This function ensure we apply the same treatment to all changesets.
191 This function ensure we apply the same treatment to all changesets.
192
192
193 - Add a 'histedit_source' entry in extra.
193 - Add a 'histedit_source' entry in extra.
194
194
195 Note that fold have its own separated logic because its handling is a bit
195 Note that fold have its own separated logic because its handling is a bit
196 different and not easily factored out of the fold method.
196 different and not easily factored out of the fold method.
197 """
197 """
198 phasemin = src.phase()
198 phasemin = src.phase()
199 def commitfunc(**kwargs):
199 def commitfunc(**kwargs):
200 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
200 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
201 try:
201 try:
202 repo.ui.setconfig('phases', 'new-commit', phasemin)
202 repo.ui.setconfig('phases', 'new-commit', phasemin)
203 extra = kwargs.get('extra', {}).copy()
203 extra = kwargs.get('extra', {}).copy()
204 extra['histedit_source'] = src.hex()
204 extra['histedit_source'] = src.hex()
205 kwargs['extra'] = extra
205 kwargs['extra'] = extra
206 return repo.commit(**kwargs)
206 return repo.commit(**kwargs)
207 finally:
207 finally:
208 repo.ui.restoreconfig(phasebackup)
208 repo.ui.restoreconfig(phasebackup)
209 return commitfunc
209 return commitfunc
210
210
211
211
212
212
213 def applychanges(ui, repo, ctx, opts):
213 def applychanges(ui, repo, ctx, opts):
214 """Merge changeset from ctx (only) in the current working directory"""
214 """Merge changeset from ctx (only) in the current working directory"""
215 wcpar = repo.dirstate.parents()[0]
215 wcpar = repo.dirstate.parents()[0]
216 if ctx.p1().node() == wcpar:
216 if ctx.p1().node() == wcpar:
217 # edition ar "in place" we do not need to make any merge,
217 # edition ar "in place" we do not need to make any merge,
218 # just applies changes on parent for edition
218 # just applies changes on parent for edition
219 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
219 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
220 stats = None
220 stats = None
221 else:
221 else:
222 try:
222 try:
223 # ui.forcemerge is an internal variable, do not document
223 # ui.forcemerge is an internal variable, do not document
224 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
224 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
225 stats = mergemod.update(repo, ctx.node(), True, True, False,
225 stats = mergemod.update(repo, ctx.node(), True, True, False,
226 ctx.p1().node())
226 ctx.p1().node())
227 finally:
227 finally:
228 repo.ui.setconfig('ui', 'forcemerge', '')
228 repo.ui.setconfig('ui', 'forcemerge', '')
229 repo.setparents(wcpar, node.nullid)
229 repo.setparents(wcpar, node.nullid)
230 repo.dirstate.write()
230 repo.dirstate.write()
231 # fix up dirstate for copies and renames
231 # fix up dirstate for copies and renames
232 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
232 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
233 return stats
233 return stats
234
234
235 def collapse(repo, first, last, commitopts):
235 def collapse(repo, first, last, commitopts):
236 """collapse the set of revisions from first to last as new one.
236 """collapse the set of revisions from first to last as new one.
237
237
238 Expected commit options are:
238 Expected commit options are:
239 - message
239 - message
240 - date
240 - date
241 - username
241 - username
242 Commit message is edited in all cases.
242 Commit message is edited in all cases.
243
243
244 This function works in memory."""
244 This function works in memory."""
245 ctxs = list(repo.set('%d::%d', first, last))
245 ctxs = list(repo.set('%d::%d', first, last))
246 if not ctxs:
246 if not ctxs:
247 return None
247 return None
248 base = first.parents()[0]
248 base = first.parents()[0]
249
249
250 # commit a new version of the old changeset, including the update
250 # commit a new version of the old changeset, including the update
251 # collect all files which might be affected
251 # collect all files which might be affected
252 files = set()
252 files = set()
253 for ctx in ctxs:
253 for ctx in ctxs:
254 files.update(ctx.files())
254 files.update(ctx.files())
255
255
256 # Recompute copies (avoid recording a -> b -> a)
256 # Recompute copies (avoid recording a -> b -> a)
257 copied = copies.pathcopies(base, last)
257 copied = copies.pathcopies(base, last)
258
258
259 # prune files which were reverted by the updates
259 # prune files which were reverted by the updates
260 def samefile(f):
260 def samefile(f):
261 if f in last.manifest():
261 if f in last.manifest():
262 a = last.filectx(f)
262 a = last.filectx(f)
263 if f in base.manifest():
263 if f in base.manifest():
264 b = base.filectx(f)
264 b = base.filectx(f)
265 return (a.data() == b.data()
265 return (a.data() == b.data()
266 and a.flags() == b.flags())
266 and a.flags() == b.flags())
267 else:
267 else:
268 return False
268 return False
269 else:
269 else:
270 return f not in base.manifest()
270 return f not in base.manifest()
271 files = [f for f in files if not samefile(f)]
271 files = [f for f in files if not samefile(f)]
272 # commit version of these files as defined by head
272 # commit version of these files as defined by head
273 headmf = last.manifest()
273 headmf = last.manifest()
274 def filectxfn(repo, ctx, path):
274 def filectxfn(repo, ctx, path):
275 if path in headmf:
275 if path in headmf:
276 fctx = last[path]
276 fctx = last[path]
277 flags = fctx.flags()
277 flags = fctx.flags()
278 mctx = context.memfilectx(fctx.path(), fctx.data(),
278 mctx = context.memfilectx(fctx.path(), fctx.data(),
279 islink='l' in flags,
279 islink='l' in flags,
280 isexec='x' in flags,
280 isexec='x' in flags,
281 copied=copied.get(path))
281 copied=copied.get(path))
282 return mctx
282 return mctx
283 raise IOError()
283 raise IOError()
284
284
285 if commitopts.get('message'):
285 if commitopts.get('message'):
286 message = commitopts['message']
286 message = commitopts['message']
287 else:
287 else:
288 message = first.description()
288 message = first.description()
289 user = commitopts.get('user')
289 user = commitopts.get('user')
290 date = commitopts.get('date')
290 date = commitopts.get('date')
291 extra = commitopts.get('extra')
291 extra = commitopts.get('extra')
292
292
293 parents = (first.p1().node(), first.p2().node())
293 parents = (first.p1().node(), first.p2().node())
294 new = context.memctx(repo,
294 new = context.memctx(repo,
295 parents=parents,
295 parents=parents,
296 text=message,
296 text=message,
297 files=files,
297 files=files,
298 filectxfn=filectxfn,
298 filectxfn=filectxfn,
299 user=user,
299 user=user,
300 date=date,
300 date=date,
301 extra=extra)
301 extra=extra)
302 new._text = cmdutil.commitforceeditor(repo, new, [])
302 new._text = cmdutil.commitforceeditor(repo, new, [])
303 return repo.commitctx(new)
303 return repo.commitctx(new)
304
304
305 def pick(ui, repo, ctx, ha, opts):
305 def pick(ui, repo, ctx, ha, opts):
306 oldctx = repo[ha]
306 oldctx = repo[ha]
307 if oldctx.parents()[0] == ctx:
307 if oldctx.parents()[0] == ctx:
308 ui.debug('node %s unchanged\n' % ha)
308 ui.debug('node %s unchanged\n' % ha)
309 return oldctx, []
309 return oldctx, []
310 hg.update(repo, ctx.node())
310 hg.update(repo, ctx.node())
311 stats = applychanges(ui, repo, oldctx, opts)
311 stats = applychanges(ui, repo, oldctx, opts)
312 if stats and stats[3] > 0:
312 if stats and stats[3] > 0:
313 raise error.InterventionRequired(_('Fix up the change and run '
313 raise error.InterventionRequired(_('Fix up the change and run '
314 'hg histedit --continue'))
314 'hg histedit --continue'))
315 # drop the second merge parent
315 # drop the second merge parent
316 commit = commitfuncfor(repo, oldctx)
316 commit = commitfuncfor(repo, oldctx)
317 n = commit(text=oldctx.description(), user=oldctx.user(),
317 n = commit(text=oldctx.description(), user=oldctx.user(),
318 date=oldctx.date(), extra=oldctx.extra())
318 date=oldctx.date(), extra=oldctx.extra())
319 if n is None:
319 if n is None:
320 ui.warn(_('%s: empty changeset\n')
320 ui.warn(_('%s: empty changeset\n')
321 % node.hex(ha))
321 % node.hex(ha))
322 return ctx, []
322 return ctx, []
323 new = repo[n]
323 new = repo[n]
324 return new, [(oldctx.node(), (n,))]
324 return new, [(oldctx.node(), (n,))]
325
325
326
326
327 def edit(ui, repo, ctx, ha, opts):
327 def edit(ui, repo, ctx, ha, opts):
328 oldctx = repo[ha]
328 oldctx = repo[ha]
329 hg.update(repo, ctx.node())
329 hg.update(repo, ctx.node())
330 applychanges(ui, repo, oldctx, opts)
330 applychanges(ui, repo, oldctx, opts)
331 raise error.InterventionRequired(
331 raise error.InterventionRequired(
332 _('Make changes as needed, you may commit or record as needed now.\n'
332 _('Make changes as needed, you may commit or record as needed now.\n'
333 'When you are finished, run hg histedit --continue to resume.'))
333 'When you are finished, run hg histedit --continue to resume.'))
334
334
335 def fold(ui, repo, ctx, ha, opts):
335 def fold(ui, repo, ctx, ha, opts):
336 oldctx = repo[ha]
336 oldctx = repo[ha]
337 hg.update(repo, ctx.node())
337 hg.update(repo, ctx.node())
338 stats = applychanges(ui, repo, oldctx, opts)
338 stats = applychanges(ui, repo, oldctx, opts)
339 if stats and stats[3] > 0:
339 if stats and stats[3] > 0:
340 raise error.InterventionRequired(
340 raise error.InterventionRequired(
341 _('Fix up the change and run hg histedit --continue'))
341 _('Fix up the change and run hg histedit --continue'))
342 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
342 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
343 date=oldctx.date(), extra=oldctx.extra())
343 date=oldctx.date(), extra=oldctx.extra())
344 if n is None:
344 if n is None:
345 ui.warn(_('%s: empty changeset')
345 ui.warn(_('%s: empty changeset')
346 % node.hex(ha))
346 % node.hex(ha))
347 return ctx, []
347 return ctx, []
348 return finishfold(ui, repo, ctx, oldctx, n, opts, [])
348 return finishfold(ui, repo, ctx, oldctx, n, opts, [])
349
349
350 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
350 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
351 parent = ctx.parents()[0].node()
351 parent = ctx.parents()[0].node()
352 hg.update(repo, parent)
352 hg.update(repo, parent)
353 ### prepare new commit data
353 ### prepare new commit data
354 commitopts = opts.copy()
354 commitopts = opts.copy()
355 # username
355 # username
356 if ctx.user() == oldctx.user():
356 if ctx.user() == oldctx.user():
357 username = ctx.user()
357 username = ctx.user()
358 else:
358 else:
359 username = ui.username()
359 username = ui.username()
360 commitopts['user'] = username
360 commitopts['user'] = username
361 # commit message
361 # commit message
362 newmessage = '\n***\n'.join(
362 newmessage = '\n***\n'.join(
363 [ctx.description()] +
363 [ctx.description()] +
364 [repo[r].description() for r in internalchanges] +
364 [repo[r].description() for r in internalchanges] +
365 [oldctx.description()]) + '\n'
365 [oldctx.description()]) + '\n'
366 commitopts['message'] = newmessage
366 commitopts['message'] = newmessage
367 # date
367 # date
368 commitopts['date'] = max(ctx.date(), oldctx.date())
368 commitopts['date'] = max(ctx.date(), oldctx.date())
369 extra = ctx.extra().copy()
369 extra = ctx.extra().copy()
370 # histedit_source
370 # histedit_source
371 # note: ctx is likely a temporary commit but that the best we can do here
371 # note: ctx is likely a temporary commit but that the best we can do here
372 # This is sufficient to solve issue3681 anyway
372 # This is sufficient to solve issue3681 anyway
373 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
373 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
374 commitopts['extra'] = extra
374 commitopts['extra'] = extra
375 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
375 phasebackup = repo.ui.backupconfig('phases', 'new-commit')
376 try:
376 try:
377 phasemin = max(ctx.phase(), oldctx.phase())
377 phasemin = max(ctx.phase(), oldctx.phase())
378 repo.ui.setconfig('phases', 'new-commit', phasemin)
378 repo.ui.setconfig('phases', 'new-commit', phasemin)
379 n = collapse(repo, ctx, repo[newnode], commitopts)
379 n = collapse(repo, ctx, repo[newnode], commitopts)
380 finally:
380 finally:
381 repo.ui.restoreconfig(phasebackup)
381 repo.ui.restoreconfig(phasebackup)
382 if n is None:
382 if n is None:
383 return ctx, []
383 return ctx, []
384 hg.update(repo, n)
384 hg.update(repo, n)
385 replacements = [(oldctx.node(), (newnode,)),
385 replacements = [(oldctx.node(), (newnode,)),
386 (ctx.node(), (n,)),
386 (ctx.node(), (n,)),
387 (newnode, (n,)),
387 (newnode, (n,)),
388 ]
388 ]
389 for ich in internalchanges:
389 for ich in internalchanges:
390 replacements.append((ich, (n,)))
390 replacements.append((ich, (n,)))
391 return repo[n], replacements
391 return repo[n], replacements
392
392
393 def drop(ui, repo, ctx, ha, opts):
393 def drop(ui, repo, ctx, ha, opts):
394 return ctx, [(repo[ha].node(), ())]
394 return ctx, [(repo[ha].node(), ())]
395
395
396
396
397 def message(ui, repo, ctx, ha, opts):
397 def message(ui, repo, ctx, ha, opts):
398 oldctx = repo[ha]
398 oldctx = repo[ha]
399 hg.update(repo, ctx.node())
399 hg.update(repo, ctx.node())
400 stats = applychanges(ui, repo, oldctx, opts)
400 stats = applychanges(ui, repo, oldctx, opts)
401 if stats and stats[3] > 0:
401 if stats and stats[3] > 0:
402 raise error.InterventionRequired(
402 raise error.InterventionRequired(
403 _('Fix up the change and run hg histedit --continue'))
403 _('Fix up the change and run hg histedit --continue'))
404 message = oldctx.description() + '\n'
404 message = oldctx.description() + '\n'
405 message = ui.edit(message, ui.username())
405 message = ui.edit(message, ui.username())
406 commit = commitfuncfor(repo, oldctx)
406 commit = commitfuncfor(repo, oldctx)
407 new = commit(text=message, user=oldctx.user(), date=oldctx.date(),
407 new = commit(text=message, user=oldctx.user(), date=oldctx.date(),
408 extra=oldctx.extra())
408 extra=oldctx.extra())
409 newctx = repo[new]
409 newctx = repo[new]
410 if oldctx.node() != newctx.node():
410 if oldctx.node() != newctx.node():
411 return newctx, [(oldctx.node(), (new,))]
411 return newctx, [(oldctx.node(), (new,))]
412 # We didn't make an edit, so just indicate no replaced nodes
412 # We didn't make an edit, so just indicate no replaced nodes
413 return newctx, []
413 return newctx, []
414
414
415 def findoutgoing(ui, repo, remote=None, force=False, opts={}):
415 def findoutgoing(ui, repo, remote=None, force=False, opts={}):
416 """utility function to find the first outgoing changeset
416 """utility function to find the first outgoing changeset
417
417
418 Used by initialisation code"""
418 Used by initialisation code"""
419 dest = ui.expandpath(remote or 'default-push', remote or 'default')
419 dest = ui.expandpath(remote or 'default-push', remote or 'default')
420 dest, revs = hg.parseurl(dest, None)[:2]
420 dest, revs = hg.parseurl(dest, None)[:2]
421 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
421 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
422
422
423 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
423 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
424 other = hg.peer(repo, opts, dest)
424 other = hg.peer(repo, opts, dest)
425
425
426 if revs:
426 if revs:
427 revs = [repo.lookup(rev) for rev in revs]
427 revs = [repo.lookup(rev) for rev in revs]
428
428
429 outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
429 outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
430 if not outgoing.missing:
430 if not outgoing.missing:
431 raise util.Abort(_('no outgoing ancestors'))
431 raise util.Abort(_('no outgoing ancestors'))
432 roots = list(repo.revs("roots(%ln)", outgoing.missing))
432 roots = list(repo.revs("roots(%ln)", outgoing.missing))
433 if 1 < len(roots):
433 if 1 < len(roots):
434 msg = _('there are ambiguous outgoing revisions')
434 msg = _('there are ambiguous outgoing revisions')
435 hint = _('see "hg help histedit" for more detail')
435 hint = _('see "hg help histedit" for more detail')
436 raise util.Abort(msg, hint=hint)
436 raise util.Abort(msg, hint=hint)
437 return repo.lookup(roots[0])
437 return repo.lookup(roots[0])
438
438
439 actiontable = {'p': pick,
439 actiontable = {'p': pick,
440 'pick': pick,
440 'pick': pick,
441 'e': edit,
441 'e': edit,
442 'edit': edit,
442 'edit': edit,
443 'f': fold,
443 'f': fold,
444 'fold': fold,
444 'fold': fold,
445 'd': drop,
445 'd': drop,
446 'drop': drop,
446 'drop': drop,
447 'm': message,
447 'm': message,
448 'mess': message,
448 'mess': message,
449 }
449 }
450
450
451 @command('histedit',
451 @command('histedit',
452 [('', 'commands', '',
452 [('', 'commands', '',
453 _('Read history edits from the specified file.')),
453 _('Read history edits from the specified file.')),
454 ('c', 'continue', False, _('continue an edit already in progress')),
454 ('c', 'continue', False, _('continue an edit already in progress')),
455 ('k', 'keep', False,
455 ('k', 'keep', False,
456 _("don't strip old nodes after edit is complete")),
456 _("don't strip old nodes after edit is complete")),
457 ('', 'abort', False, _('abort an edit in progress')),
457 ('', 'abort', False, _('abort an edit in progress')),
458 ('o', 'outgoing', False, _('changesets not found in destination')),
458 ('o', 'outgoing', False, _('changesets not found in destination')),
459 ('f', 'force', False,
459 ('f', 'force', False,
460 _('force outgoing even for unrelated repositories')),
460 _('force outgoing even for unrelated repositories')),
461 ('r', 'rev', [], _('first revision to be edited'))],
461 ('r', 'rev', [], _('first revision to be edited'))],
462 _("ANCESTOR | --outgoing [URL]"))
462 _("ANCESTOR | --outgoing [URL]"))
463 def histedit(ui, repo, *freeargs, **opts):
463 def histedit(ui, repo, *freeargs, **opts):
464 """interactively edit changeset history
464 """interactively edit changeset history
465
465
466 This command edits changesets between ANCESTOR and the parent of
466 This command edits changesets between ANCESTOR and the parent of
467 the working directory.
467 the working directory.
468
468
469 With --outgoing, this edits changesets not found in the
469 With --outgoing, this edits changesets not found in the
470 destination repository. If URL of the destination is omitted, the
470 destination repository. If URL of the destination is omitted, the
471 'default-push' (or 'default') path will be used.
471 'default-push' (or 'default') path will be used.
472
472
473 For safety, this command is aborted, also if there are ambiguous
473 For safety, this command is aborted, also if there are ambiguous
474 outgoing revisions which may confuse users: for example, there are
474 outgoing revisions which may confuse users: for example, there are
475 multiple branches containing outgoing revisions.
475 multiple branches containing outgoing revisions.
476
476
477 Use "min(outgoing() and ::.)" or similar revset specification
477 Use "min(outgoing() and ::.)" or similar revset specification
478 instead of --outgoing to specify edit target revision exactly in
478 instead of --outgoing to specify edit target revision exactly in
479 such ambiguous situation. See :hg:`help revsets` for detail about
479 such ambiguous situation. See :hg:`help revsets` for detail about
480 selecting revisions.
480 selecting revisions.
481
481
482 Returns 0 on success, 1 if user intervention is required (not only
482 Returns 0 on success, 1 if user intervention is required (not only
483 for intentional "edit" command, but also for resolving unexpected
483 for intentional "edit" command, but also for resolving unexpected
484 conflicts).
484 conflicts).
485 """
485 """
486 lock = wlock = None
486 lock = wlock = None
487 try:
487 try:
488 wlock = repo.wlock()
488 wlock = repo.wlock()
489 lock = repo.lock()
489 lock = repo.lock()
490 _histedit(ui, repo, *freeargs, **opts)
490 _histedit(ui, repo, *freeargs, **opts)
491 finally:
491 finally:
492 release(lock, wlock)
492 release(lock, wlock)
493
493
494 def _histedit(ui, repo, *freeargs, **opts):
494 def _histedit(ui, repo, *freeargs, **opts):
495 # TODO only abort if we try and histedit mq patches, not just
495 # TODO only abort if we try and histedit mq patches, not just
496 # blanket if mq patches are applied somewhere
496 # blanket if mq patches are applied somewhere
497 mq = getattr(repo, 'mq', None)
497 mq = getattr(repo, 'mq', None)
498 if mq and mq.applied:
498 if mq and mq.applied:
499 raise util.Abort(_('source has mq patches applied'))
499 raise util.Abort(_('source has mq patches applied'))
500
500
501 # basic argument incompatibility processing
501 # basic argument incompatibility processing
502 outg = opts.get('outgoing')
502 outg = opts.get('outgoing')
503 cont = opts.get('continue')
503 cont = opts.get('continue')
504 abort = opts.get('abort')
504 abort = opts.get('abort')
505 force = opts.get('force')
505 force = opts.get('force')
506 rules = opts.get('commands', '')
506 rules = opts.get('commands', '')
507 revs = opts.get('rev', [])
507 revs = opts.get('rev', [])
508 goal = 'new' # This invocation goal, in new, continue, abort
508 goal = 'new' # This invocation goal, in new, continue, abort
509 if force and not outg:
509 if force and not outg:
510 raise util.Abort(_('--force only allowed with --outgoing'))
510 raise util.Abort(_('--force only allowed with --outgoing'))
511 if cont:
511 if cont:
512 if util.any((outg, abort, revs, freeargs, rules)):
512 if util.any((outg, abort, revs, freeargs, rules)):
513 raise util.Abort(_('no arguments allowed with --continue'))
513 raise util.Abort(_('no arguments allowed with --continue'))
514 goal = 'continue'
514 goal = 'continue'
515 elif abort:
515 elif abort:
516 if util.any((outg, revs, freeargs, rules)):
516 if util.any((outg, revs, freeargs, rules)):
517 raise util.Abort(_('no arguments allowed with --abort'))
517 raise util.Abort(_('no arguments allowed with --abort'))
518 goal = 'abort'
518 goal = 'abort'
519 else:
519 else:
520 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
520 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
521 raise util.Abort(_('history edit already in progress, try '
521 raise util.Abort(_('history edit already in progress, try '
522 '--continue or --abort'))
522 '--continue or --abort'))
523 if outg:
523 if outg:
524 if revs:
524 if revs:
525 raise util.Abort(_('no revisions allowed with --outgoing'))
525 raise util.Abort(_('no revisions allowed with --outgoing'))
526 if len(freeargs) > 1:
526 if len(freeargs) > 1:
527 raise util.Abort(
527 raise util.Abort(
528 _('only one repo argument allowed with --outgoing'))
528 _('only one repo argument allowed with --outgoing'))
529 else:
529 else:
530 revs.extend(freeargs)
530 revs.extend(freeargs)
531 if len(revs) != 1:
531 if len(revs) != 1:
532 raise util.Abort(
532 raise util.Abort(
533 _('histedit requires exactly one ancestor revision'))
533 _('histedit requires exactly one ancestor revision'))
534
534
535
535
536 if goal == 'continue':
536 if goal == 'continue':
537 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
537 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
538 parentctx = repo[parentctxnode]
538 parentctx = repo[parentctxnode]
539 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
539 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
540 replacements.extend(repl)
540 replacements.extend(repl)
541 elif goal == 'abort':
541 elif goal == 'abort':
542 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
542 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
543 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
543 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
544 ui.debug('restore wc to old parent %s\n' % node.short(topmost))
544 ui.debug('restore wc to old parent %s\n' % node.short(topmost))
545 # check whether we should update away
545 # check whether we should update away
546 parentnodes = [c.node() for c in repo[None].parents()]
546 parentnodes = [c.node() for c in repo[None].parents()]
547 for n in leafs | set([parentctxnode]):
547 for n in leafs | set([parentctxnode]):
548 if n in parentnodes:
548 if n in parentnodes:
549 hg.clean(repo, topmost)
549 hg.clean(repo, topmost)
550 break
550 break
551 else:
551 else:
552 pass
552 pass
553 cleanupnode(ui, repo, 'created', tmpnodes)
553 cleanupnode(ui, repo, 'created', tmpnodes)
554 cleanupnode(ui, repo, 'temp', leafs)
554 cleanupnode(ui, repo, 'temp', leafs)
555 os.unlink(os.path.join(repo.path, 'histedit-state'))
555 os.unlink(os.path.join(repo.path, 'histedit-state'))
556 return
556 return
557 else:
557 else:
558 cmdutil.checkunfinished(repo)
558 cmdutil.checkunfinished(repo)
559 cmdutil.bailifchanged(repo)
559 cmdutil.bailifchanged(repo)
560
560
561 topmost, empty = repo.dirstate.parents()
561 topmost, empty = repo.dirstate.parents()
562 if outg:
562 if outg:
563 if freeargs:
563 if freeargs:
564 remote = freeargs[0]
564 remote = freeargs[0]
565 else:
565 else:
566 remote = None
566 remote = None
567 root = findoutgoing(ui, repo, remote, force, opts)
567 root = findoutgoing(ui, repo, remote, force, opts)
568 else:
568 else:
569 root = revs[0]
569 root = revs[0]
570 root = scmutil.revsingle(repo, root).node()
570 root = scmutil.revsingle(repo, root).node()
571
571
572 keep = opts.get('keep', False)
572 keep = opts.get('keep', False)
573 revs = between(repo, root, topmost, keep)
573 revs = between(repo, root, topmost, keep)
574 if not revs:
574 if not revs:
575 raise util.Abort(_('%s is not an ancestor of working directory') %
575 raise util.Abort(_('%s is not an ancestor of working directory') %
576 node.short(root))
576 node.short(root))
577
577
578 ctxs = [repo[r] for r in revs]
578 ctxs = [repo[r] for r in revs]
579 if not rules:
579 if not rules:
580 rules = '\n'.join([makedesc(c) for c in ctxs])
580 rules = '\n'.join([makedesc(c) for c in ctxs])
581 rules += '\n\n'
581 rules += '\n\n'
582 rules += editcomment % (node.short(root), node.short(topmost))
582 rules += editcomment % (node.short(root), node.short(topmost))
583 rules = ui.edit(rules, ui.username())
583 rules = ui.edit(rules, ui.username())
584 # Save edit rules in .hg/histedit-last-edit.txt in case
584 # Save edit rules in .hg/histedit-last-edit.txt in case
585 # the user needs to ask for help after something
585 # the user needs to ask for help after something
586 # surprising happens.
586 # surprising happens.
587 f = open(repo.join('histedit-last-edit.txt'), 'w')
587 f = open(repo.join('histedit-last-edit.txt'), 'w')
588 f.write(rules)
588 f.write(rules)
589 f.close()
589 f.close()
590 else:
590 else:
591 if rules == '-':
591 if rules == '-':
592 f = sys.stdin
592 f = sys.stdin
593 else:
593 else:
594 f = open(rules)
594 f = open(rules)
595 rules = f.read()
595 rules = f.read()
596 f.close()
596 f.close()
597 rules = [l for l in (r.strip() for r in rules.splitlines())
597 rules = [l for l in (r.strip() for r in rules.splitlines())
598 if l and not l[0] == '#']
598 if l and not l[0] == '#']
599 rules = verifyrules(rules, repo, ctxs)
599 rules = verifyrules(rules, repo, ctxs)
600
600
601 parentctx = repo[root].parents()[0]
601 parentctx = repo[root].parents()[0]
602 keep = opts.get('keep', False)
602 keep = opts.get('keep', False)
603 replacements = []
603 replacements = []
604
604
605
605
606 while rules:
606 while rules:
607 writestate(repo, parentctx.node(), rules, keep, topmost, replacements)
607 writestate(repo, parentctx.node(), rules, keep, topmost, replacements)
608 action, ha = rules.pop(0)
608 action, ha = rules.pop(0)
609 ui.debug('histedit: processing %s %s\n' % (action, ha))
609 ui.debug('histedit: processing %s %s\n' % (action, ha))
610 actfunc = actiontable[action]
610 actfunc = actiontable[action]
611 parentctx, replacement_ = actfunc(ui, repo, parentctx, ha, opts)
611 parentctx, replacement_ = actfunc(ui, repo, parentctx, ha, opts)
612 replacements.extend(replacement_)
612 replacements.extend(replacement_)
613
613
614 hg.update(repo, parentctx.node())
614 hg.update(repo, parentctx.node())
615
615
616 mapping, tmpnodes, created, ntm = processreplacement(repo, replacements)
616 mapping, tmpnodes, created, ntm = processreplacement(repo, replacements)
617 if mapping:
617 if mapping:
618 for prec, succs in mapping.iteritems():
618 for prec, succs in mapping.iteritems():
619 if not succs:
619 if not succs:
620 ui.debug('histedit: %s is dropped\n' % node.short(prec))
620 ui.debug('histedit: %s is dropped\n' % node.short(prec))
621 else:
621 else:
622 ui.debug('histedit: %s is replaced by %s\n' % (
622 ui.debug('histedit: %s is replaced by %s\n' % (
623 node.short(prec), node.short(succs[0])))
623 node.short(prec), node.short(succs[0])))
624 if len(succs) > 1:
624 if len(succs) > 1:
625 m = 'histedit: %s'
625 m = 'histedit: %s'
626 for n in succs[1:]:
626 for n in succs[1:]:
627 ui.debug(m % node.short(n))
627 ui.debug(m % node.short(n))
628
628
629 if not keep:
629 if not keep:
630 if mapping:
630 if mapping:
631 movebookmarks(ui, repo, mapping, topmost, ntm)
631 movebookmarks(ui, repo, mapping, topmost, ntm)
632 # TODO update mq state
632 # TODO update mq state
633 if obsolete._enabled:
633 if obsolete._enabled:
634 markers = []
634 markers = []
635 # sort by revision number because it sound "right"
635 # sort by revision number because it sound "right"
636 for prec in sorted(mapping, key=repo.changelog.rev):
636 for prec in sorted(mapping, key=repo.changelog.rev):
637 succs = mapping[prec]
637 succs = mapping[prec]
638 markers.append((repo[prec],
638 markers.append((repo[prec],
639 tuple(repo[s] for s in succs)))
639 tuple(repo[s] for s in succs)))
640 if markers:
640 if markers:
641 obsolete.createmarkers(repo, markers)
641 obsolete.createmarkers(repo, markers)
642 else:
642 else:
643 cleanupnode(ui, repo, 'replaced', mapping)
643 cleanupnode(ui, repo, 'replaced', mapping)
644
644
645 cleanupnode(ui, repo, 'temp', tmpnodes)
645 cleanupnode(ui, repo, 'temp', tmpnodes)
646 os.unlink(os.path.join(repo.path, 'histedit-state'))
646 os.unlink(os.path.join(repo.path, 'histedit-state'))
647 if os.path.exists(repo.sjoin('undo')):
647 if os.path.exists(repo.sjoin('undo')):
648 os.unlink(repo.sjoin('undo'))
648 os.unlink(repo.sjoin('undo'))
649
649
650
650
651 def bootstrapcontinue(ui, repo, parentctx, rules, opts):
651 def bootstrapcontinue(ui, repo, parentctx, rules, opts):
652 action, currentnode = rules.pop(0)
652 action, currentnode = rules.pop(0)
653 ctx = repo[currentnode]
653 ctx = repo[currentnode]
654 # is there any new commit between the expected parent and "."
654 # is there any new commit between the expected parent and "."
655 #
655 #
656 # note: does not take non linear new change in account (but previous
656 # note: does not take non linear new change in account (but previous
657 # implementation didn't used them anyway (issue3655)
657 # implementation didn't used them anyway (issue3655)
658 newchildren = [c.node() for c in repo.set('(%d::.)', parentctx)]
658 newchildren = [c.node() for c in repo.set('(%d::.)', parentctx)]
659 if parentctx.node() != node.nullid:
659 if parentctx.node() != node.nullid:
660 if not newchildren:
660 if not newchildren:
661 # `parentctxnode` should match but no result. This means that
661 # `parentctxnode` should match but no result. This means that
662 # currentnode is not a descendant from parentctxnode.
662 # currentnode is not a descendant from parentctxnode.
663 msg = _('%s is not an ancestor of working directory')
663 msg = _('%s is not an ancestor of working directory')
664 hint = _('use "histedit --abort" to clear broken state')
664 hint = _('use "histedit --abort" to clear broken state')
665 raise util.Abort(msg % parentctx, hint=hint)
665 raise util.Abort(msg % parentctx, hint=hint)
666 newchildren.pop(0) # remove parentctxnode
666 newchildren.pop(0) # remove parentctxnode
667 # Commit dirty working directory if necessary
667 # Commit dirty working directory if necessary
668 new = None
668 new = None
669 m, a, r, d = repo.status()[:4]
669 m, a, r, d = repo.status()[:4]
670 if m or a or r or d:
670 if m or a or r or d:
671 # prepare the message for the commit to comes
671 # prepare the message for the commit to comes
672 if action in ('f', 'fold'):
672 if action in ('f', 'fold'):
673 message = 'fold-temp-revision %s' % currentnode
673 message = 'fold-temp-revision %s' % currentnode
674 else:
674 else:
675 message = ctx.description() + '\n'
675 message = ctx.description() + '\n'
676 if action in ('e', 'edit', 'm', 'mess'):
676 if action in ('e', 'edit', 'm', 'mess'):
677 editor = cmdutil.commitforceeditor
677 editor = cmdutil.commitforceeditor
678 else:
678 else:
679 editor = False
679 editor = False
680 commit = commitfuncfor(repo, ctx)
680 commit = commitfuncfor(repo, ctx)
681 new = commit(text=message, user=ctx.user(),
681 new = commit(text=message, user=ctx.user(),
682 date=ctx.date(), extra=ctx.extra(),
682 date=ctx.date(), extra=ctx.extra(),
683 editor=editor)
683 editor=editor)
684 if new is not None:
684 if new is not None:
685 newchildren.append(new)
685 newchildren.append(new)
686
686
687 replacements = []
687 replacements = []
688 # track replacements
688 # track replacements
689 if ctx.node() not in newchildren:
689 if ctx.node() not in newchildren:
690 # note: new children may be empty when the changeset is dropped.
690 # note: new children may be empty when the changeset is dropped.
691 # this happen e.g during conflicting pick where we revert content
691 # this happen e.g during conflicting pick where we revert content
692 # to parent.
692 # to parent.
693 replacements.append((ctx.node(), tuple(newchildren)))
693 replacements.append((ctx.node(), tuple(newchildren)))
694
694
695 if action in ('f', 'fold'):
695 if action in ('f', 'fold'):
696 if newchildren:
696 if newchildren:
697 # finalize fold operation if applicable
697 # finalize fold operation if applicable
698 if new is None:
698 if new is None:
699 new = newchildren[-1]
699 new = newchildren[-1]
700 else:
700 else:
701 newchildren.pop() # remove new from internal changes
701 newchildren.pop() # remove new from internal changes
702 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, opts,
702 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, opts,
703 newchildren)
703 newchildren)
704 replacements.extend(repl)
704 replacements.extend(repl)
705 else:
705 else:
706 # newchildren is empty if the fold did not result in any commit
706 # newchildren is empty if the fold did not result in any commit
707 # this happen when all folded change are discarded during the
707 # this happen when all folded change are discarded during the
708 # merge.
708 # merge.
709 replacements.append((ctx.node(), (parentctx.node(),)))
709 replacements.append((ctx.node(), (parentctx.node(),)))
710 elif newchildren:
710 elif newchildren:
711 # otherwise update "parentctx" before proceeding to further operation
711 # otherwise update "parentctx" before proceeding to further operation
712 parentctx = repo[newchildren[-1]]
712 parentctx = repo[newchildren[-1]]
713 return parentctx, replacements
713 return parentctx, replacements
714
714
715
715
716 def between(repo, old, new, keep):
716 def between(repo, old, new, keep):
717 """select and validate the set of revision to edit
717 """select and validate the set of revision to edit
718
718
719 When keep is false, the specified set can't have children."""
719 When keep is false, the specified set can't have children."""
720 ctxs = list(repo.set('%n::%n', old, new))
720 ctxs = list(repo.set('%n::%n', old, new))
721 if ctxs and not keep:
721 if ctxs and not keep:
722 if (not obsolete._enabled and
722 if (not obsolete._enabled and
723 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
723 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
724 raise util.Abort(_('cannot edit history that would orphan nodes'))
724 raise util.Abort(_('cannot edit history that would orphan nodes'))
725 if repo.revs('(%ld) and merge()', ctxs):
725 if repo.revs('(%ld) and merge()', ctxs):
726 raise util.Abort(_('cannot edit history that contains merges'))
726 raise util.Abort(_('cannot edit history that contains merges'))
727 root = ctxs[0] # list is already sorted by repo.set
727 root = ctxs[0] # list is already sorted by repo.set
728 if not root.phase():
728 if not root.phase():
729 raise util.Abort(_('cannot edit immutable changeset: %s') % root)
729 raise util.Abort(_('cannot edit immutable changeset: %s') % root)
730 return [c.node() for c in ctxs]
730 return [c.node() for c in ctxs]
731
731
732
732
733 def writestate(repo, parentnode, rules, keep, topmost, replacements):
733 def writestate(repo, parentnode, rules, keep, topmost, replacements):
734 fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
734 fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
735 pickle.dump((parentnode, rules, keep, topmost, replacements), fp)
735 pickle.dump((parentnode, rules, keep, topmost, replacements), fp)
736 fp.close()
736 fp.close()
737
737
738 def readstate(repo):
738 def readstate(repo):
739 """Returns a tuple of (parentnode, rules, keep, topmost, replacements).
739 """Returns a tuple of (parentnode, rules, keep, topmost, replacements).
740 """
740 """
741 fp = open(os.path.join(repo.path, 'histedit-state'))
741 fp = open(os.path.join(repo.path, 'histedit-state'))
742 return pickle.load(fp)
742 return pickle.load(fp)
743
743
744
744
745 def makedesc(c):
745 def makedesc(c):
746 """build a initial action line for a ctx `c`
746 """build a initial action line for a ctx `c`
747
747
748 line are in the form:
748 line are in the form:
749
749
750 pick <hash> <rev> <summary>
750 pick <hash> <rev> <summary>
751 """
751 """
752 summary = ''
752 summary = ''
753 if c.description():
753 if c.description():
754 summary = c.description().splitlines()[0]
754 summary = c.description().splitlines()[0]
755 line = 'pick %s %d %s' % (c, c.rev(), summary)
755 line = 'pick %s %d %s' % (c, c.rev(), summary)
756 return line[:80] # trim to 80 chars so it's not stupidly wide in my editor
756 return line[:80] # trim to 80 chars so it's not stupidly wide in my editor
757
757
758 def verifyrules(rules, repo, ctxs):
758 def verifyrules(rules, repo, ctxs):
759 """Verify that there exists exactly one edit rule per given changeset.
759 """Verify that there exists exactly one edit rule per given changeset.
760
760
761 Will abort if there are to many or too few rules, a malformed rule,
761 Will abort if there are to many or too few rules, a malformed rule,
762 or a rule on a changeset outside of the user-given range.
762 or a rule on a changeset outside of the user-given range.
763 """
763 """
764 parsed = []
764 parsed = []
765 expected = set(str(c) for c in ctxs)
765 expected = set(str(c) for c in ctxs)
766 seen = set()
766 seen = set()
767 for r in rules:
767 for r in rules:
768 if ' ' not in r:
768 if ' ' not in r:
769 raise util.Abort(_('malformed line "%s"') % r)
769 raise util.Abort(_('malformed line "%s"') % r)
770 action, rest = r.split(' ', 1)
770 action, rest = r.split(' ', 1)
771 ha = rest.strip().split(' ', 1)[0]
771 ha = rest.strip().split(' ', 1)[0]
772 try:
772 try:
773 ha = str(repo[ha]) # ensure its a short hash
773 ha = str(repo[ha]) # ensure its a short hash
774 except error.RepoError:
774 except error.RepoError:
775 raise util.Abort(_('unknown changeset %s listed') % ha)
775 raise util.Abort(_('unknown changeset %s listed') % ha)
776 if ha not in expected:
776 if ha not in expected:
777 raise util.Abort(
777 raise util.Abort(
778 _('may not use changesets other than the ones listed'))
778 _('may not use changesets other than the ones listed'))
779 if ha in seen:
779 if ha in seen:
780 raise util.Abort(_('duplicated command for changeset %s') % ha)
780 raise util.Abort(_('duplicated command for changeset %s') % ha)
781 seen.add(ha)
781 seen.add(ha)
782 if action not in actiontable:
782 if action not in actiontable:
783 raise util.Abort(_('unknown action "%s"') % action)
783 raise util.Abort(_('unknown action "%s"') % action)
784 parsed.append([action, ha])
784 parsed.append([action, ha])
785 missing = sorted(expected - seen) # sort to stabilize output
785 missing = sorted(expected - seen) # sort to stabilize output
786 if missing:
786 if missing:
787 raise util.Abort(_('missing rules for changeset %s') % missing[0],
787 raise util.Abort(_('missing rules for changeset %s') % missing[0],
788 hint=_('do you want to use the drop action?'))
788 hint=_('do you want to use the drop action?'))
789 return parsed
789 return parsed
790
790
791 def processreplacement(repo, replacements):
791 def processreplacement(repo, replacements):
792 """process the list of replacements to return
792 """process the list of replacements to return
793
793
794 1) the final mapping between original and created nodes
794 1) the final mapping between original and created nodes
795 2) the list of temporary node created by histedit
795 2) the list of temporary node created by histedit
796 3) the list of new commit created by histedit"""
796 3) the list of new commit created by histedit"""
797 allsuccs = set()
797 allsuccs = set()
798 replaced = set()
798 replaced = set()
799 fullmapping = {}
799 fullmapping = {}
800 # initialise basic set
800 # initialise basic set
801 # fullmapping record all operation recorded in replacement
801 # fullmapping record all operation recorded in replacement
802 for rep in replacements:
802 for rep in replacements:
803 allsuccs.update(rep[1])
803 allsuccs.update(rep[1])
804 replaced.add(rep[0])
804 replaced.add(rep[0])
805 fullmapping.setdefault(rep[0], set()).update(rep[1])
805 fullmapping.setdefault(rep[0], set()).update(rep[1])
806 new = allsuccs - replaced
806 new = allsuccs - replaced
807 tmpnodes = allsuccs & replaced
807 tmpnodes = allsuccs & replaced
808 # Reduce content fullmapping into direct relation between original nodes
808 # Reduce content fullmapping into direct relation between original nodes
809 # and final node created during history edition
809 # and final node created during history edition
810 # Dropped changeset are replaced by an empty list
810 # Dropped changeset are replaced by an empty list
811 toproceed = set(fullmapping)
811 toproceed = set(fullmapping)
812 final = {}
812 final = {}
813 while toproceed:
813 while toproceed:
814 for x in list(toproceed):
814 for x in list(toproceed):
815 succs = fullmapping[x]
815 succs = fullmapping[x]
816 for s in list(succs):
816 for s in list(succs):
817 if s in toproceed:
817 if s in toproceed:
818 # non final node with unknown closure
818 # non final node with unknown closure
819 # We can't process this now
819 # We can't process this now
820 break
820 break
821 elif s in final:
821 elif s in final:
822 # non final node, replace with closure
822 # non final node, replace with closure
823 succs.remove(s)
823 succs.remove(s)
824 succs.update(final[s])
824 succs.update(final[s])
825 else:
825 else:
826 final[x] = succs
826 final[x] = succs
827 toproceed.remove(x)
827 toproceed.remove(x)
828 # remove tmpnodes from final mapping
828 # remove tmpnodes from final mapping
829 for n in tmpnodes:
829 for n in tmpnodes:
830 del final[n]
830 del final[n]
831 # we expect all changes involved in final to exist in the repo
831 # we expect all changes involved in final to exist in the repo
832 # turn `final` into list (topologically sorted)
832 # turn `final` into list (topologically sorted)
833 nm = repo.changelog.nodemap
833 nm = repo.changelog.nodemap
834 for prec, succs in final.items():
834 for prec, succs in final.items():
835 final[prec] = sorted(succs, key=nm.get)
835 final[prec] = sorted(succs, key=nm.get)
836
836
837 # computed topmost element (necessary for bookmark)
837 # computed topmost element (necessary for bookmark)
838 if new:
838 if new:
839 newtopmost = sorted(new, key=repo.changelog.rev)[-1]
839 newtopmost = sorted(new, key=repo.changelog.rev)[-1]
840 elif not final:
840 elif not final:
841 # Nothing rewritten at all. we won't need `newtopmost`
841 # Nothing rewritten at all. we won't need `newtopmost`
842 # It is the same as `oldtopmost` and `processreplacement` know it
842 # It is the same as `oldtopmost` and `processreplacement` know it
843 newtopmost = None
843 newtopmost = None
844 else:
844 else:
845 # every body died. The newtopmost is the parent of the root.
845 # every body died. The newtopmost is the parent of the root.
846 newtopmost = repo[sorted(final, key=repo.changelog.rev)[0]].p1().node()
846 newtopmost = repo[sorted(final, key=repo.changelog.rev)[0]].p1().node()
847
847
848 return final, tmpnodes, new, newtopmost
848 return final, tmpnodes, new, newtopmost
849
849
850 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
850 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
851 """Move bookmark from old to newly created node"""
851 """Move bookmark from old to newly created node"""
852 if not mapping:
852 if not mapping:
853 # if nothing got rewritten there is not purpose for this function
853 # if nothing got rewritten there is not purpose for this function
854 return
854 return
855 moves = []
855 moves = []
856 for bk, old in sorted(repo._bookmarks.iteritems()):
856 for bk, old in sorted(repo._bookmarks.iteritems()):
857 if old == oldtopmost:
857 if old == oldtopmost:
858 # special case ensure bookmark stay on tip.
858 # special case ensure bookmark stay on tip.
859 #
859 #
860 # This is arguably a feature and we may only want that for the
860 # This is arguably a feature and we may only want that for the
861 # active bookmark. But the behavior is kept compatible with the old
861 # active bookmark. But the behavior is kept compatible with the old
862 # version for now.
862 # version for now.
863 moves.append((bk, newtopmost))
863 moves.append((bk, newtopmost))
864 continue
864 continue
865 base = old
865 base = old
866 new = mapping.get(base, None)
866 new = mapping.get(base, None)
867 if new is None:
867 if new is None:
868 continue
868 continue
869 while not new:
869 while not new:
870 # base is killed, trying with parent
870 # base is killed, trying with parent
871 base = repo[base].p1().node()
871 base = repo[base].p1().node()
872 new = mapping.get(base, (base,))
872 new = mapping.get(base, (base,))
873 # nothing to move
873 # nothing to move
874 moves.append((bk, new[-1]))
874 moves.append((bk, new[-1]))
875 if moves:
875 if moves:
876 marks = repo._bookmarks
876 marks = repo._bookmarks
877 for mark, new in moves:
877 for mark, new in moves:
878 old = marks[mark]
878 old = marks[mark]
879 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
879 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
880 % (mark, node.short(old), node.short(new)))
880 % (mark, node.short(old), node.short(new)))
881 marks[mark] = new
881 marks[mark] = new
882 marks.write()
882 marks.write()
883
883
884 def cleanupnode(ui, repo, name, nodes):
884 def cleanupnode(ui, repo, name, nodes):
885 """strip a group of nodes from the repository
885 """strip a group of nodes from the repository
886
886
887 The set of node to strip may contains unknown nodes."""
887 The set of node to strip may contains unknown nodes."""
888 ui.debug('should strip %s nodes %s\n' %
888 ui.debug('should strip %s nodes %s\n' %
889 (name, ', '.join([node.short(n) for n in nodes])))
889 (name, ', '.join([node.short(n) for n in nodes])))
890 lock = None
890 lock = None
891 try:
891 try:
892 lock = repo.lock()
892 lock = repo.lock()
893 # Find all node that need to be stripped
893 # Find all node that need to be stripped
894 # (we hg %lr instead of %ln to silently ignore unknown item
894 # (we hg %lr instead of %ln to silently ignore unknown item
895 nm = repo.changelog.nodemap
895 nm = repo.changelog.nodemap
896 nodes = [n for n in nodes if n in nm]
896 nodes = [n for n in nodes if n in nm]
897 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
897 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
898 for c in roots:
898 for c in roots:
899 # We should process node in reverse order to strip tip most first.
899 # We should process node in reverse order to strip tip most first.
900 # but this trigger a bug in changegroup hook.
900 # but this trigger a bug in changegroup hook.
901 # This would reduce bundle overhead
901 # This would reduce bundle overhead
902 repair.strip(ui, repo, c)
902 repair.strip(ui, repo, c)
903 finally:
903 finally:
904 lockmod.release(lock)
904 lockmod.release(lock)
905
905
906 def summaryhook(ui, repo):
906 def summaryhook(ui, repo):
907 if not os.path.exists(repo.join('histedit-state')):
907 if not os.path.exists(repo.join('histedit-state')):
908 return
908 return
909 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
909 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
910 if rules:
910 if rules:
911 # i18n: column positioning for "hg summary"
911 # i18n: column positioning for "hg summary"
912 ui.write(_('hist: %s (histedit --continue)\n') %
912 ui.write(_('hist: %s (histedit --continue)\n') %
913 (ui.label(_('%d remaining'), 'histedit.remaining') %
913 (ui.label(_('%d remaining'), 'histedit.remaining') %
914 len(rules)))
914 len(rules)))
915
915
916 def extsetup(ui):
916 def extsetup(ui):
917 cmdutil.summaryhooks.add('histedit', summaryhook)
917 cmdutil.summaryhooks.add('histedit', summaryhook)
918 cmdutil.unfinishedstates.append(
918 cmdutil.unfinishedstates.append(
919 ['histedit-state', False, True, _('histedit in progress'),
919 ['histedit-state', False, True, _('histedit in progress'),
920 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
920 _("use 'hg histedit --continue' or 'hg histedit --abort'")])
@@ -1,200 +1,200 b''
1 Test argument handling and various data parsing
1 Test argument handling and various data parsing
2 ==================================================
2 ==================================================
3
3
4
4
5 Enable extensions used by this test.
5 Enable extensions used by this test.
6 $ cat >>$HGRCPATH <<EOF
6 $ cat >>$HGRCPATH <<EOF
7 > [extensions]
7 > [extensions]
8 > histedit=
8 > histedit=
9 > EOF
9 > EOF
10
10
11 Repo setup.
11 Repo setup.
12 $ hg init foo
12 $ hg init foo
13 $ cd foo
13 $ cd foo
14 $ echo alpha >> alpha
14 $ echo alpha >> alpha
15 $ hg addr
15 $ hg addr
16 adding alpha
16 adding alpha
17 $ hg ci -m one
17 $ hg ci -m one
18 $ echo alpha >> alpha
18 $ echo alpha >> alpha
19 $ hg ci -m two
19 $ hg ci -m two
20 $ echo alpha >> alpha
20 $ echo alpha >> alpha
21 $ hg ci -m three
21 $ hg ci -m three
22 $ echo alpha >> alpha
22 $ echo alpha >> alpha
23 $ hg ci -m four
23 $ hg ci -m four
24 $ echo alpha >> alpha
24 $ echo alpha >> alpha
25 $ hg ci -m five
25 $ hg ci -m five
26
26
27 $ hg log --style compact --graph
27 $ hg log --style compact --graph
28 @ 4[tip] 08d98a8350f3 1970-01-01 00:00 +0000 test
28 @ 4[tip] 08d98a8350f3 1970-01-01 00:00 +0000 test
29 | five
29 | five
30 |
30 |
31 o 3 c8e68270e35a 1970-01-01 00:00 +0000 test
31 o 3 c8e68270e35a 1970-01-01 00:00 +0000 test
32 | four
32 | four
33 |
33 |
34 o 2 eb57da33312f 1970-01-01 00:00 +0000 test
34 o 2 eb57da33312f 1970-01-01 00:00 +0000 test
35 | three
35 | three
36 |
36 |
37 o 1 579e40513370 1970-01-01 00:00 +0000 test
37 o 1 579e40513370 1970-01-01 00:00 +0000 test
38 | two
38 | two
39 |
39 |
40 o 0 6058cbb6cfd7 1970-01-01 00:00 +0000 test
40 o 0 6058cbb6cfd7 1970-01-01 00:00 +0000 test
41 one
41 one
42
42
43
43
44 Run a dummy edit to make sure we get tip^^ correctly via revsingle.
44 Run a dummy edit to make sure we get tip^^ correctly via revsingle.
45 --------------------------------------------------------------------
45 --------------------------------------------------------------------
46
46
47 $ HGEDITOR=cat hg histedit "tip^^"
47 $ HGEDITOR=cat hg histedit "tip^^"
48 pick eb57da33312f 2 three
48 pick eb57da33312f 2 three
49 pick c8e68270e35a 3 four
49 pick c8e68270e35a 3 four
50 pick 08d98a8350f3 4 five
50 pick 08d98a8350f3 4 five
51
51
52 # Edit history between eb57da33312f and 08d98a8350f3
52 # Edit history between eb57da33312f and 08d98a8350f3
53 #
53 #
54 # Commits are listed from least to most recent
54 # Commits are listed from least to most recent
55 #
55 #
56 # Commands:
56 # Commands:
57 # p, pick = use commit
57 # p, pick = use commit
58 # e, edit = use commit, but stop for amending
58 # e, edit = use commit, but stop for amending
59 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
59 # f, fold = use commit, but combine it with the one above
60 # d, drop = remove commit from history
60 # d, drop = remove commit from history
61 # m, mess = edit message without changing commit content
61 # m, mess = edit message without changing commit content
62 #
62 #
63 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
64
64
65 Run on a revision not ancestors of the current working directory.
65 Run on a revision not ancestors of the current working directory.
66 --------------------------------------------------------------------
66 --------------------------------------------------------------------
67
67
68 $ hg up 2
68 $ hg up 2
69 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 $ hg histedit -r 4
70 $ hg histedit -r 4
71 abort: 08d98a8350f3 is not an ancestor of working directory
71 abort: 08d98a8350f3 is not an ancestor of working directory
72 [255]
72 [255]
73 $ hg up --quiet
73 $ hg up --quiet
74
74
75 Run on a revision not descendants of the initial parent
75 Run on a revision not descendants of the initial parent
76 --------------------------------------------------------------------
76 --------------------------------------------------------------------
77
77
78 Test the message shown for inconsistent histedit state, which may be
78 Test the message shown for inconsistent histedit state, which may be
79 created (and forgotten) by Mercurial earlier than 2.7. This emulates
79 created (and forgotten) by Mercurial earlier than 2.7. This emulates
80 Mercurial earlier than 2.7 by renaming ".hg/histedit-state"
80 Mercurial earlier than 2.7 by renaming ".hg/histedit-state"
81 temporarily.
81 temporarily.
82
82
83 $ HGEDITOR=cat hg histedit -r 4 --commands - << EOF
83 $ HGEDITOR=cat hg histedit -r 4 --commands - << EOF
84 > edit 08d98a8350f3 4 five
84 > edit 08d98a8350f3 4 five
85 > EOF
85 > EOF
86 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 reverting alpha
87 reverting alpha
88 Make changes as needed, you may commit or record as needed now.
88 Make changes as needed, you may commit or record as needed now.
89 When you are finished, run hg histedit --continue to resume.
89 When you are finished, run hg histedit --continue to resume.
90 [1]
90 [1]
91
91
92 $ mv .hg/histedit-state .hg/histedit-state.back
92 $ mv .hg/histedit-state .hg/histedit-state.back
93 $ hg update --quiet --clean 2
93 $ hg update --quiet --clean 2
94 $ mv .hg/histedit-state.back .hg/histedit-state
94 $ mv .hg/histedit-state.back .hg/histedit-state
95
95
96 $ hg histedit --continue
96 $ hg histedit --continue
97 abort: c8e68270e35a is not an ancestor of working directory
97 abort: c8e68270e35a is not an ancestor of working directory
98 (use "histedit --abort" to clear broken state)
98 (use "histedit --abort" to clear broken state)
99 [255]
99 [255]
100
100
101 $ hg histedit --abort
101 $ hg histedit --abort
102 $ hg update --quiet --clean
102 $ hg update --quiet --clean
103
103
104 Test that missing revisions are detected
104 Test that missing revisions are detected
105 ---------------------------------------
105 ---------------------------------------
106
106
107 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
107 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
108 > pick eb57da33312f 2 three
108 > pick eb57da33312f 2 three
109 > pick 08d98a8350f3 4 five
109 > pick 08d98a8350f3 4 five
110 > EOF
110 > EOF
111 abort: missing rules for changeset c8e68270e35a
111 abort: missing rules for changeset c8e68270e35a
112 (do you want to use the drop action?)
112 (do you want to use the drop action?)
113 [255]
113 [255]
114
114
115 Test that extra revisions are detected
115 Test that extra revisions are detected
116 ---------------------------------------
116 ---------------------------------------
117
117
118 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
118 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
119 > pick 6058cbb6cfd7 0 one
119 > pick 6058cbb6cfd7 0 one
120 > pick c8e68270e35a 3 four
120 > pick c8e68270e35a 3 four
121 > pick 08d98a8350f3 4 five
121 > pick 08d98a8350f3 4 five
122 > EOF
122 > EOF
123 abort: may not use changesets other than the ones listed
123 abort: may not use changesets other than the ones listed
124 [255]
124 [255]
125
125
126 Test malformed line
126 Test malformed line
127 ---------------------------------------
127 ---------------------------------------
128
128
129 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
129 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
130 > pickeb57da33312f2three
130 > pickeb57da33312f2three
131 > pick c8e68270e35a 3 four
131 > pick c8e68270e35a 3 four
132 > pick 08d98a8350f3 4 five
132 > pick 08d98a8350f3 4 five
133 > EOF
133 > EOF
134 abort: malformed line "pickeb57da33312f2three"
134 abort: malformed line "pickeb57da33312f2three"
135 [255]
135 [255]
136
136
137 Test unknown changeset
137 Test unknown changeset
138 ---------------------------------------
138 ---------------------------------------
139
139
140 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
140 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
141 > pick 0123456789ab 2 three
141 > pick 0123456789ab 2 three
142 > pick c8e68270e35a 3 four
142 > pick c8e68270e35a 3 four
143 > pick 08d98a8350f3 4 five
143 > pick 08d98a8350f3 4 five
144 > EOF
144 > EOF
145 abort: unknown changeset 0123456789ab listed
145 abort: unknown changeset 0123456789ab listed
146 [255]
146 [255]
147
147
148 Test unknown command
148 Test unknown command
149 ---------------------------------------
149 ---------------------------------------
150
150
151 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
151 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
152 > coin eb57da33312f 2 three
152 > coin eb57da33312f 2 three
153 > pick c8e68270e35a 3 four
153 > pick c8e68270e35a 3 four
154 > pick 08d98a8350f3 4 five
154 > pick 08d98a8350f3 4 five
155 > EOF
155 > EOF
156 abort: unknown action "coin"
156 abort: unknown action "coin"
157 [255]
157 [255]
158
158
159 Test duplicated changeset
159 Test duplicated changeset
160 ---------------------------------------
160 ---------------------------------------
161
161
162 So one is missing and one appear twice.
162 So one is missing and one appear twice.
163
163
164 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
164 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
165 > pick eb57da33312f 2 three
165 > pick eb57da33312f 2 three
166 > pick eb57da33312f 2 three
166 > pick eb57da33312f 2 three
167 > pick 08d98a8350f3 4 five
167 > pick 08d98a8350f3 4 five
168 > EOF
168 > EOF
169 abort: duplicated command for changeset eb57da33312f
169 abort: duplicated command for changeset eb57da33312f
170 [255]
170 [255]
171
171
172 Test short version of command
172 Test short version of command
173 ---------------------------------------
173 ---------------------------------------
174
174
175 Note: we use varying amounts of white space between command name and changeset
175 Note: we use varying amounts of white space between command name and changeset
176 short hash. This tests issue3893.
176 short hash. This tests issue3893.
177
177
178 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
178 $ HGEDITOR=cat hg histedit "tip^^" --commands - << EOF
179 > pick eb57da33312f 2 three
179 > pick eb57da33312f 2 three
180 > p c8e68270e35a 3 four
180 > p c8e68270e35a 3 four
181 > f 08d98a8350f3 4 five
181 > f 08d98a8350f3 4 five
182 > EOF
182 > EOF
183 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
183 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
184 reverting alpha
184 reverting alpha
185 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
185 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 four
186 four
187 ***
187 ***
188 five
188 five
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: changed alpha
197 HG: changed alpha
198 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
198 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
200 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
200 saved backup bundle to $TESTTMP/foo/.hg/strip-backup/*-backup.hg (glob)
@@ -1,180 +1,180 b''
1 $ . "$TESTDIR/histedit-helpers.sh"
1 $ . "$TESTDIR/histedit-helpers.sh"
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > histedit=
5 > histedit=
6 > EOF
6 > EOF
7
7
8 $ hg init r
8 $ hg init r
9 $ cd r
9 $ cd r
10
10
11 $ for x in a b c d e f ; do
11 $ for x in a b c d e f ; do
12 > echo $x > $x
12 > echo $x > $x
13 > hg add $x
13 > hg add $x
14 > hg ci -m $x
14 > hg ci -m $x
15 > done
15 > done
16
16
17 $ hg book -r 1 will-move-backwards
17 $ hg book -r 1 will-move-backwards
18 $ hg book -r 2 two
18 $ hg book -r 2 two
19 $ hg book -r 2 also-two
19 $ hg book -r 2 also-two
20 $ hg book -r 3 three
20 $ hg book -r 3 three
21 $ hg book -r 4 four
21 $ hg book -r 4 four
22 $ hg book -r tip five
22 $ hg book -r tip five
23 $ hg log --graph
23 $ hg log --graph
24 @ changeset: 5:652413bf663e
24 @ changeset: 5:652413bf663e
25 | bookmark: five
25 | bookmark: five
26 | tag: tip
26 | tag: tip
27 | user: test
27 | user: test
28 | date: Thu Jan 01 00:00:00 1970 +0000
28 | date: Thu Jan 01 00:00:00 1970 +0000
29 | summary: f
29 | summary: f
30 |
30 |
31 o changeset: 4:e860deea161a
31 o changeset: 4:e860deea161a
32 | bookmark: four
32 | bookmark: four
33 | user: test
33 | user: test
34 | date: Thu Jan 01 00:00:00 1970 +0000
34 | date: Thu Jan 01 00:00:00 1970 +0000
35 | summary: e
35 | summary: e
36 |
36 |
37 o changeset: 3:055a42cdd887
37 o changeset: 3:055a42cdd887
38 | bookmark: three
38 | bookmark: three
39 | user: test
39 | user: test
40 | date: Thu Jan 01 00:00:00 1970 +0000
40 | date: Thu Jan 01 00:00:00 1970 +0000
41 | summary: d
41 | summary: d
42 |
42 |
43 o changeset: 2:177f92b77385
43 o changeset: 2:177f92b77385
44 | bookmark: also-two
44 | bookmark: also-two
45 | bookmark: two
45 | bookmark: two
46 | user: test
46 | user: test
47 | date: Thu Jan 01 00:00:00 1970 +0000
47 | date: Thu Jan 01 00:00:00 1970 +0000
48 | summary: c
48 | summary: c
49 |
49 |
50 o changeset: 1:d2ae7f538514
50 o changeset: 1:d2ae7f538514
51 | bookmark: will-move-backwards
51 | bookmark: will-move-backwards
52 | user: test
52 | user: test
53 | date: Thu Jan 01 00:00:00 1970 +0000
53 | date: Thu Jan 01 00:00:00 1970 +0000
54 | summary: b
54 | summary: b
55 |
55 |
56 o changeset: 0:cb9a9f314b8b
56 o changeset: 0:cb9a9f314b8b
57 user: test
57 user: test
58 date: Thu Jan 01 00:00:00 1970 +0000
58 date: Thu Jan 01 00:00:00 1970 +0000
59 summary: a
59 summary: a
60
60
61 $ HGEDITOR=cat hg histedit 1
61 $ HGEDITOR=cat hg histedit 1
62 pick d2ae7f538514 1 b
62 pick d2ae7f538514 1 b
63 pick 177f92b77385 2 c
63 pick 177f92b77385 2 c
64 pick 055a42cdd887 3 d
64 pick 055a42cdd887 3 d
65 pick e860deea161a 4 e
65 pick e860deea161a 4 e
66 pick 652413bf663e 5 f
66 pick 652413bf663e 5 f
67
67
68 # Edit history between d2ae7f538514 and 652413bf663e
68 # Edit history between d2ae7f538514 and 652413bf663e
69 #
69 #
70 # Commits are listed from least to most recent
70 # Commits are listed from least to most recent
71 #
71 #
72 # Commands:
72 # Commands:
73 # p, pick = use commit
73 # p, pick = use commit
74 # e, edit = use commit, but stop for amending
74 # e, edit = use commit, but stop for amending
75 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
75 # f, fold = use commit, but combine it with the one above
76 # d, drop = remove commit from history
76 # d, drop = remove commit from history
77 # m, mess = edit message without changing commit content
77 # m, mess = edit message without changing commit content
78 #
78 #
79 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
80 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
81 > pick 177f92b77385 2 c
81 > pick 177f92b77385 2 c
82 > drop d2ae7f538514 1 b
82 > drop d2ae7f538514 1 b
83 > pick 055a42cdd887 3 d
83 > pick 055a42cdd887 3 d
84 > fold e860deea161a 4 e
84 > fold e860deea161a 4 e
85 > pick 652413bf663e 5 f
85 > pick 652413bf663e 5 f
86 > EOF
86 > EOF
87 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
87 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
88 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
88 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
89 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
89 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
90 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
90 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
91 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
91 histedit: moving bookmarks two from 177f92b77385 to b346ab9a313d
92 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
92 histedit: moving bookmarks will-move-backwards from d2ae7f538514 to cb9a9f314b8b
93 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-backup.hg (glob)
93 saved backup bundle to $TESTTMP/r/.hg/strip-backup/d2ae7f538514-backup.hg (glob)
94 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-backup.hg (glob)
94 saved backup bundle to $TESTTMP/r/.hg/strip-backup/96e494a2d553-backup.hg (glob)
95 $ hg log --graph
95 $ hg log --graph
96 @ changeset: 3:cacdfd884a93
96 @ changeset: 3:cacdfd884a93
97 | bookmark: five
97 | bookmark: five
98 | tag: tip
98 | tag: tip
99 | user: test
99 | user: test
100 | date: Thu Jan 01 00:00:00 1970 +0000
100 | date: Thu Jan 01 00:00:00 1970 +0000
101 | summary: f
101 | summary: f
102 |
102 |
103 o changeset: 2:59d9f330561f
103 o changeset: 2:59d9f330561f
104 | bookmark: four
104 | bookmark: four
105 | bookmark: three
105 | bookmark: three
106 | user: test
106 | user: test
107 | date: Thu Jan 01 00:00:00 1970 +0000
107 | date: Thu Jan 01 00:00:00 1970 +0000
108 | summary: d
108 | summary: d
109 |
109 |
110 o changeset: 1:b346ab9a313d
110 o changeset: 1:b346ab9a313d
111 | bookmark: also-two
111 | bookmark: also-two
112 | bookmark: two
112 | bookmark: two
113 | user: test
113 | user: test
114 | date: Thu Jan 01 00:00:00 1970 +0000
114 | date: Thu Jan 01 00:00:00 1970 +0000
115 | summary: c
115 | summary: c
116 |
116 |
117 o changeset: 0:cb9a9f314b8b
117 o changeset: 0:cb9a9f314b8b
118 bookmark: will-move-backwards
118 bookmark: will-move-backwards
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: a
121 summary: a
122
122
123 $ HGEDITOR=cat hg histedit 1
123 $ HGEDITOR=cat hg histedit 1
124 pick b346ab9a313d 1 c
124 pick b346ab9a313d 1 c
125 pick 59d9f330561f 2 d
125 pick 59d9f330561f 2 d
126 pick cacdfd884a93 3 f
126 pick cacdfd884a93 3 f
127
127
128 # Edit history between b346ab9a313d and cacdfd884a93
128 # Edit history between b346ab9a313d and cacdfd884a93
129 #
129 #
130 # Commits are listed from least to most recent
130 # Commits are listed from least to most recent
131 #
131 #
132 # Commands:
132 # Commands:
133 # p, pick = use commit
133 # p, pick = use commit
134 # e, edit = use commit, but stop for amending
134 # e, edit = use commit, but stop for amending
135 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
135 # f, fold = use commit, but combine it with the one above
136 # d, drop = remove commit from history
136 # d, drop = remove commit from history
137 # m, mess = edit message without changing commit content
137 # m, mess = edit message without changing commit content
138 #
138 #
139 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
139 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
140 $ hg histedit 1 --commands - --verbose << EOF | grep histedit
141 > pick b346ab9a313d 1 c
141 > pick b346ab9a313d 1 c
142 > pick cacdfd884a93 3 f
142 > pick cacdfd884a93 3 f
143 > pick 59d9f330561f 2 d
143 > pick 59d9f330561f 2 d
144 > EOF
144 > EOF
145 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
145 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
146 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
146 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
147 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
147 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
148 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-backup.hg (glob)
148 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-backup.hg (glob)
149
149
150 We expect 'five' to stay at tip, since the tipmost bookmark is most
150 We expect 'five' to stay at tip, since the tipmost bookmark is most
151 likely the useful signal.
151 likely the useful signal.
152
152
153 $ hg log --graph
153 $ hg log --graph
154 @ changeset: 3:c04e50810e4b
154 @ changeset: 3:c04e50810e4b
155 | bookmark: five
155 | bookmark: five
156 | bookmark: four
156 | bookmark: four
157 | bookmark: three
157 | bookmark: three
158 | tag: tip
158 | tag: tip
159 | user: test
159 | user: test
160 | date: Thu Jan 01 00:00:00 1970 +0000
160 | date: Thu Jan 01 00:00:00 1970 +0000
161 | summary: d
161 | summary: d
162 |
162 |
163 o changeset: 2:c13eb81022ca
163 o changeset: 2:c13eb81022ca
164 | user: test
164 | user: test
165 | date: Thu Jan 01 00:00:00 1970 +0000
165 | date: Thu Jan 01 00:00:00 1970 +0000
166 | summary: f
166 | summary: f
167 |
167 |
168 o changeset: 1:b346ab9a313d
168 o changeset: 1:b346ab9a313d
169 | bookmark: also-two
169 | bookmark: also-two
170 | bookmark: two
170 | bookmark: two
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: 0:cb9a9f314b8b
175 o changeset: 0:cb9a9f314b8b
176 bookmark: will-move-backwards
176 bookmark: will-move-backwards
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: a
179 summary: a
180
180
@@ -1,358 +1,358 b''
1 $ . "$TESTDIR/histedit-helpers.sh"
1 $ . "$TESTDIR/histedit-helpers.sh"
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > histedit=
5 > histedit=
6 > EOF
6 > EOF
7
7
8 $ initrepo ()
8 $ initrepo ()
9 > {
9 > {
10 > hg init r
10 > hg init r
11 > cd r
11 > cd r
12 > for x in a b c d e f ; do
12 > for x in a b c d e f ; do
13 > echo $x > $x
13 > echo $x > $x
14 > hg add $x
14 > hg add $x
15 > hg ci -m $x
15 > hg ci -m $x
16 > done
16 > done
17 > }
17 > }
18
18
19 $ initrepo
19 $ initrepo
20
20
21 log before edit
21 log before edit
22 $ hg log --graph
22 $ hg log --graph
23 @ changeset: 5:652413bf663e
23 @ changeset: 5:652413bf663e
24 | tag: tip
24 | tag: tip
25 | user: test
25 | user: test
26 | date: Thu Jan 01 00:00:00 1970 +0000
26 | date: Thu Jan 01 00:00:00 1970 +0000
27 | summary: f
27 | summary: f
28 |
28 |
29 o changeset: 4:e860deea161a
29 o changeset: 4:e860deea161a
30 | user: test
30 | user: test
31 | date: Thu Jan 01 00:00:00 1970 +0000
31 | date: Thu Jan 01 00:00:00 1970 +0000
32 | summary: e
32 | summary: e
33 |
33 |
34 o changeset: 3:055a42cdd887
34 o changeset: 3:055a42cdd887
35 | user: test
35 | user: test
36 | date: Thu Jan 01 00:00:00 1970 +0000
36 | date: Thu Jan 01 00:00:00 1970 +0000
37 | summary: d
37 | summary: d
38 |
38 |
39 o changeset: 2:177f92b77385
39 o changeset: 2:177f92b77385
40 | user: test
40 | user: test
41 | date: Thu Jan 01 00:00:00 1970 +0000
41 | date: Thu Jan 01 00:00:00 1970 +0000
42 | summary: c
42 | summary: c
43 |
43 |
44 o changeset: 1:d2ae7f538514
44 o changeset: 1:d2ae7f538514
45 | user: test
45 | user: test
46 | date: Thu Jan 01 00:00:00 1970 +0000
46 | date: Thu Jan 01 00:00:00 1970 +0000
47 | summary: b
47 | summary: b
48 |
48 |
49 o changeset: 0:cb9a9f314b8b
49 o changeset: 0:cb9a9f314b8b
50 user: test
50 user: test
51 date: Thu Jan 01 00:00:00 1970 +0000
51 date: Thu Jan 01 00:00:00 1970 +0000
52 summary: a
52 summary: a
53
53
54
54
55 show the edit commands offered
55 show the edit commands offered
56 $ HGEDITOR=cat hg histedit 177f92b77385
56 $ HGEDITOR=cat hg histedit 177f92b77385
57 pick 177f92b77385 2 c
57 pick 177f92b77385 2 c
58 pick 055a42cdd887 3 d
58 pick 055a42cdd887 3 d
59 pick e860deea161a 4 e
59 pick e860deea161a 4 e
60 pick 652413bf663e 5 f
60 pick 652413bf663e 5 f
61
61
62 # Edit history between 177f92b77385 and 652413bf663e
62 # Edit history between 177f92b77385 and 652413bf663e
63 #
63 #
64 # Commits are listed from least to most recent
64 # Commits are listed from least to most recent
65 #
65 #
66 # Commands:
66 # Commands:
67 # p, pick = use commit
67 # p, pick = use commit
68 # e, edit = use commit, but stop for amending
68 # e, edit = use commit, but stop for amending
69 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
69 # f, fold = use commit, but combine it with the one above
70 # d, drop = remove commit from history
70 # d, drop = remove commit from history
71 # m, mess = edit message without changing commit content
71 # m, mess = edit message without changing commit content
72 #
72 #
73 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
74
74
75 edit the history
75 edit the history
76 (use a hacky editor to check histedit-last-edit.txt backup)
76 (use a hacky editor to check histedit-last-edit.txt backup)
77
77
78 $ EDITED="$TESTTMP/editedhistory"
78 $ EDITED="$TESTTMP/editedhistory"
79 $ cat > $EDITED <<EOF
79 $ cat > $EDITED <<EOF
80 > pick 177f92b77385 c
80 > pick 177f92b77385 c
81 > pick e860deea161a e
81 > pick e860deea161a e
82 > pick 652413bf663e f
82 > pick 652413bf663e f
83 > pick 055a42cdd887 d
83 > pick 055a42cdd887 d
84 > EOF
84 > EOF
85 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
85 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
86 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
86 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
87 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
90
90
91 rules should end up in .hg/histedit-last-edit.txt:
91 rules should end up in .hg/histedit-last-edit.txt:
92 $ cat .hg/histedit-last-edit.txt
92 $ cat .hg/histedit-last-edit.txt
93 pick 177f92b77385 c
93 pick 177f92b77385 c
94 pick e860deea161a e
94 pick e860deea161a e
95 pick 652413bf663e f
95 pick 652413bf663e f
96 pick 055a42cdd887 d
96 pick 055a42cdd887 d
97
97
98 log after edit
98 log after edit
99 $ hg log --graph
99 $ hg log --graph
100 @ changeset: 5:07114f51870f
100 @ changeset: 5:07114f51870f
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: d
104 | summary: d
105 |
105 |
106 o changeset: 4:8ade9693061e
106 o changeset: 4:8ade9693061e
107 | user: test
107 | user: test
108 | date: Thu Jan 01 00:00:00 1970 +0000
108 | date: Thu Jan 01 00:00:00 1970 +0000
109 | summary: f
109 | summary: f
110 |
110 |
111 o changeset: 3:d8249471110a
111 o changeset: 3:d8249471110a
112 | user: test
112 | user: test
113 | date: Thu Jan 01 00:00:00 1970 +0000
113 | date: Thu Jan 01 00:00:00 1970 +0000
114 | summary: e
114 | summary: e
115 |
115 |
116 o changeset: 2:177f92b77385
116 o changeset: 2:177f92b77385
117 | user: test
117 | user: test
118 | date: Thu Jan 01 00:00:00 1970 +0000
118 | date: Thu Jan 01 00:00:00 1970 +0000
119 | summary: c
119 | summary: c
120 |
120 |
121 o changeset: 1:d2ae7f538514
121 o changeset: 1:d2ae7f538514
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: b
124 | summary: b
125 |
125 |
126 o changeset: 0:cb9a9f314b8b
126 o changeset: 0:cb9a9f314b8b
127 user: test
127 user: test
128 date: Thu Jan 01 00:00:00 1970 +0000
128 date: Thu Jan 01 00:00:00 1970 +0000
129 summary: a
129 summary: a
130
130
131
131
132 put things back
132 put things back
133
133
134 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF | fixbundle
134 $ hg histedit 177f92b77385 --commands - 2>&1 << EOF | fixbundle
135 > pick 177f92b77385 c
135 > pick 177f92b77385 c
136 > pick 07114f51870f d
136 > pick 07114f51870f d
137 > pick d8249471110a e
137 > pick d8249471110a e
138 > pick 8ade9693061e f
138 > pick 8ade9693061e f
139 > EOF
139 > EOF
140 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
140 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
144
144
145 $ hg log --graph
145 $ hg log --graph
146 @ changeset: 5:7eca9b5b1148
146 @ changeset: 5:7eca9b5b1148
147 | tag: tip
147 | tag: tip
148 | user: test
148 | user: test
149 | date: Thu Jan 01 00:00:00 1970 +0000
149 | date: Thu Jan 01 00:00:00 1970 +0000
150 | summary: f
150 | summary: f
151 |
151 |
152 o changeset: 4:915da888f2de
152 o changeset: 4:915da888f2de
153 | user: test
153 | user: test
154 | date: Thu Jan 01 00:00:00 1970 +0000
154 | date: Thu Jan 01 00:00:00 1970 +0000
155 | summary: e
155 | summary: e
156 |
156 |
157 o changeset: 3:10517e47bbbb
157 o changeset: 3:10517e47bbbb
158 | user: test
158 | user: test
159 | date: Thu Jan 01 00:00:00 1970 +0000
159 | date: Thu Jan 01 00:00:00 1970 +0000
160 | summary: d
160 | summary: d
161 |
161 |
162 o changeset: 2:177f92b77385
162 o changeset: 2:177f92b77385
163 | user: test
163 | user: test
164 | date: Thu Jan 01 00:00:00 1970 +0000
164 | date: Thu Jan 01 00:00:00 1970 +0000
165 | summary: c
165 | summary: c
166 |
166 |
167 o changeset: 1:d2ae7f538514
167 o changeset: 1:d2ae7f538514
168 | user: test
168 | user: test
169 | date: Thu Jan 01 00:00:00 1970 +0000
169 | date: Thu Jan 01 00:00:00 1970 +0000
170 | summary: b
170 | summary: b
171 |
171 |
172 o changeset: 0:cb9a9f314b8b
172 o changeset: 0:cb9a9f314b8b
173 user: test
173 user: test
174 date: Thu Jan 01 00:00:00 1970 +0000
174 date: Thu Jan 01 00:00:00 1970 +0000
175 summary: a
175 summary: a
176
176
177
177
178 slightly different this time
178 slightly different this time
179
179
180 $ hg histedit 177f92b77385 --commands - << EOF 2>&1 | fixbundle
180 $ hg histedit 177f92b77385 --commands - << EOF 2>&1 | fixbundle
181 > pick 10517e47bbbb d
181 > pick 10517e47bbbb d
182 > pick 7eca9b5b1148 f
182 > pick 7eca9b5b1148 f
183 > pick 915da888f2de e
183 > pick 915da888f2de e
184 > pick 177f92b77385 c
184 > pick 177f92b77385 c
185 > EOF
185 > EOF
186 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
186 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
187 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
188 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
188 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 $ hg log --graph
191 $ hg log --graph
192 @ changeset: 5:38b92f448761
192 @ changeset: 5:38b92f448761
193 | tag: tip
193 | tag: tip
194 | user: test
194 | user: test
195 | date: Thu Jan 01 00:00:00 1970 +0000
195 | date: Thu Jan 01 00:00:00 1970 +0000
196 | summary: c
196 | summary: c
197 |
197 |
198 o changeset: 4:de71b079d9ce
198 o changeset: 4:de71b079d9ce
199 | user: test
199 | user: test
200 | date: Thu Jan 01 00:00:00 1970 +0000
200 | date: Thu Jan 01 00:00:00 1970 +0000
201 | summary: e
201 | summary: e
202 |
202 |
203 o changeset: 3:be9ae3a309c6
203 o changeset: 3:be9ae3a309c6
204 | user: test
204 | user: test
205 | date: Thu Jan 01 00:00:00 1970 +0000
205 | date: Thu Jan 01 00:00:00 1970 +0000
206 | summary: f
206 | summary: f
207 |
207 |
208 o changeset: 2:799205341b6b
208 o changeset: 2:799205341b6b
209 | user: test
209 | user: test
210 | date: Thu Jan 01 00:00:00 1970 +0000
210 | date: Thu Jan 01 00:00:00 1970 +0000
211 | summary: d
211 | summary: d
212 |
212 |
213 o changeset: 1:d2ae7f538514
213 o changeset: 1:d2ae7f538514
214 | user: test
214 | user: test
215 | date: Thu Jan 01 00:00:00 1970 +0000
215 | date: Thu Jan 01 00:00:00 1970 +0000
216 | summary: b
216 | summary: b
217 |
217 |
218 o changeset: 0:cb9a9f314b8b
218 o changeset: 0:cb9a9f314b8b
219 user: test
219 user: test
220 date: Thu Jan 01 00:00:00 1970 +0000
220 date: Thu Jan 01 00:00:00 1970 +0000
221 summary: a
221 summary: a
222
222
223
223
224 keep prevents stripping dead revs
224 keep prevents stripping dead revs
225 $ hg histedit 799205341b6b --keep --commands - 2>&1 << EOF | fixbundle
225 $ hg histedit 799205341b6b --keep --commands - 2>&1 << EOF | fixbundle
226 > pick 799205341b6b d
226 > pick 799205341b6b d
227 > pick be9ae3a309c6 f
227 > pick be9ae3a309c6 f
228 > pick 38b92f448761 c
228 > pick 38b92f448761 c
229 > pick de71b079d9ce e
229 > pick de71b079d9ce e
230 > EOF
230 > EOF
231 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
231 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
232 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
232 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 abort: may not use changesets other than the ones listed
283 abort: may not use changesets other than the ones listed
284 $ hg log --graph
284 $ hg log --graph
285 @ changeset: 7:803ef1c6fcfd
285 @ changeset: 7:803ef1c6fcfd
286 | tag: tip
286 | tag: tip
287 | user: test
287 | user: test
288 | date: Thu Jan 01 00:00:00 1970 +0000
288 | date: Thu Jan 01 00:00:00 1970 +0000
289 | summary: e
289 | summary: e
290 |
290 |
291 o changeset: 6:ece0b8d93dda
291 o changeset: 6:ece0b8d93dda
292 | parent: 3:be9ae3a309c6
292 | parent: 3:be9ae3a309c6
293 | user: test
293 | user: test
294 | date: Thu Jan 01 00:00:00 1970 +0000
294 | date: Thu Jan 01 00:00:00 1970 +0000
295 | summary: c
295 | summary: c
296 |
296 |
297 | o changeset: 5:38b92f448761
297 | o changeset: 5:38b92f448761
298 | | user: test
298 | | user: test
299 | | date: Thu Jan 01 00:00:00 1970 +0000
299 | | date: Thu Jan 01 00:00:00 1970 +0000
300 | | summary: c
300 | | summary: c
301 | |
301 | |
302 | o changeset: 4:de71b079d9ce
302 | o changeset: 4:de71b079d9ce
303 |/ user: test
303 |/ user: test
304 | date: Thu Jan 01 00:00:00 1970 +0000
304 | date: Thu Jan 01 00:00:00 1970 +0000
305 | summary: e
305 | summary: e
306 |
306 |
307 o changeset: 3:be9ae3a309c6
307 o changeset: 3:be9ae3a309c6
308 | user: test
308 | user: test
309 | date: Thu Jan 01 00:00:00 1970 +0000
309 | date: Thu Jan 01 00:00:00 1970 +0000
310 | summary: f
310 | summary: f
311 |
311 |
312 o changeset: 2:799205341b6b
312 o changeset: 2:799205341b6b
313 | user: test
313 | user: test
314 | date: Thu Jan 01 00:00:00 1970 +0000
314 | date: Thu Jan 01 00:00:00 1970 +0000
315 | summary: d
315 | summary: d
316 |
316 |
317 o changeset: 1:d2ae7f538514
317 o changeset: 1:d2ae7f538514
318 | user: test
318 | user: test
319 | date: Thu Jan 01 00:00:00 1970 +0000
319 | date: Thu Jan 01 00:00:00 1970 +0000
320 | summary: b
320 | summary: b
321 |
321 |
322 o changeset: 0:cb9a9f314b8b
322 o changeset: 0:cb9a9f314b8b
323 user: test
323 user: test
324 date: Thu Jan 01 00:00:00 1970 +0000
324 date: Thu Jan 01 00:00:00 1970 +0000
325 summary: a
325 summary: a
326
326
327
327
328 should also work if a commit message is missing
328 should also work if a commit message is missing
329 $ BUNDLE="$TESTDIR/missing-comment.hg"
329 $ BUNDLE="$TESTDIR/missing-comment.hg"
330 $ hg init missing
330 $ hg init missing
331 $ cd missing
331 $ cd missing
332 $ hg unbundle $BUNDLE
332 $ hg unbundle $BUNDLE
333 adding changesets
333 adding changesets
334 adding manifests
334 adding manifests
335 adding file changes
335 adding file changes
336 added 3 changesets with 3 changes to 1 files
336 added 3 changesets with 3 changes to 1 files
337 (run 'hg update' to get a working copy)
337 (run 'hg update' to get a working copy)
338 $ hg co tip
338 $ hg co tip
339 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
339 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 $ hg log --graph
340 $ hg log --graph
341 @ changeset: 2:bd22688093b3
341 @ changeset: 2:bd22688093b3
342 | tag: tip
342 | tag: tip
343 | user: Robert Altman <robert.altman@telventDTN.com>
343 | user: Robert Altman <robert.altman@telventDTN.com>
344 | date: Mon Nov 28 16:40:04 2011 +0000
344 | date: Mon Nov 28 16:40:04 2011 +0000
345 | summary: Update file.
345 | summary: Update file.
346 |
346 |
347 o changeset: 1:3b3e956f9171
347 o changeset: 1:3b3e956f9171
348 | user: Robert Altman <robert.altman@telventDTN.com>
348 | user: Robert Altman <robert.altman@telventDTN.com>
349 | date: Mon Nov 28 16:37:57 2011 +0000
349 | date: Mon Nov 28 16:37:57 2011 +0000
350 |
350 |
351 o changeset: 0:141947992243
351 o changeset: 0:141947992243
352 user: Robert Altman <robert.altman@telventDTN.com>
352 user: Robert Altman <robert.altman@telventDTN.com>
353 date: Mon Nov 28 16:35:28 2011 +0000
353 date: Mon Nov 28 16:35:28 2011 +0000
354 summary: Checked in text file
354 summary: Checked in text file
355
355
356 $ hg histedit 0
356 $ hg histedit 0
357 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 $ cd ..
358 $ cd ..
@@ -1,462 +1,462 b''
1 $ . "$TESTDIR/histedit-helpers.sh"
1 $ . "$TESTDIR/histedit-helpers.sh"
2
2
3 Enable obsolete
3 Enable obsolete
4
4
5 $ cat > ${TESTTMP}/obs.py << EOF
5 $ cat > ${TESTTMP}/obs.py << EOF
6 > import mercurial.obsolete
6 > import mercurial.obsolete
7 > mercurial.obsolete._enabled = True
7 > mercurial.obsolete._enabled = True
8 > EOF
8 > EOF
9
9
10 $ cat >> $HGRCPATH << EOF
10 $ cat >> $HGRCPATH << EOF
11 > [ui]
11 > [ui]
12 > logtemplate= {rev}:{node|short} {desc|firstline}
12 > logtemplate= {rev}:{node|short} {desc|firstline}
13 > [phases]
13 > [phases]
14 > publish=False
14 > publish=False
15 > [extensions]'
15 > [extensions]'
16 > histedit=
16 > histedit=
17 > rebase=
17 > rebase=
18 >
18 >
19 > obs=${TESTTMP}/obs.py
19 > obs=${TESTTMP}/obs.py
20 > EOF
20 > EOF
21
21
22 $ hg init base
22 $ hg init base
23 $ cd base
23 $ cd base
24
24
25 $ for x in a b c d e f ; do
25 $ for x in a b c d e f ; do
26 > echo $x > $x
26 > echo $x > $x
27 > hg add $x
27 > hg add $x
28 > hg ci -m $x
28 > hg ci -m $x
29 > done
29 > done
30
30
31 $ hg log --graph
31 $ hg log --graph
32 @ 5:652413bf663e f
32 @ 5:652413bf663e f
33 |
33 |
34 o 4:e860deea161a e
34 o 4:e860deea161a e
35 |
35 |
36 o 3:055a42cdd887 d
36 o 3:055a42cdd887 d
37 |
37 |
38 o 2:177f92b77385 c
38 o 2:177f92b77385 c
39 |
39 |
40 o 1:d2ae7f538514 b
40 o 1:d2ae7f538514 b
41 |
41 |
42 o 0:cb9a9f314b8b a
42 o 0:cb9a9f314b8b a
43
43
44
44
45 $ HGEDITOR=cat hg histedit 1
45 $ HGEDITOR=cat hg histedit 1
46 pick d2ae7f538514 1 b
46 pick d2ae7f538514 1 b
47 pick 177f92b77385 2 c
47 pick 177f92b77385 2 c
48 pick 055a42cdd887 3 d
48 pick 055a42cdd887 3 d
49 pick e860deea161a 4 e
49 pick e860deea161a 4 e
50 pick 652413bf663e 5 f
50 pick 652413bf663e 5 f
51
51
52 # Edit history between d2ae7f538514 and 652413bf663e
52 # Edit history between d2ae7f538514 and 652413bf663e
53 #
53 #
54 # Commits are listed from least to most recent
54 # Commits are listed from least to most recent
55 #
55 #
56 # Commands:
56 # Commands:
57 # p, pick = use commit
57 # p, pick = use commit
58 # e, edit = use commit, but stop for amending
58 # e, edit = use commit, but stop for amending
59 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
59 # f, fold = use commit, but combine it with the one above
60 # d, drop = remove commit from history
60 # d, drop = remove commit from history
61 # m, mess = edit message without changing commit content
61 # m, mess = edit message without changing commit content
62 #
62 #
63 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
64 $ hg histedit 1 --commands - --verbose <<EOF | grep histedit
65 > pick 177f92b77385 2 c
65 > pick 177f92b77385 2 c
66 > drop d2ae7f538514 1 b
66 > drop d2ae7f538514 1 b
67 > pick 055a42cdd887 3 d
67 > pick 055a42cdd887 3 d
68 > fold e860deea161a 4 e
68 > fold e860deea161a 4 e
69 > pick 652413bf663e 5 f
69 > pick 652413bf663e 5 f
70 > EOF
70 > EOF
71 saved backup bundle to $TESTTMP/base/.hg/strip-backup/96e494a2d553-backup.hg (glob)
71 saved backup bundle to $TESTTMP/base/.hg/strip-backup/96e494a2d553-backup.hg (glob)
72 $ hg log --graph --hidden
72 $ hg log --graph --hidden
73 @ 8:cacdfd884a93 f
73 @ 8:cacdfd884a93 f
74 |
74 |
75 o 7:59d9f330561f d
75 o 7:59d9f330561f d
76 |
76 |
77 o 6:b346ab9a313d c
77 o 6:b346ab9a313d c
78 |
78 |
79 | x 5:652413bf663e f
79 | x 5:652413bf663e f
80 | |
80 | |
81 | x 4:e860deea161a e
81 | x 4:e860deea161a e
82 | |
82 | |
83 | x 3:055a42cdd887 d
83 | x 3:055a42cdd887 d
84 | |
84 | |
85 | x 2:177f92b77385 c
85 | x 2:177f92b77385 c
86 | |
86 | |
87 | x 1:d2ae7f538514 b
87 | x 1:d2ae7f538514 b
88 |/
88 |/
89 o 0:cb9a9f314b8b a
89 o 0:cb9a9f314b8b a
90
90
91 $ hg debugobsolete
91 $ hg debugobsolete
92 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {'date': '* *', 'user': 'test'} (glob)
92 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {'date': '* *', 'user': 'test'} (glob)
93 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 {'date': '* *', 'user': 'test'} (glob)
93 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 {'date': '* *', 'user': 'test'} (glob)
94 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
94 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
95 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
95 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
96 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 {'date': '* *', 'user': 'test'} (glob)
96 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 {'date': '* *', 'user': 'test'} (glob)
97
97
98
98
99 Ensure hidden revision does not prevent histedit
99 Ensure hidden revision does not prevent histedit
100 -------------------------------------------------
100 -------------------------------------------------
101
101
102 create an hidden revision
102 create an hidden revision
103
103
104 $ hg histedit 6 --commands - << EOF
104 $ hg histedit 6 --commands - << EOF
105 > pick b346ab9a313d 6 c
105 > pick b346ab9a313d 6 c
106 > drop 59d9f330561f 7 d
106 > drop 59d9f330561f 7 d
107 > pick cacdfd884a93 8 f
107 > pick cacdfd884a93 8 f
108 > EOF
108 > EOF
109 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
109 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
110 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 $ hg log --graph
111 $ hg log --graph
112 @ 9:c13eb81022ca f
112 @ 9:c13eb81022ca f
113 |
113 |
114 o 6:b346ab9a313d c
114 o 6:b346ab9a313d c
115 |
115 |
116 o 0:cb9a9f314b8b a
116 o 0:cb9a9f314b8b a
117
117
118 check hidden revision are ignored (6 have hidden children 7 and 8)
118 check hidden revision are ignored (6 have hidden children 7 and 8)
119
119
120 $ hg histedit 6 --commands - << EOF
120 $ hg histedit 6 --commands - << EOF
121 > pick b346ab9a313d 6 c
121 > pick b346ab9a313d 6 c
122 > pick c13eb81022ca 8 f
122 > pick c13eb81022ca 8 f
123 > EOF
123 > EOF
124 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
125
125
126
126
127
127
128 Test that rewriting leaving instability behind is allowed
128 Test that rewriting leaving instability behind is allowed
129 ---------------------------------------------------------------------
129 ---------------------------------------------------------------------
130
130
131 $ hg up '.^'
131 $ hg up '.^'
132 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
132 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
133 $ hg log -r 'children(.)'
133 $ hg log -r 'children(.)'
134 9:c13eb81022ca f (no-eol)
134 9:c13eb81022ca f (no-eol)
135 $ hg histedit -r '.' --commands - <<EOF
135 $ hg histedit -r '.' --commands - <<EOF
136 > edit b346ab9a313d 6 c
136 > edit b346ab9a313d 6 c
137 > EOF
137 > EOF
138 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
138 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
139 adding c
139 adding c
140 Make changes as needed, you may commit or record as needed now.
140 Make changes as needed, you may commit or record as needed now.
141 When you are finished, run hg histedit --continue to resume.
141 When you are finished, run hg histedit --continue to resume.
142 [1]
142 [1]
143 $ echo c >> c
143 $ echo c >> c
144 $ hg histedit --continue
144 $ hg histedit --continue
145 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
145 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
146
146
147 $ hg log -r 'unstable()'
147 $ hg log -r 'unstable()'
148 9:c13eb81022ca f (no-eol)
148 9:c13eb81022ca f (no-eol)
149
149
150 stabilise
150 stabilise
151
151
152 $ hg rebase -r 'unstable()' -d .
152 $ hg rebase -r 'unstable()' -d .
153 $ hg up tip -q
153 $ hg up tip -q
154
154
155 Test dropping of changeset on the top of the stack
155 Test dropping of changeset on the top of the stack
156 -------------------------------------------------------
156 -------------------------------------------------------
157
157
158 Nothing is rewritten below, the working directory parent must be change for the
158 Nothing is rewritten below, the working directory parent must be change for the
159 dropped changeset to be hidden.
159 dropped changeset to be hidden.
160
160
161 $ cd ..
161 $ cd ..
162 $ hg clone base droplast
162 $ hg clone base droplast
163 updating to branch default
163 updating to branch default
164 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
164 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 $ cd droplast
165 $ cd droplast
166 $ hg histedit -r '40db8afa467b' --commands - << EOF
166 $ hg histedit -r '40db8afa467b' --commands - << EOF
167 > pick 40db8afa467b 10 c
167 > pick 40db8afa467b 10 c
168 > drop b449568bf7fc 11 f
168 > drop b449568bf7fc 11 f
169 > EOF
169 > EOF
170 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
170 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
171 $ hg log -G
171 $ hg log -G
172 @ 10:40db8afa467b c
172 @ 10:40db8afa467b c
173 |
173 |
174 o 0:cb9a9f314b8b a
174 o 0:cb9a9f314b8b a
175
175
176
176
177 With rewritten ancestors
177 With rewritten ancestors
178
178
179 $ echo e > e
179 $ echo e > e
180 $ hg add e
180 $ hg add e
181 $ hg commit -m g
181 $ hg commit -m g
182 $ echo f > f
182 $ echo f > f
183 $ hg add f
183 $ hg add f
184 $ hg commit -m h
184 $ hg commit -m h
185 $ hg histedit -r '40db8afa467b' --commands - << EOF
185 $ hg histedit -r '40db8afa467b' --commands - << EOF
186 > pick 47a8561c0449 12 g
186 > pick 47a8561c0449 12 g
187 > pick 40db8afa467b 10 c
187 > pick 40db8afa467b 10 c
188 > drop 1b3b05f35ff0 13 h
188 > drop 1b3b05f35ff0 13 h
189 > EOF
189 > EOF
190 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
190 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
191 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 $ hg log -G
193 $ hg log -G
194 @ 15:ee6544123ab8 c
194 @ 15:ee6544123ab8 c
195 |
195 |
196 o 14:269e713e9eae g
196 o 14:269e713e9eae g
197 |
197 |
198 o 0:cb9a9f314b8b a
198 o 0:cb9a9f314b8b a
199
199
200 $ cd ../base
200 $ cd ../base
201
201
202
202
203
203
204 Test phases support
204 Test phases support
205 ===========================================
205 ===========================================
206
206
207 Check that histedit respect immutability
207 Check that histedit respect immutability
208 -------------------------------------------
208 -------------------------------------------
209
209
210 $ cat >> $HGRCPATH << EOF
210 $ cat >> $HGRCPATH << EOF
211 > [ui]
211 > [ui]
212 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
212 > logtemplate= {rev}:{node|short} ({phase}) {desc|firstline}\n
213 > EOF
213 > EOF
214
214
215 $ hg ph -pv '.^'
215 $ hg ph -pv '.^'
216 phase changed for 2 changesets
216 phase changed for 2 changesets
217 $ hg log -G
217 $ hg log -G
218 @ 11:b449568bf7fc (draft) f
218 @ 11:b449568bf7fc (draft) f
219 |
219 |
220 o 10:40db8afa467b (public) c
220 o 10:40db8afa467b (public) c
221 |
221 |
222 o 0:cb9a9f314b8b (public) a
222 o 0:cb9a9f314b8b (public) a
223
223
224 $ hg histedit -r '.~2'
224 $ hg histedit -r '.~2'
225 abort: cannot edit immutable changeset: cb9a9f314b8b
225 abort: cannot edit immutable changeset: cb9a9f314b8b
226 [255]
226 [255]
227
227
228
228
229 Prepare further testing
229 Prepare further testing
230 -------------------------------------------
230 -------------------------------------------
231
231
232 $ for x in g h i j k ; do
232 $ for x in g h i j k ; do
233 > echo $x > $x
233 > echo $x > $x
234 > hg add $x
234 > hg add $x
235 > hg ci -m $x
235 > hg ci -m $x
236 > done
236 > done
237 $ hg phase --force --secret .~2
237 $ hg phase --force --secret .~2
238 $ hg log -G
238 $ hg log -G
239 @ 16:ee118ab9fa44 (secret) k
239 @ 16:ee118ab9fa44 (secret) k
240 |
240 |
241 o 15:3a6c53ee7f3d (secret) j
241 o 15:3a6c53ee7f3d (secret) j
242 |
242 |
243 o 14:b605fb7503f2 (secret) i
243 o 14:b605fb7503f2 (secret) i
244 |
244 |
245 o 13:7395e1ff83bd (draft) h
245 o 13:7395e1ff83bd (draft) h
246 |
246 |
247 o 12:6b70183d2492 (draft) g
247 o 12:6b70183d2492 (draft) g
248 |
248 |
249 o 11:b449568bf7fc (draft) f
249 o 11:b449568bf7fc (draft) f
250 |
250 |
251 o 10:40db8afa467b (public) c
251 o 10:40db8afa467b (public) c
252 |
252 |
253 o 0:cb9a9f314b8b (public) a
253 o 0:cb9a9f314b8b (public) a
254
254
255 $ cd ..
255 $ cd ..
256
256
257 simple phase conservation
257 simple phase conservation
258 -------------------------------------------
258 -------------------------------------------
259
259
260 Resulting changeset should conserve the phase of the original one whatever the
260 Resulting changeset should conserve the phase of the original one whatever the
261 phases.new-commit option is.
261 phases.new-commit option is.
262
262
263 New-commit as draft (default)
263 New-commit as draft (default)
264
264
265 $ cp -r base simple-draft
265 $ cp -r base simple-draft
266 $ cd simple-draft
266 $ cd simple-draft
267 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
267 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
268 > edit b449568bf7fc 11 f
268 > edit b449568bf7fc 11 f
269 > pick 6b70183d2492 12 g
269 > pick 6b70183d2492 12 g
270 > pick 7395e1ff83bd 13 h
270 > pick 7395e1ff83bd 13 h
271 > pick b605fb7503f2 14 i
271 > pick b605fb7503f2 14 i
272 > pick 3a6c53ee7f3d 15 j
272 > pick 3a6c53ee7f3d 15 j
273 > pick ee118ab9fa44 16 k
273 > pick ee118ab9fa44 16 k
274 > EOF
274 > EOF
275 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
275 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
276 adding f
276 adding f
277 Make changes as needed, you may commit or record as needed now.
277 Make changes as needed, you may commit or record as needed now.
278 When you are finished, run hg histedit --continue to resume.
278 When you are finished, run hg histedit --continue to resume.
279 [1]
279 [1]
280 $ echo f >> f
280 $ echo f >> f
281 $ hg histedit --continue
281 $ hg histedit --continue
282 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
282 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
286 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
286 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 $ hg log -G
288 $ hg log -G
289 @ 22:12e89af74238 (secret) k
289 @ 22:12e89af74238 (secret) k
290 |
290 |
291 o 21:636a8687b22e (secret) j
291 o 21:636a8687b22e (secret) j
292 |
292 |
293 o 20:ccaf0a38653f (secret) i
293 o 20:ccaf0a38653f (secret) i
294 |
294 |
295 o 19:11a89d1c2613 (draft) h
295 o 19:11a89d1c2613 (draft) h
296 |
296 |
297 o 18:c1dec7ca82ea (draft) g
297 o 18:c1dec7ca82ea (draft) g
298 |
298 |
299 o 17:087281e68428 (draft) f
299 o 17:087281e68428 (draft) f
300 |
300 |
301 o 10:40db8afa467b (public) c
301 o 10:40db8afa467b (public) c
302 |
302 |
303 o 0:cb9a9f314b8b (public) a
303 o 0:cb9a9f314b8b (public) a
304
304
305 $ cd ..
305 $ cd ..
306
306
307
307
308 New-commit as draft (default)
308 New-commit as draft (default)
309
309
310 $ cp -r base simple-secret
310 $ cp -r base simple-secret
311 $ cd simple-secret
311 $ cd simple-secret
312 $ cat >> .hg/hgrc << EOF
312 $ cat >> .hg/hgrc << EOF
313 > [phases]
313 > [phases]
314 > new-commit=secret
314 > new-commit=secret
315 > EOF
315 > EOF
316 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
316 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
317 > edit b449568bf7fc 11 f
317 > edit b449568bf7fc 11 f
318 > pick 6b70183d2492 12 g
318 > pick 6b70183d2492 12 g
319 > pick 7395e1ff83bd 13 h
319 > pick 7395e1ff83bd 13 h
320 > pick b605fb7503f2 14 i
320 > pick b605fb7503f2 14 i
321 > pick 3a6c53ee7f3d 15 j
321 > pick 3a6c53ee7f3d 15 j
322 > pick ee118ab9fa44 16 k
322 > pick ee118ab9fa44 16 k
323 > EOF
323 > EOF
324 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
324 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
325 adding f
325 adding f
326 Make changes as needed, you may commit or record as needed now.
326 Make changes as needed, you may commit or record as needed now.
327 When you are finished, run hg histedit --continue to resume.
327 When you are finished, run hg histedit --continue to resume.
328 [1]
328 [1]
329 $ echo f >> f
329 $ echo f >> f
330 $ hg histedit --continue
330 $ hg histedit --continue
331 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
334 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
336 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
336 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 $ hg log -G
337 $ hg log -G
338 @ 22:12e89af74238 (secret) k
338 @ 22:12e89af74238 (secret) k
339 |
339 |
340 o 21:636a8687b22e (secret) j
340 o 21:636a8687b22e (secret) j
341 |
341 |
342 o 20:ccaf0a38653f (secret) i
342 o 20:ccaf0a38653f (secret) i
343 |
343 |
344 o 19:11a89d1c2613 (draft) h
344 o 19:11a89d1c2613 (draft) h
345 |
345 |
346 o 18:c1dec7ca82ea (draft) g
346 o 18:c1dec7ca82ea (draft) g
347 |
347 |
348 o 17:087281e68428 (draft) f
348 o 17:087281e68428 (draft) f
349 |
349 |
350 o 10:40db8afa467b (public) c
350 o 10:40db8afa467b (public) c
351 |
351 |
352 o 0:cb9a9f314b8b (public) a
352 o 0:cb9a9f314b8b (public) a
353
353
354 $ cd ..
354 $ cd ..
355
355
356
356
357 Changeset reordering
357 Changeset reordering
358 -------------------------------------------
358 -------------------------------------------
359
359
360 If a secret changeset is put before a draft one, all descendant should be secret.
360 If a secret changeset is put before a draft one, all descendant should be secret.
361 It seems more important to present the secret phase.
361 It seems more important to present the secret phase.
362
362
363 $ cp -r base reorder
363 $ cp -r base reorder
364 $ cd reorder
364 $ cd reorder
365 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
365 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
366 > pick b449568bf7fc 11 f
366 > pick b449568bf7fc 11 f
367 > pick 3a6c53ee7f3d 15 j
367 > pick 3a6c53ee7f3d 15 j
368 > pick 6b70183d2492 12 g
368 > pick 6b70183d2492 12 g
369 > pick b605fb7503f2 14 i
369 > pick b605fb7503f2 14 i
370 > pick 7395e1ff83bd 13 h
370 > pick 7395e1ff83bd 13 h
371 > pick ee118ab9fa44 16 k
371 > pick ee118ab9fa44 16 k
372 > EOF
372 > EOF
373 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
373 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
374 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
379 $ hg log -G
379 $ hg log -G
380 @ 21:558246857888 (secret) k
380 @ 21:558246857888 (secret) k
381 |
381 |
382 o 20:28bd44768535 (secret) h
382 o 20:28bd44768535 (secret) h
383 |
383 |
384 o 19:d5395202aeb9 (secret) i
384 o 19:d5395202aeb9 (secret) i
385 |
385 |
386 o 18:21edda8e341b (secret) g
386 o 18:21edda8e341b (secret) g
387 |
387 |
388 o 17:5ab64f3a4832 (secret) j
388 o 17:5ab64f3a4832 (secret) j
389 |
389 |
390 o 11:b449568bf7fc (draft) f
390 o 11:b449568bf7fc (draft) f
391 |
391 |
392 o 10:40db8afa467b (public) c
392 o 10:40db8afa467b (public) c
393 |
393 |
394 o 0:cb9a9f314b8b (public) a
394 o 0:cb9a9f314b8b (public) a
395
395
396 $ cd ..
396 $ cd ..
397
397
398 Changeset folding
398 Changeset folding
399 -------------------------------------------
399 -------------------------------------------
400
400
401 Folding a secret changeset with a draft one turn the result secret (again,
401 Folding a secret changeset with a draft one turn the result secret (again,
402 better safe than sorry). Folding between same phase changeset still works
402 better safe than sorry). Folding between same phase changeset still works
403
403
404 Note that there is a few reordering in this series for more extensive test
404 Note that there is a few reordering in this series for more extensive test
405
405
406 $ cp -r base folding
406 $ cp -r base folding
407 $ cd folding
407 $ cd folding
408 $ cat >> .hg/hgrc << EOF
408 $ cat >> .hg/hgrc << EOF
409 > [phases]
409 > [phases]
410 > new-commit=secret
410 > new-commit=secret
411 > EOF
411 > EOF
412 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
412 $ hg histedit -r 'b449568bf7fc' --commands - << EOF
413 > pick 7395e1ff83bd 13 h
413 > pick 7395e1ff83bd 13 h
414 > fold b449568bf7fc 11 f
414 > fold b449568bf7fc 11 f
415 > pick 6b70183d2492 12 g
415 > pick 6b70183d2492 12 g
416 > fold 3a6c53ee7f3d 15 j
416 > fold 3a6c53ee7f3d 15 j
417 > pick b605fb7503f2 14 i
417 > pick b605fb7503f2 14 i
418 > fold ee118ab9fa44 16 k
418 > fold ee118ab9fa44 16 k
419 > EOF
419 > EOF
420 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
420 0 files updated, 0 files merged, 6 files removed, 0 files unresolved
421 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
421 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
422 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
422 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
423 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
423 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
424 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
424 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
426 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
427 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
429 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
429 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
430 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
430 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
431 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/58019c66f35f-backup.hg (glob)
433 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/58019c66f35f-backup.hg (glob)
434 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/83d1858e070b-backup.hg (glob)
434 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/83d1858e070b-backup.hg (glob)
435 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/859969f5ed7e-backup.hg (glob)
435 saved backup bundle to $TESTTMP/folding/.hg/strip-backup/859969f5ed7e-backup.hg (glob)
436 $ hg log -G
436 $ hg log -G
437 @ 19:f9daec13fb98 (secret) i
437 @ 19:f9daec13fb98 (secret) i
438 |
438 |
439 o 18:49807617f46a (secret) g
439 o 18:49807617f46a (secret) g
440 |
440 |
441 o 17:050280826e04 (draft) h
441 o 17:050280826e04 (draft) h
442 |
442 |
443 o 10:40db8afa467b (public) c
443 o 10:40db8afa467b (public) c
444 |
444 |
445 o 0:cb9a9f314b8b (public) a
445 o 0:cb9a9f314b8b (public) a
446
446
447 $ hg co 18
447 $ hg co 18
448 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
448 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
449 $ echo wat >> wat
449 $ echo wat >> wat
450 $ hg add wat
450 $ hg add wat
451 $ hg ci -m 'add wat'
451 $ hg ci -m 'add wat'
452 created new head
452 created new head
453 $ hg merge 19
453 $ hg merge 19
454 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
454 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
455 (branch merge, don't forget to commit)
455 (branch merge, don't forget to commit)
456 $ hg ci -m 'merge'
456 $ hg ci -m 'merge'
457 $ echo not wat > wat
457 $ echo not wat > wat
458 $ hg ci -m 'modify wat'
458 $ hg ci -m 'modify wat'
459 $ hg histedit 17
459 $ hg histedit 17
460 abort: cannot edit history that contains merges
460 abort: cannot edit history that contains merges
461 [255]
461 [255]
462 $ cd ..
462 $ cd ..
@@ -1,144 +1,144 b''
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 # Commands:
48 # Commands:
49 # p, pick = use commit
49 # p, pick = use commit
50 # e, edit = use commit, but stop for amending
50 # e, edit = use commit, but stop for amending
51 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
51 # f, fold = use commit, but combine it with the one above
52 # d, drop = remove commit from history
52 # d, drop = remove commit from history
53 # m, mess = edit message without changing commit content
53 # m, mess = edit message without changing commit content
54 #
54 #
55 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 $ cd ..
56 $ cd ..
57
57
58 show the error from unrelated repos
58 show the error from unrelated repos
59 $ cd r3
59 $ cd r3
60 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
60 $ HGEDITOR=cat hg histedit --outgoing ../r | grep -v comparing | grep -v searching
61 abort: repository is unrelated
61 abort: repository is unrelated
62 [1]
62 [1]
63 $ cd ..
63 $ cd ..
64
64
65 show the error from unrelated repos
65 show the error from unrelated repos
66 $ cd r3
66 $ cd r3
67 $ HGEDITOR=cat hg histedit --force --outgoing ../r
67 $ HGEDITOR=cat hg histedit --force --outgoing ../r
68 comparing with ../r
68 comparing with ../r
69 searching for changes
69 searching for changes
70 warning: repository is unrelated
70 warning: repository is unrelated
71 pick 2a4042b45417 0 g
71 pick 2a4042b45417 0 g
72 pick 68c46b4927ce 1 h
72 pick 68c46b4927ce 1 h
73 pick 51281e65ba79 2 i
73 pick 51281e65ba79 2 i
74
74
75 # Edit history between 2a4042b45417 and 51281e65ba79
75 # Edit history between 2a4042b45417 and 51281e65ba79
76 #
76 #
77 # Commits are listed from least to most recent
77 # Commits are listed from least to most recent
78 #
78 #
79 # Commands:
79 # Commands:
80 # p, pick = use commit
80 # p, pick = use commit
81 # e, edit = use commit, but stop for amending
81 # e, edit = use commit, but stop for amending
82 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
82 # f, fold = use commit, but combine it with the one above
83 # d, drop = remove commit from history
83 # d, drop = remove commit from history
84 # m, mess = edit message without changing commit content
84 # m, mess = edit message without changing commit content
85 #
85 #
86 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 $ cd ..
87 $ cd ..
88
88
89 test sensitivity to branch in URL:
89 test sensitivity to branch in URL:
90
90
91 $ cd r2
91 $ cd r2
92 $ hg -q update 2
92 $ hg -q update 2
93 $ hg -q branch foo
93 $ hg -q branch foo
94 $ hg commit -m 'create foo branch'
94 $ hg commit -m 'create foo branch'
95 $ HGEDITOR=cat hg histedit --outgoing '../r#foo' | grep -v comparing | grep -v searching
95 $ HGEDITOR=cat hg histedit --outgoing '../r#foo' | grep -v comparing | grep -v searching
96 pick f26599ee3441 6 create foo branch
96 pick f26599ee3441 6 create foo branch
97
97
98 # Edit history between f26599ee3441 and f26599ee3441
98 # Edit history between f26599ee3441 and f26599ee3441
99 #
99 #
100 # Commits are listed from least to most recent
100 # Commits are listed from least to most recent
101 #
101 #
102 # Commands:
102 # Commands:
103 # p, pick = use commit
103 # p, pick = use commit
104 # e, edit = use commit, but stop for amending
104 # e, edit = use commit, but stop for amending
105 # f, fold = use commit, but fold into previous commit (combines this commit with the one above)
105 # f, fold = use commit, but combine it with the one above
106 # d, drop = remove commit from history
106 # d, drop = remove commit from history
107 # m, mess = edit message without changing commit content
107 # m, mess = edit message without changing commit content
108 #
108 #
109 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
110
110
111 test to check number of roots in outgoing revisions
111 test to check number of roots in outgoing revisions
112
112
113 $ hg -q outgoing -G --template '{node|short}({branch})' '../r'
113 $ hg -q outgoing -G --template '{node|short}({branch})' '../r'
114 @ f26599ee3441(foo)
114 @ f26599ee3441(foo)
115
115
116 o 652413bf663e(default)
116 o 652413bf663e(default)
117 |
117 |
118 o e860deea161a(default)
118 o e860deea161a(default)
119 |
119 |
120 o 055a42cdd887(default)
120 o 055a42cdd887(default)
121
121
122 $ HGEDITOR=cat hg -q histedit --outgoing '../r'
122 $ HGEDITOR=cat hg -q histedit --outgoing '../r'
123 abort: there are ambiguous outgoing revisions
123 abort: there are ambiguous outgoing revisions
124 (see "hg help histedit" for more detail)
124 (see "hg help histedit" for more detail)
125 [255]
125 [255]
126
126
127 $ hg -q update -C 2
127 $ hg -q update -C 2
128 $ echo aa >> a
128 $ echo aa >> a
129 $ hg -q commit -m 'another head on default'
129 $ hg -q commit -m 'another head on default'
130 $ hg -q outgoing -G --template '{node|short}({branch})' '../r#default'
130 $ hg -q outgoing -G --template '{node|short}({branch})' '../r#default'
131 @ 3879dc049647(default)
131 @ 3879dc049647(default)
132
132
133 o 652413bf663e(default)
133 o 652413bf663e(default)
134 |
134 |
135 o e860deea161a(default)
135 o e860deea161a(default)
136 |
136 |
137 o 055a42cdd887(default)
137 o 055a42cdd887(default)
138
138
139 $ HGEDITOR=cat hg -q histedit --outgoing '../r#default'
139 $ HGEDITOR=cat hg -q histedit --outgoing '../r#default'
140 abort: there are ambiguous outgoing revisions
140 abort: there are ambiguous outgoing revisions
141 (see "hg help histedit" for more detail)
141 (see "hg help histedit" for more detail)
142 [255]
142 [255]
143
143
144 $ cd ..
144 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now