##// END OF EJS Templates
histedit: record histedit source (issue3681)...
Pierre-Yves David -
r18437:358c23e8 default
parent child Browse files
Show More
@@ -1,790 +1,799 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 # Commands:
33 # Commands:
34 # p, pick = use commit
34 # p, pick = use commit
35 # e, edit = use commit, but stop for amending
35 # e, edit = use commit, but stop for amending
36 # f, fold = use commit, but fold into previous commit (combines N and N-1)
36 # f, fold = use commit, but fold into previous commit (combines N and N-1)
37 # d, drop = remove commit from history
37 # d, drop = remove commit from history
38 # m, mess = edit message without changing commit content
38 # m, mess = edit message without changing commit content
39 #
39 #
40
40
41 In this file, lines beginning with ``#`` are ignored. You must specify a rule
41 In this file, lines beginning with ``#`` are ignored. You must specify a rule
42 for each revision in your history. For example, if you had meant to add gamma
42 for each revision in your history. For example, if you had meant to add gamma
43 before beta, and then wanted to add delta in the same revision as beta, you
43 before beta, and then wanted to add delta in the same revision as beta, you
44 would reorganize the file to look like this::
44 would reorganize the file to look like this::
45
45
46 pick 030b686bedc4 Add gamma
46 pick 030b686bedc4 Add gamma
47 pick c561b4e977df Add beta
47 pick c561b4e977df Add beta
48 fold 7c2fd3b9020c Add delta
48 fold 7c2fd3b9020c Add delta
49
49
50 # Edit history between c561b4e977df and 7c2fd3b9020c
50 # Edit history between c561b4e977df and 7c2fd3b9020c
51 #
51 #
52 # Commands:
52 # Commands:
53 # p, pick = use commit
53 # p, pick = use commit
54 # e, edit = use commit, but stop for amending
54 # e, edit = use commit, but stop for amending
55 # f, fold = use commit, but fold into previous commit (combines N and N-1)
55 # f, fold = use commit, but fold into previous commit (combines N and N-1)
56 # d, drop = remove commit from history
56 # d, drop = remove commit from history
57 # m, mess = edit message without changing commit content
57 # m, mess = edit message without changing commit content
58 #
58 #
59
59
60 At which point you close the editor and ``histedit`` starts working. When you
60 At which point you close the editor and ``histedit`` starts working. When you
61 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
61 specify a ``fold`` operation, ``histedit`` will open an editor when it folds
62 those revisions together, offering you a chance to clean up the commit message::
62 those revisions together, offering you a chance to clean up the commit message::
63
63
64 Add beta
64 Add beta
65 ***
65 ***
66 Add delta
66 Add delta
67
67
68 Edit the commit message to your liking, then close the editor. For
68 Edit the commit message to your liking, then close the editor. For
69 this example, let's assume that the commit message was changed to
69 this example, let's assume that the commit message was changed to
70 ``Add beta and delta.`` After histedit has run and had a chance to
70 ``Add beta and delta.`` After histedit has run and had a chance to
71 remove any old or temporary revisions it needed, the history looks
71 remove any old or temporary revisions it needed, the history looks
72 like this::
72 like this::
73
73
74 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
74 @ 2[tip] 989b4d060121 2009-04-27 18:04 -0500 durin42
75 | Add beta and delta.
75 | Add beta and delta.
76 |
76 |
77 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
77 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
78 | Add gamma
78 | Add gamma
79 |
79 |
80 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
80 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
81 Add alpha
81 Add alpha
82
82
83 Note that ``histedit`` does *not* remove any revisions (even its own temporary
83 Note that ``histedit`` does *not* remove any revisions (even its own temporary
84 ones) until after it has completed all the editing operations, so it will
84 ones) until after it has completed all the editing operations, so it will
85 probably perform several strip operations when it's done. For the above example,
85 probably perform several strip operations when it's done. For the above example,
86 it had to run strip twice. Strip can be slow depending on a variety of factors,
86 it had to run strip twice. Strip can be slow depending on a variety of factors,
87 so you might need to be a little patient. You can choose to keep the original
87 so you might need to be a little patient. You can choose to keep the original
88 revisions by passing the ``--keep`` flag.
88 revisions by passing the ``--keep`` flag.
89
89
90 The ``edit`` operation will drop you back to a command prompt,
90 The ``edit`` operation will drop you back to a command prompt,
91 allowing you to edit files freely, or even use ``hg record`` to commit
91 allowing you to edit files freely, or even use ``hg record`` to commit
92 some changes as a separate commit. When you're done, any remaining
92 some changes as a separate commit. When you're done, any remaining
93 uncommitted changes will be committed as well. When done, run ``hg
93 uncommitted changes will be committed as well. When done, run ``hg
94 histedit --continue`` to finish this step. You'll be prompted for a
94 histedit --continue`` to finish this step. You'll be prompted for a
95 new commit message, but the default commit message will be the
95 new commit message, but the default commit message will be the
96 original message for the ``edit`` ed revision.
96 original message for the ``edit`` ed revision.
97
97
98 The ``message`` operation will give you a chance to revise a commit
98 The ``message`` operation will give you a chance to revise a commit
99 message without changing the contents. It's a shortcut for doing
99 message without changing the contents. It's a shortcut for doing
100 ``edit`` immediately followed by `hg histedit --continue``.
100 ``edit`` immediately followed by `hg histedit --continue``.
101
101
102 If ``histedit`` encounters a conflict when moving a revision (while
102 If ``histedit`` encounters a conflict when moving a revision (while
103 handling ``pick`` or ``fold``), it'll stop in a similar manner to
103 handling ``pick`` or ``fold``), it'll stop in a similar manner to
104 ``edit`` with the difference that it won't prompt you for a commit
104 ``edit`` with the difference that it won't prompt you for a commit
105 message when done. If you decide at this point that you don't like how
105 message when done. If you decide at this point that you don't like how
106 much work it will be to rearrange history, or that you made a mistake,
106 much work it will be to rearrange history, or that you made a mistake,
107 you can use ``hg histedit --abort`` to abandon the new changes you
107 you can use ``hg histedit --abort`` to abandon the new changes you
108 have made and return to the state before you attempted to edit your
108 have made and return to the state before you attempted to edit your
109 history.
109 history.
110
110
111 If we clone the histedit-ed example repository above and add four more
111 If we clone the histedit-ed example repository above and add four more
112 changes, such that we have the following history::
112 changes, such that we have the following history::
113
113
114 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
114 @ 6[tip] 038383181893 2009-04-27 18:04 -0500 stefan
115 | Add theta
115 | Add theta
116 |
116 |
117 o 5 140988835471 2009-04-27 18:04 -0500 stefan
117 o 5 140988835471 2009-04-27 18:04 -0500 stefan
118 | Add eta
118 | Add eta
119 |
119 |
120 o 4 122930637314 2009-04-27 18:04 -0500 stefan
120 o 4 122930637314 2009-04-27 18:04 -0500 stefan
121 | Add zeta
121 | Add zeta
122 |
122 |
123 o 3 836302820282 2009-04-27 18:04 -0500 stefan
123 o 3 836302820282 2009-04-27 18:04 -0500 stefan
124 | Add epsilon
124 | Add epsilon
125 |
125 |
126 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
126 o 2 989b4d060121 2009-04-27 18:04 -0500 durin42
127 | Add beta and delta.
127 | Add beta and delta.
128 |
128 |
129 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
129 o 1 081603921c3f 2009-04-27 18:04 -0500 durin42
130 | Add gamma
130 | Add gamma
131 |
131 |
132 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
132 o 0 d8d2fcd0e319 2009-04-27 18:04 -0500 durin42
133 Add alpha
133 Add alpha
134
134
135 If you run ``hg histedit --outgoing`` on the clone then it is the same
135 If you run ``hg histedit --outgoing`` on the clone then it is the same
136 as running ``hg histedit 836302820282``. If you need plan to push to a
136 as running ``hg histedit 836302820282``. If you need plan to push to a
137 repository that Mercurial does not detect to be related to the source
137 repository that Mercurial does not detect to be related to the source
138 repo, you can add a ``--force`` option.
138 repo, you can add a ``--force`` option.
139 """
139 """
140
140
141 try:
141 try:
142 import cPickle as pickle
142 import cPickle as pickle
143 except ImportError:
143 except ImportError:
144 import pickle
144 import pickle
145 import os
145 import os
146
146
147 from mercurial import cmdutil
147 from mercurial import cmdutil
148 from mercurial import discovery
148 from mercurial import discovery
149 from mercurial import error
149 from mercurial import error
150 from mercurial import copies
150 from mercurial import copies
151 from mercurial import context
151 from mercurial import context
152 from mercurial import hg
152 from mercurial import hg
153 from mercurial import lock as lockmod
153 from mercurial import lock as lockmod
154 from mercurial import node
154 from mercurial import node
155 from mercurial import repair
155 from mercurial import repair
156 from mercurial import scmutil
156 from mercurial import scmutil
157 from mercurial import util
157 from mercurial import util
158 from mercurial import obsolete
158 from mercurial import obsolete
159 from mercurial import merge as mergemod
159 from mercurial import merge as mergemod
160 from mercurial.i18n import _
160 from mercurial.i18n import _
161
161
162 cmdtable = {}
162 cmdtable = {}
163 command = cmdutil.command(cmdtable)
163 command = cmdutil.command(cmdtable)
164
164
165 testedwith = 'internal'
165 testedwith = 'internal'
166
166
167 # i18n: command names and abbreviations must remain untranslated
167 # i18n: command names and abbreviations must remain untranslated
168 editcomment = _("""# Edit history between %s and %s
168 editcomment = _("""# Edit history between %s and %s
169 #
169 #
170 # Commands:
170 # Commands:
171 # p, pick = use commit
171 # p, pick = use commit
172 # e, edit = use commit, but stop for amending
172 # e, edit = use commit, but stop for amending
173 # f, fold = use commit, but fold into previous commit (combines N and N-1)
173 # f, fold = use commit, but fold into previous commit (combines N and N-1)
174 # d, drop = remove commit from history
174 # d, drop = remove commit from history
175 # m, mess = edit message without changing commit content
175 # m, mess = edit message without changing commit content
176 #
176 #
177 """)
177 """)
178
178
179 def commitfuncfor(repo, src):
179 def commitfuncfor(repo, src):
180 """Build a commit function for the replacement of <src>
180 """Build a commit function for the replacement of <src>
181
181
182 This function ensure we apply the same treatement to all changesets.
182 This function ensure we apply the same treatement to all changesets.
183
183
184 No such treatment is done yet.
184 - Add a 'histedit_source' entry in extra.
185
185
186 Note that fold have its own separated logic because its handling is a bit
186 Note that fold have its own separated logic because its handling is a bit
187 different and not easily factored out of the fold method.
187 different and not easily factored out of the fold method.
188 """
188 """
189 def commitfunc(**kwargs):
189 def commitfunc(**kwargs):
190 extra = kwargs.get('extra', {}).copy()
191 extra['histedit_source'] = src.hex()
192 kwargs['extra'] = extra
190 return repo.commit(**kwargs)
193 return repo.commit(**kwargs)
191 return commitfunc
194 return commitfunc
192
195
193
196
194
197
195 def applychanges(ui, repo, ctx, opts):
198 def applychanges(ui, repo, ctx, opts):
196 """Merge changeset from ctx (only) in the current working directory"""
199 """Merge changeset from ctx (only) in the current working directory"""
197 wcpar = repo.dirstate.parents()[0]
200 wcpar = repo.dirstate.parents()[0]
198 if ctx.p1().node() == wcpar:
201 if ctx.p1().node() == wcpar:
199 # edition ar "in place" we do not need to make any merge,
202 # edition ar "in place" we do not need to make any merge,
200 # just applies changes on parent for edition
203 # just applies changes on parent for edition
201 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
204 cmdutil.revert(ui, repo, ctx, (wcpar, node.nullid), all=True)
202 stats = None
205 stats = None
203 else:
206 else:
204 try:
207 try:
205 # ui.forcemerge is an internal variable, do not document
208 # ui.forcemerge is an internal variable, do not document
206 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
209 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
207 stats = mergemod.update(repo, ctx.node(), True, True, False,
210 stats = mergemod.update(repo, ctx.node(), True, True, False,
208 ctx.p1().node())
211 ctx.p1().node())
209 finally:
212 finally:
210 repo.ui.setconfig('ui', 'forcemerge', '')
213 repo.ui.setconfig('ui', 'forcemerge', '')
211 repo.setparents(wcpar, node.nullid)
214 repo.setparents(wcpar, node.nullid)
212 repo.dirstate.write()
215 repo.dirstate.write()
213 # fix up dirstate for copies and renames
216 # fix up dirstate for copies and renames
214 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
217 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
215 return stats
218 return stats
216
219
217 def collapse(repo, first, last, commitopts):
220 def collapse(repo, first, last, commitopts):
218 """collapse the set of revisions from first to last as new one.
221 """collapse the set of revisions from first to last as new one.
219
222
220 Expected commit options are:
223 Expected commit options are:
221 - message
224 - message
222 - date
225 - date
223 - username
226 - username
224 Commit message is edited in all cases.
227 Commit message is edited in all cases.
225
228
226 This function works in memory."""
229 This function works in memory."""
227 ctxs = list(repo.set('%d::%d', first, last))
230 ctxs = list(repo.set('%d::%d', first, last))
228 if not ctxs:
231 if not ctxs:
229 return None
232 return None
230 base = first.parents()[0]
233 base = first.parents()[0]
231
234
232 # commit a new version of the old changeset, including the update
235 # commit a new version of the old changeset, including the update
233 # collect all files which might be affected
236 # collect all files which might be affected
234 files = set()
237 files = set()
235 for ctx in ctxs:
238 for ctx in ctxs:
236 files.update(ctx.files())
239 files.update(ctx.files())
237
240
238 # Recompute copies (avoid recording a -> b -> a)
241 # Recompute copies (avoid recording a -> b -> a)
239 copied = copies.pathcopies(first, last)
242 copied = copies.pathcopies(first, last)
240
243
241 # prune files which were reverted by the updates
244 # prune files which were reverted by the updates
242 def samefile(f):
245 def samefile(f):
243 if f in last.manifest():
246 if f in last.manifest():
244 a = last.filectx(f)
247 a = last.filectx(f)
245 if f in base.manifest():
248 if f in base.manifest():
246 b = base.filectx(f)
249 b = base.filectx(f)
247 return (a.data() == b.data()
250 return (a.data() == b.data()
248 and a.flags() == b.flags())
251 and a.flags() == b.flags())
249 else:
252 else:
250 return False
253 return False
251 else:
254 else:
252 return f not in base.manifest()
255 return f not in base.manifest()
253 files = [f for f in files if not samefile(f)]
256 files = [f for f in files if not samefile(f)]
254 # commit version of these files as defined by head
257 # commit version of these files as defined by head
255 headmf = last.manifest()
258 headmf = last.manifest()
256 def filectxfn(repo, ctx, path):
259 def filectxfn(repo, ctx, path):
257 if path in headmf:
260 if path in headmf:
258 fctx = last[path]
261 fctx = last[path]
259 flags = fctx.flags()
262 flags = fctx.flags()
260 mctx = context.memfilectx(fctx.path(), fctx.data(),
263 mctx = context.memfilectx(fctx.path(), fctx.data(),
261 islink='l' in flags,
264 islink='l' in flags,
262 isexec='x' in flags,
265 isexec='x' in flags,
263 copied=copied.get(path))
266 copied=copied.get(path))
264 return mctx
267 return mctx
265 raise IOError()
268 raise IOError()
266
269
267 if commitopts.get('message'):
270 if commitopts.get('message'):
268 message = commitopts['message']
271 message = commitopts['message']
269 else:
272 else:
270 message = first.description()
273 message = first.description()
271 user = commitopts.get('user')
274 user = commitopts.get('user')
272 date = commitopts.get('date')
275 date = commitopts.get('date')
273 extra = first.extra()
276 extra = commitopts.get('extra')
274
277
275 parents = (first.p1().node(), first.p2().node())
278 parents = (first.p1().node(), first.p2().node())
276 new = context.memctx(repo,
279 new = context.memctx(repo,
277 parents=parents,
280 parents=parents,
278 text=message,
281 text=message,
279 files=files,
282 files=files,
280 filectxfn=filectxfn,
283 filectxfn=filectxfn,
281 user=user,
284 user=user,
282 date=date,
285 date=date,
283 extra=extra)
286 extra=extra)
284 new._text = cmdutil.commitforceeditor(repo, new, [])
287 new._text = cmdutil.commitforceeditor(repo, new, [])
285 return repo.commitctx(new)
288 return repo.commitctx(new)
286
289
287 def pick(ui, repo, ctx, ha, opts):
290 def pick(ui, repo, ctx, ha, opts):
288 oldctx = repo[ha]
291 oldctx = repo[ha]
289 if oldctx.parents()[0] == ctx:
292 if oldctx.parents()[0] == ctx:
290 ui.debug('node %s unchanged\n' % ha)
293 ui.debug('node %s unchanged\n' % ha)
291 return oldctx, []
294 return oldctx, []
292 hg.update(repo, ctx.node())
295 hg.update(repo, ctx.node())
293 stats = applychanges(ui, repo, oldctx, opts)
296 stats = applychanges(ui, repo, oldctx, opts)
294 if stats and stats[3] > 0:
297 if stats and stats[3] > 0:
295 raise util.Abort(_('Fix up the change and run '
298 raise util.Abort(_('Fix up the change and run '
296 'hg histedit --continue'))
299 'hg histedit --continue'))
297 # drop the second merge parent
300 # drop the second merge parent
298 commit = commitfuncfor(repo, oldctx)
301 commit = commitfuncfor(repo, oldctx)
299 n = commit(text=oldctx.description(), user=oldctx.user(),
302 n = commit(text=oldctx.description(), user=oldctx.user(),
300 date=oldctx.date(), extra=oldctx.extra())
303 date=oldctx.date(), extra=oldctx.extra())
301 if n is None:
304 if n is None:
302 ui.warn(_('%s: empty changeset\n')
305 ui.warn(_('%s: empty changeset\n')
303 % node.hex(ha))
306 % node.hex(ha))
304 return ctx, []
307 return ctx, []
305 new = repo[n]
308 new = repo[n]
306 return new, [(oldctx.node(), (n,))]
309 return new, [(oldctx.node(), (n,))]
307
310
308
311
309 def edit(ui, repo, ctx, ha, opts):
312 def edit(ui, repo, ctx, ha, opts):
310 oldctx = repo[ha]
313 oldctx = repo[ha]
311 hg.update(repo, ctx.node())
314 hg.update(repo, ctx.node())
312 applychanges(ui, repo, oldctx, opts)
315 applychanges(ui, repo, oldctx, opts)
313 raise util.Abort(_('Make changes as needed, you may commit or record as '
316 raise util.Abort(_('Make changes as needed, you may commit or record as '
314 'needed now.\nWhen you are finished, run hg'
317 'needed now.\nWhen you are finished, run hg'
315 ' histedit --continue to resume.'))
318 ' histedit --continue to resume.'))
316
319
317 def fold(ui, repo, ctx, ha, opts):
320 def fold(ui, repo, ctx, ha, opts):
318 oldctx = repo[ha]
321 oldctx = repo[ha]
319 hg.update(repo, ctx.node())
322 hg.update(repo, ctx.node())
320 stats = applychanges(ui, repo, oldctx, opts)
323 stats = applychanges(ui, repo, oldctx, opts)
321 if stats and stats[3] > 0:
324 if stats and stats[3] > 0:
322 raise util.Abort(_('Fix up the change and run '
325 raise util.Abort(_('Fix up the change and run '
323 'hg histedit --continue'))
326 'hg histedit --continue'))
324 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
327 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
325 date=oldctx.date(), extra=oldctx.extra())
328 date=oldctx.date(), extra=oldctx.extra())
326 if n is None:
329 if n is None:
327 ui.warn(_('%s: empty changeset')
330 ui.warn(_('%s: empty changeset')
328 % node.hex(ha))
331 % node.hex(ha))
329 return ctx, []
332 return ctx, []
330 return finishfold(ui, repo, ctx, oldctx, n, opts, [])
333 return finishfold(ui, repo, ctx, oldctx, n, opts, [])
331
334
332 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
335 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
333 parent = ctx.parents()[0].node()
336 parent = ctx.parents()[0].node()
334 hg.update(repo, parent)
337 hg.update(repo, parent)
335 ### prepare new commit data
338 ### prepare new commit data
336 commitopts = opts.copy()
339 commitopts = opts.copy()
337 # username
340 # username
338 if ctx.user() == oldctx.user():
341 if ctx.user() == oldctx.user():
339 username = ctx.user()
342 username = ctx.user()
340 else:
343 else:
341 username = ui.username()
344 username = ui.username()
342 commitopts['user'] = username
345 commitopts['user'] = username
343 # commit message
346 # commit message
344 newmessage = '\n***\n'.join(
347 newmessage = '\n***\n'.join(
345 [ctx.description()] +
348 [ctx.description()] +
346 [repo[r].description() for r in internalchanges] +
349 [repo[r].description() for r in internalchanges] +
347 [oldctx.description()]) + '\n'
350 [oldctx.description()]) + '\n'
348 commitopts['message'] = newmessage
351 commitopts['message'] = newmessage
349 # date
352 # date
350 commitopts['date'] = max(ctx.date(), oldctx.date())
353 commitopts['date'] = max(ctx.date(), oldctx.date())
354 extra = ctx.extra().copy()
355 # histedit_source
356 # note: ctx is likely a temporary commit but that the best we can do here
357 # This is sufficient to solve issue3681 anyway
358 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
359 commitopts['extra'] = extra
351 n = collapse(repo, ctx, repo[newnode], commitopts)
360 n = collapse(repo, ctx, repo[newnode], commitopts)
352 if n is None:
361 if n is None:
353 return ctx, []
362 return ctx, []
354 hg.update(repo, n)
363 hg.update(repo, n)
355 replacements = [(oldctx.node(), (newnode,)),
364 replacements = [(oldctx.node(), (newnode,)),
356 (ctx.node(), (n,)),
365 (ctx.node(), (n,)),
357 (newnode, (n,)),
366 (newnode, (n,)),
358 ]
367 ]
359 for ich in internalchanges:
368 for ich in internalchanges:
360 replacements.append((ich, (n,)))
369 replacements.append((ich, (n,)))
361 return repo[n], replacements
370 return repo[n], replacements
362
371
363 def drop(ui, repo, ctx, ha, opts):
372 def drop(ui, repo, ctx, ha, opts):
364 return ctx, [(repo[ha].node(), ())]
373 return ctx, [(repo[ha].node(), ())]
365
374
366
375
367 def message(ui, repo, ctx, ha, opts):
376 def message(ui, repo, ctx, ha, opts):
368 oldctx = repo[ha]
377 oldctx = repo[ha]
369 hg.update(repo, ctx.node())
378 hg.update(repo, ctx.node())
370 stats = applychanges(ui, repo, oldctx, opts)
379 stats = applychanges(ui, repo, oldctx, opts)
371 if stats and stats[3] > 0:
380 if stats and stats[3] > 0:
372 raise util.Abort(_('Fix up the change and run '
381 raise util.Abort(_('Fix up the change and run '
373 'hg histedit --continue'))
382 'hg histedit --continue'))
374 message = oldctx.description() + '\n'
383 message = oldctx.description() + '\n'
375 message = ui.edit(message, ui.username())
384 message = ui.edit(message, ui.username())
376 commit = commitfuncfor(repo, oldctx)
385 commit = commitfuncfor(repo, oldctx)
377 new = commit(text=message, user=oldctx.user(), date=oldctx.date(),
386 new = commit(text=message, user=oldctx.user(), date=oldctx.date(),
378 extra=oldctx.extra())
387 extra=oldctx.extra())
379 newctx = repo[new]
388 newctx = repo[new]
380 if oldctx.node() != newctx.node():
389 if oldctx.node() != newctx.node():
381 return newctx, [(oldctx.node(), (new,))]
390 return newctx, [(oldctx.node(), (new,))]
382 # We didn't make an edit, so just indicate no replaced nodes
391 # We didn't make an edit, so just indicate no replaced nodes
383 return newctx, []
392 return newctx, []
384
393
385 actiontable = {'p': pick,
394 actiontable = {'p': pick,
386 'pick': pick,
395 'pick': pick,
387 'e': edit,
396 'e': edit,
388 'edit': edit,
397 'edit': edit,
389 'f': fold,
398 'f': fold,
390 'fold': fold,
399 'fold': fold,
391 'd': drop,
400 'd': drop,
392 'drop': drop,
401 'drop': drop,
393 'm': message,
402 'm': message,
394 'mess': message,
403 'mess': message,
395 }
404 }
396
405
397 @command('histedit',
406 @command('histedit',
398 [('', 'commands', '',
407 [('', 'commands', '',
399 _('Read history edits from the specified file.')),
408 _('Read history edits from the specified file.')),
400 ('c', 'continue', False, _('continue an edit already in progress')),
409 ('c', 'continue', False, _('continue an edit already in progress')),
401 ('k', 'keep', False,
410 ('k', 'keep', False,
402 _("don't strip old nodes after edit is complete")),
411 _("don't strip old nodes after edit is complete")),
403 ('', 'abort', False, _('abort an edit in progress')),
412 ('', 'abort', False, _('abort an edit in progress')),
404 ('o', 'outgoing', False, _('changesets not found in destination')),
413 ('o', 'outgoing', False, _('changesets not found in destination')),
405 ('f', 'force', False,
414 ('f', 'force', False,
406 _('force outgoing even for unrelated repositories')),
415 _('force outgoing even for unrelated repositories')),
407 ('r', 'rev', [], _('first revision to be edited'))],
416 ('r', 'rev', [], _('first revision to be edited'))],
408 _("[PARENT]"))
417 _("[PARENT]"))
409 def histedit(ui, repo, *parent, **opts):
418 def histedit(ui, repo, *parent, **opts):
410 """interactively edit changeset history
419 """interactively edit changeset history
411 """
420 """
412 # TODO only abort if we try and histedit mq patches, not just
421 # TODO only abort if we try and histedit mq patches, not just
413 # blanket if mq patches are applied somewhere
422 # blanket if mq patches are applied somewhere
414 mq = getattr(repo, 'mq', None)
423 mq = getattr(repo, 'mq', None)
415 if mq and mq.applied:
424 if mq and mq.applied:
416 raise util.Abort(_('source has mq patches applied'))
425 raise util.Abort(_('source has mq patches applied'))
417
426
418 parent = list(parent) + opts.get('rev', [])
427 parent = list(parent) + opts.get('rev', [])
419 if opts.get('outgoing'):
428 if opts.get('outgoing'):
420 if len(parent) > 1:
429 if len(parent) > 1:
421 raise util.Abort(
430 raise util.Abort(
422 _('only one repo argument allowed with --outgoing'))
431 _('only one repo argument allowed with --outgoing'))
423 elif parent:
432 elif parent:
424 parent = parent[0]
433 parent = parent[0]
425
434
426 dest = ui.expandpath(parent or 'default-push', parent or 'default')
435 dest = ui.expandpath(parent or 'default-push', parent or 'default')
427 dest, revs = hg.parseurl(dest, None)[:2]
436 dest, revs = hg.parseurl(dest, None)[:2]
428 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
437 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
429
438
430 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
439 revs, checkout = hg.addbranchrevs(repo, repo, revs, None)
431 other = hg.peer(repo, opts, dest)
440 other = hg.peer(repo, opts, dest)
432
441
433 if revs:
442 if revs:
434 revs = [repo.lookup(rev) for rev in revs]
443 revs = [repo.lookup(rev) for rev in revs]
435
444
436 parent = discovery.findcommonoutgoing(
445 parent = discovery.findcommonoutgoing(
437 repo, other, [], force=opts.get('force')).missing[0:1]
446 repo, other, [], force=opts.get('force')).missing[0:1]
438 else:
447 else:
439 if opts.get('force'):
448 if opts.get('force'):
440 raise util.Abort(_('--force only allowed with --outgoing'))
449 raise util.Abort(_('--force only allowed with --outgoing'))
441
450
442 if opts.get('continue', False):
451 if opts.get('continue', False):
443 if len(parent) != 0:
452 if len(parent) != 0:
444 raise util.Abort(_('no arguments allowed with --continue'))
453 raise util.Abort(_('no arguments allowed with --continue'))
445 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
454 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
446 currentparent, wantnull = repo.dirstate.parents()
455 currentparent, wantnull = repo.dirstate.parents()
447 parentctx = repo[parentctxnode]
456 parentctx = repo[parentctxnode]
448 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
457 parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
449 replacements.extend(repl)
458 replacements.extend(repl)
450 elif opts.get('abort', False):
459 elif opts.get('abort', False):
451 if len(parent) != 0:
460 if len(parent) != 0:
452 raise util.Abort(_('no arguments allowed with --abort'))
461 raise util.Abort(_('no arguments allowed with --abort'))
453 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
462 (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
454 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
463 mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
455 ui.debug('restore wc to old parent %s\n' % node.short(topmost))
464 ui.debug('restore wc to old parent %s\n' % node.short(topmost))
456 hg.clean(repo, topmost)
465 hg.clean(repo, topmost)
457 cleanupnode(ui, repo, 'created', tmpnodes)
466 cleanupnode(ui, repo, 'created', tmpnodes)
458 cleanupnode(ui, repo, 'temp', leafs)
467 cleanupnode(ui, repo, 'temp', leafs)
459 os.unlink(os.path.join(repo.path, 'histedit-state'))
468 os.unlink(os.path.join(repo.path, 'histedit-state'))
460 return
469 return
461 else:
470 else:
462 cmdutil.bailifchanged(repo)
471 cmdutil.bailifchanged(repo)
463 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
472 if os.path.exists(os.path.join(repo.path, 'histedit-state')):
464 raise util.Abort(_('history edit already in progress, try '
473 raise util.Abort(_('history edit already in progress, try '
465 '--continue or --abort'))
474 '--continue or --abort'))
466
475
467 topmost, empty = repo.dirstate.parents()
476 topmost, empty = repo.dirstate.parents()
468
477
469 if len(parent) != 1:
478 if len(parent) != 1:
470 raise util.Abort(_('histedit requires exactly one parent revision'))
479 raise util.Abort(_('histedit requires exactly one parent revision'))
471 parent = scmutil.revsingle(repo, parent[0]).node()
480 parent = scmutil.revsingle(repo, parent[0]).node()
472
481
473 keep = opts.get('keep', False)
482 keep = opts.get('keep', False)
474 revs = between(repo, parent, topmost, keep)
483 revs = between(repo, parent, topmost, keep)
475 if not revs:
484 if not revs:
476 ui.warn(_('nothing to edit\n'))
485 ui.warn(_('nothing to edit\n'))
477 return 1
486 return 1
478
487
479 ctxs = [repo[r] for r in revs]
488 ctxs = [repo[r] for r in revs]
480 rules = opts.get('commands', '')
489 rules = opts.get('commands', '')
481 if not rules:
490 if not rules:
482 rules = '\n'.join([makedesc(c) for c in ctxs])
491 rules = '\n'.join([makedesc(c) for c in ctxs])
483 rules += '\n\n'
492 rules += '\n\n'
484 rules += editcomment % (node.short(parent), node.short(topmost))
493 rules += editcomment % (node.short(parent), node.short(topmost))
485 rules = ui.edit(rules, ui.username())
494 rules = ui.edit(rules, ui.username())
486 # Save edit rules in .hg/histedit-last-edit.txt in case
495 # Save edit rules in .hg/histedit-last-edit.txt in case
487 # the user needs to ask for help after something
496 # the user needs to ask for help after something
488 # surprising happens.
497 # surprising happens.
489 f = open(repo.join('histedit-last-edit.txt'), 'w')
498 f = open(repo.join('histedit-last-edit.txt'), 'w')
490 f.write(rules)
499 f.write(rules)
491 f.close()
500 f.close()
492 else:
501 else:
493 f = open(rules)
502 f = open(rules)
494 rules = f.read()
503 rules = f.read()
495 f.close()
504 f.close()
496 rules = [l for l in (r.strip() for r in rules.splitlines())
505 rules = [l for l in (r.strip() for r in rules.splitlines())
497 if l and not l[0] == '#']
506 if l and not l[0] == '#']
498 rules = verifyrules(rules, repo, ctxs)
507 rules = verifyrules(rules, repo, ctxs)
499
508
500 parentctx = repo[parent].parents()[0]
509 parentctx = repo[parent].parents()[0]
501 keep = opts.get('keep', False)
510 keep = opts.get('keep', False)
502 replacements = []
511 replacements = []
503
512
504
513
505 while rules:
514 while rules:
506 writestate(repo, parentctx.node(), rules, keep, topmost, replacements)
515 writestate(repo, parentctx.node(), rules, keep, topmost, replacements)
507 action, ha = rules.pop(0)
516 action, ha = rules.pop(0)
508 ui.debug('histedit: processing %s %s\n' % (action, ha))
517 ui.debug('histedit: processing %s %s\n' % (action, ha))
509 actfunc = actiontable[action]
518 actfunc = actiontable[action]
510 parentctx, replacement_ = actfunc(ui, repo, parentctx, ha, opts)
519 parentctx, replacement_ = actfunc(ui, repo, parentctx, ha, opts)
511 replacements.extend(replacement_)
520 replacements.extend(replacement_)
512
521
513 hg.update(repo, parentctx.node())
522 hg.update(repo, parentctx.node())
514
523
515 mapping, tmpnodes, created, ntm = processreplacement(repo, replacements)
524 mapping, tmpnodes, created, ntm = processreplacement(repo, replacements)
516 if mapping:
525 if mapping:
517 for prec, succs in mapping.iteritems():
526 for prec, succs in mapping.iteritems():
518 if not succs:
527 if not succs:
519 ui.debug('histedit: %s is dropped\n' % node.short(prec))
528 ui.debug('histedit: %s is dropped\n' % node.short(prec))
520 else:
529 else:
521 ui.debug('histedit: %s is replaced by %s\n' % (
530 ui.debug('histedit: %s is replaced by %s\n' % (
522 node.short(prec), node.short(succs[0])))
531 node.short(prec), node.short(succs[0])))
523 if len(succs) > 1:
532 if len(succs) > 1:
524 m = 'histedit: %s'
533 m = 'histedit: %s'
525 for n in succs[1:]:
534 for n in succs[1:]:
526 ui.debug(m % node.short(n))
535 ui.debug(m % node.short(n))
527
536
528 if not keep:
537 if not keep:
529 if mapping:
538 if mapping:
530 movebookmarks(ui, repo, mapping, topmost, ntm)
539 movebookmarks(ui, repo, mapping, topmost, ntm)
531 # TODO update mq state
540 # TODO update mq state
532 if obsolete._enabled:
541 if obsolete._enabled:
533 markers = []
542 markers = []
534 # sort by revision number because it sound "right"
543 # sort by revision number because it sound "right"
535 for prec in sorted(mapping, key=repo.changelog.rev):
544 for prec in sorted(mapping, key=repo.changelog.rev):
536 succs = mapping[prec]
545 succs = mapping[prec]
537 markers.append((repo[prec],
546 markers.append((repo[prec],
538 tuple(repo[s] for s in succs)))
547 tuple(repo[s] for s in succs)))
539 if markers:
548 if markers:
540 obsolete.createmarkers(repo, markers)
549 obsolete.createmarkers(repo, markers)
541 else:
550 else:
542 cleanupnode(ui, repo, 'replaced', mapping)
551 cleanupnode(ui, repo, 'replaced', mapping)
543
552
544 cleanupnode(ui, repo, 'temp', tmpnodes)
553 cleanupnode(ui, repo, 'temp', tmpnodes)
545 os.unlink(os.path.join(repo.path, 'histedit-state'))
554 os.unlink(os.path.join(repo.path, 'histedit-state'))
546 if os.path.exists(repo.sjoin('undo')):
555 if os.path.exists(repo.sjoin('undo')):
547 os.unlink(repo.sjoin('undo'))
556 os.unlink(repo.sjoin('undo'))
548
557
549
558
550 def bootstrapcontinue(ui, repo, parentctx, rules, opts):
559 def bootstrapcontinue(ui, repo, parentctx, rules, opts):
551 action, currentnode = rules.pop(0)
560 action, currentnode = rules.pop(0)
552 ctx = repo[currentnode]
561 ctx = repo[currentnode]
553 # is there any new commit between the expected parent and "."
562 # is there any new commit between the expected parent and "."
554 #
563 #
555 # note: does not take non linear new change in account (but previous
564 # note: does not take non linear new change in account (but previous
556 # implementation didn't used them anyway (issue3655)
565 # implementation didn't used them anyway (issue3655)
557 newchildren = [c.node() for c in repo.set('(%d::.)', parentctx)]
566 newchildren = [c.node() for c in repo.set('(%d::.)', parentctx)]
558 if not newchildren:
567 if not newchildren:
559 # `parentctxnode` should match but no result. This means that
568 # `parentctxnode` should match but no result. This means that
560 # currentnode is not a descendant from parentctxnode.
569 # currentnode is not a descendant from parentctxnode.
561 msg = _('working directory parent is not a descendant of %s')
570 msg = _('working directory parent is not a descendant of %s')
562 hint = _('update to %s or descendant and run "hg histedit '
571 hint = _('update to %s or descendant and run "hg histedit '
563 '--continue" again') % parentctx
572 '--continue" again') % parentctx
564 raise util.Abort(msg % parentctx, hint=hint)
573 raise util.Abort(msg % parentctx, hint=hint)
565 newchildren.pop(0) # remove parentctxnode
574 newchildren.pop(0) # remove parentctxnode
566 # Commit dirty working directory if necessary
575 # Commit dirty working directory if necessary
567 new = None
576 new = None
568 m, a, r, d = repo.status()[:4]
577 m, a, r, d = repo.status()[:4]
569 if m or a or r or d:
578 if m or a or r or d:
570 # prepare the message for the commit to comes
579 # prepare the message for the commit to comes
571 if action in ('f', 'fold'):
580 if action in ('f', 'fold'):
572 message = 'fold-temp-revision %s' % currentnode
581 message = 'fold-temp-revision %s' % currentnode
573 else:
582 else:
574 message = ctx.description() + '\n'
583 message = ctx.description() + '\n'
575 if action in ('e', 'edit', 'm', 'mess'):
584 if action in ('e', 'edit', 'm', 'mess'):
576 editor = cmdutil.commitforceeditor
585 editor = cmdutil.commitforceeditor
577 else:
586 else:
578 editor = False
587 editor = False
579 commit = commitfuncfor(repo, ctx)
588 commit = commitfuncfor(repo, ctx)
580 new = commit(text=message, user=ctx.user(),
589 new = commit(text=message, user=ctx.user(),
581 date=ctx.date(), extra=ctx.extra(),
590 date=ctx.date(), extra=ctx.extra(),
582 editor=editor)
591 editor=editor)
583 if new is not None:
592 if new is not None:
584 newchildren.append(new)
593 newchildren.append(new)
585
594
586 replacements = []
595 replacements = []
587 # track replacements
596 # track replacements
588 if ctx.node() not in newchildren:
597 if ctx.node() not in newchildren:
589 # note: new children may be empty when the changeset is dropped.
598 # note: new children may be empty when the changeset is dropped.
590 # this happen e.g during conflicting pick where we revert content
599 # this happen e.g during conflicting pick where we revert content
591 # to parent.
600 # to parent.
592 replacements.append((ctx.node(), tuple(newchildren)))
601 replacements.append((ctx.node(), tuple(newchildren)))
593
602
594 if action in ('f', 'fold'):
603 if action in ('f', 'fold'):
595 # finalize fold operation if applicable
604 # finalize fold operation if applicable
596 if new is None:
605 if new is None:
597 new = newchildren[-1]
606 new = newchildren[-1]
598 else:
607 else:
599 newchildren.pop() # remove new from internal changes
608 newchildren.pop() # remove new from internal changes
600 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, opts,
609 parentctx, repl = finishfold(ui, repo, parentctx, ctx, new, opts,
601 newchildren)
610 newchildren)
602 replacements.extend(repl)
611 replacements.extend(repl)
603 elif newchildren:
612 elif newchildren:
604 # otherwize update "parentctx" before proceding to further operation
613 # otherwize update "parentctx" before proceding to further operation
605 parentctx = repo[newchildren[-1]]
614 parentctx = repo[newchildren[-1]]
606 return parentctx, replacements
615 return parentctx, replacements
607
616
608
617
609 def between(repo, old, new, keep):
618 def between(repo, old, new, keep):
610 """select and validate the set of revision to edit
619 """select and validate the set of revision to edit
611
620
612 When keep is false, the specified set can't have children."""
621 When keep is false, the specified set can't have children."""
613 ctxs = list(repo.set('%n::%n', old, new))
622 ctxs = list(repo.set('%n::%n', old, new))
614 if ctxs and not keep:
623 if ctxs and not keep:
615 if (not obsolete._enabled and
624 if (not obsolete._enabled and
616 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
625 repo.revs('(%ld::) - (%ld)', ctxs, ctxs)):
617 raise util.Abort(_('cannot edit history that would orphan nodes'))
626 raise util.Abort(_('cannot edit history that would orphan nodes'))
618 root = ctxs[0] # list is already sorted by repo.set
627 root = ctxs[0] # list is already sorted by repo.set
619 if not root.phase():
628 if not root.phase():
620 raise util.Abort(_('cannot edit immutable changeset: %s') % root)
629 raise util.Abort(_('cannot edit immutable changeset: %s') % root)
621 return [c.node() for c in ctxs]
630 return [c.node() for c in ctxs]
622
631
623
632
624 def writestate(repo, parentnode, rules, keep, topmost, replacements):
633 def writestate(repo, parentnode, rules, keep, topmost, replacements):
625 fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
634 fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
626 pickle.dump((parentnode, rules, keep, topmost, replacements), fp)
635 pickle.dump((parentnode, rules, keep, topmost, replacements), fp)
627 fp.close()
636 fp.close()
628
637
629 def readstate(repo):
638 def readstate(repo):
630 """Returns a tuple of (parentnode, rules, keep, topmost, replacements).
639 """Returns a tuple of (parentnode, rules, keep, topmost, replacements).
631 """
640 """
632 fp = open(os.path.join(repo.path, 'histedit-state'))
641 fp = open(os.path.join(repo.path, 'histedit-state'))
633 return pickle.load(fp)
642 return pickle.load(fp)
634
643
635
644
636 def makedesc(c):
645 def makedesc(c):
637 """build a initial action line for a ctx `c`
646 """build a initial action line for a ctx `c`
638
647
639 line are in the form:
648 line are in the form:
640
649
641 pick <hash> <rev> <summary>
650 pick <hash> <rev> <summary>
642 """
651 """
643 summary = ''
652 summary = ''
644 if c.description():
653 if c.description():
645 summary = c.description().splitlines()[0]
654 summary = c.description().splitlines()[0]
646 line = 'pick %s %d %s' % (c, c.rev(), summary)
655 line = 'pick %s %d %s' % (c, c.rev(), summary)
647 return line[:80] # trim to 80 chars so it's not stupidly wide in my editor
656 return line[:80] # trim to 80 chars so it's not stupidly wide in my editor
648
657
649 def verifyrules(rules, repo, ctxs):
658 def verifyrules(rules, repo, ctxs):
650 """Verify that there exists exactly one edit rule per given changeset.
659 """Verify that there exists exactly one edit rule per given changeset.
651
660
652 Will abort if there are to many or too few rules, a malformed rule,
661 Will abort if there are to many or too few rules, a malformed rule,
653 or a rule on a changeset outside of the user-given range.
662 or a rule on a changeset outside of the user-given range.
654 """
663 """
655 parsed = []
664 parsed = []
656 if len(rules) != len(ctxs):
665 if len(rules) != len(ctxs):
657 raise util.Abort(_('must specify a rule for each changeset once'))
666 raise util.Abort(_('must specify a rule for each changeset once'))
658 for r in rules:
667 for r in rules:
659 if ' ' not in r:
668 if ' ' not in r:
660 raise util.Abort(_('malformed line "%s"') % r)
669 raise util.Abort(_('malformed line "%s"') % r)
661 action, rest = r.split(' ', 1)
670 action, rest = r.split(' ', 1)
662 if ' ' in rest.strip():
671 if ' ' in rest.strip():
663 ha, rest = rest.split(' ', 1)
672 ha, rest = rest.split(' ', 1)
664 else:
673 else:
665 ha = r.strip()
674 ha = r.strip()
666 try:
675 try:
667 if repo[ha] not in ctxs:
676 if repo[ha] not in ctxs:
668 raise util.Abort(
677 raise util.Abort(
669 _('may not use changesets other than the ones listed'))
678 _('may not use changesets other than the ones listed'))
670 except error.RepoError:
679 except error.RepoError:
671 raise util.Abort(_('unknown changeset %s listed') % ha)
680 raise util.Abort(_('unknown changeset %s listed') % ha)
672 if action not in actiontable:
681 if action not in actiontable:
673 raise util.Abort(_('unknown action "%s"') % action)
682 raise util.Abort(_('unknown action "%s"') % action)
674 parsed.append([action, ha])
683 parsed.append([action, ha])
675 return parsed
684 return parsed
676
685
677 def processreplacement(repo, replacements):
686 def processreplacement(repo, replacements):
678 """process the list of replacements to return
687 """process the list of replacements to return
679
688
680 1) the final mapping between original and created nodes
689 1) the final mapping between original and created nodes
681 2) the list of temporary node created by histedit
690 2) the list of temporary node created by histedit
682 3) the list of new commit created by histedit"""
691 3) the list of new commit created by histedit"""
683 allsuccs = set()
692 allsuccs = set()
684 replaced = set()
693 replaced = set()
685 fullmapping = {}
694 fullmapping = {}
686 # initialise basic set
695 # initialise basic set
687 # fullmapping record all operation recorded in replacement
696 # fullmapping record all operation recorded in replacement
688 for rep in replacements:
697 for rep in replacements:
689 allsuccs.update(rep[1])
698 allsuccs.update(rep[1])
690 replaced.add(rep[0])
699 replaced.add(rep[0])
691 fullmapping.setdefault(rep[0], set()).update(rep[1])
700 fullmapping.setdefault(rep[0], set()).update(rep[1])
692 new = allsuccs - replaced
701 new = allsuccs - replaced
693 tmpnodes = allsuccs & replaced
702 tmpnodes = allsuccs & replaced
694 # Reduce content fullmapping into direct relation between original nodes
703 # Reduce content fullmapping into direct relation between original nodes
695 # and final node created during history edition
704 # and final node created during history edition
696 # Dropped changeset are replaced by an empty list
705 # Dropped changeset are replaced by an empty list
697 toproceed = set(fullmapping)
706 toproceed = set(fullmapping)
698 final = {}
707 final = {}
699 while toproceed:
708 while toproceed:
700 for x in list(toproceed):
709 for x in list(toproceed):
701 succs = fullmapping[x]
710 succs = fullmapping[x]
702 for s in list(succs):
711 for s in list(succs):
703 if s in toproceed:
712 if s in toproceed:
704 # non final node with unknown closure
713 # non final node with unknown closure
705 # We can't process this now
714 # We can't process this now
706 break
715 break
707 elif s in final:
716 elif s in final:
708 # non final node, replace with closure
717 # non final node, replace with closure
709 succs.remove(s)
718 succs.remove(s)
710 succs.update(final[s])
719 succs.update(final[s])
711 else:
720 else:
712 final[x] = succs
721 final[x] = succs
713 toproceed.remove(x)
722 toproceed.remove(x)
714 # remove tmpnodes from final mapping
723 # remove tmpnodes from final mapping
715 for n in tmpnodes:
724 for n in tmpnodes:
716 del final[n]
725 del final[n]
717 # we expect all changes involved in final to exist in the repo
726 # we expect all changes involved in final to exist in the repo
718 # turn `final` into list (topologically sorted)
727 # turn `final` into list (topologically sorted)
719 nm = repo.changelog.nodemap
728 nm = repo.changelog.nodemap
720 for prec, succs in final.items():
729 for prec, succs in final.items():
721 final[prec] = sorted(succs, key=nm.get)
730 final[prec] = sorted(succs, key=nm.get)
722
731
723 # computed topmost element (necessary for bookmark)
732 # computed topmost element (necessary for bookmark)
724 if new:
733 if new:
725 newtopmost = sorted(new, key=repo.changelog.rev)[-1]
734 newtopmost = sorted(new, key=repo.changelog.rev)[-1]
726 elif not final:
735 elif not final:
727 # Nothing rewritten at all. we won't need `newtopmost`
736 # Nothing rewritten at all. we won't need `newtopmost`
728 # It is the same as `oldtopmost` and `processreplacement` know it
737 # It is the same as `oldtopmost` and `processreplacement` know it
729 newtopmost = None
738 newtopmost = None
730 else:
739 else:
731 # every body died. The newtopmost is the parent of the root.
740 # every body died. The newtopmost is the parent of the root.
732 newtopmost = repo[sorted(final, key=repo.changelog.rev)[0]].p1().node()
741 newtopmost = repo[sorted(final, key=repo.changelog.rev)[0]].p1().node()
733
742
734 return final, tmpnodes, new, newtopmost
743 return final, tmpnodes, new, newtopmost
735
744
736 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
745 def movebookmarks(ui, repo, mapping, oldtopmost, newtopmost):
737 """Move bookmark from old to newly created node"""
746 """Move bookmark from old to newly created node"""
738 if not mapping:
747 if not mapping:
739 # if nothing got rewritten there is not purpose for this function
748 # if nothing got rewritten there is not purpose for this function
740 return
749 return
741 moves = []
750 moves = []
742 for bk, old in sorted(repo._bookmarks.iteritems()):
751 for bk, old in sorted(repo._bookmarks.iteritems()):
743 if old == oldtopmost:
752 if old == oldtopmost:
744 # special case ensure bookmark stay on tip.
753 # special case ensure bookmark stay on tip.
745 #
754 #
746 # This is arguably a feature and we may only want that for the
755 # This is arguably a feature and we may only want that for the
747 # active bookmark. But the behavior is kept compatible with the old
756 # active bookmark. But the behavior is kept compatible with the old
748 # version for now.
757 # version for now.
749 moves.append((bk, newtopmost))
758 moves.append((bk, newtopmost))
750 continue
759 continue
751 base = old
760 base = old
752 new = mapping.get(base, None)
761 new = mapping.get(base, None)
753 if new is None:
762 if new is None:
754 continue
763 continue
755 while not new:
764 while not new:
756 # base is killed, trying with parent
765 # base is killed, trying with parent
757 base = repo[base].p1().node()
766 base = repo[base].p1().node()
758 new = mapping.get(base, (base,))
767 new = mapping.get(base, (base,))
759 # nothing to move
768 # nothing to move
760 moves.append((bk, new[-1]))
769 moves.append((bk, new[-1]))
761 if moves:
770 if moves:
762 marks = repo._bookmarks
771 marks = repo._bookmarks
763 for mark, new in moves:
772 for mark, new in moves:
764 old = marks[mark]
773 old = marks[mark]
765 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
774 ui.note(_('histedit: moving bookmarks %s from %s to %s\n')
766 % (mark, node.short(old), node.short(new)))
775 % (mark, node.short(old), node.short(new)))
767 marks[mark] = new
776 marks[mark] = new
768 marks.write()
777 marks.write()
769
778
770 def cleanupnode(ui, repo, name, nodes):
779 def cleanupnode(ui, repo, name, nodes):
771 """strip a group of nodes from the repository
780 """strip a group of nodes from the repository
772
781
773 The set of node to strip may contains unknown nodes."""
782 The set of node to strip may contains unknown nodes."""
774 ui.debug('should strip %s nodes %s\n' %
783 ui.debug('should strip %s nodes %s\n' %
775 (name, ', '.join([node.short(n) for n in nodes])))
784 (name, ', '.join([node.short(n) for n in nodes])))
776 lock = None
785 lock = None
777 try:
786 try:
778 lock = repo.lock()
787 lock = repo.lock()
779 # Find all node that need to be stripped
788 # Find all node that need to be stripped
780 # (we hg %lr instead of %ln to silently ignore unknown item
789 # (we hg %lr instead of %ln to silently ignore unknown item
781 nm = repo.changelog.nodemap
790 nm = repo.changelog.nodemap
782 nodes = [n for n in nodes if n in nm]
791 nodes = [n for n in nodes if n in nm]
783 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
792 roots = [c.node() for c in repo.set("roots(%ln)", nodes)]
784 for c in roots:
793 for c in roots:
785 # We should process node in reverse order to strip tip most first.
794 # We should process node in reverse order to strip tip most first.
786 # but this trigger a bug in changegroup hook.
795 # but this trigger a bug in changegroup hook.
787 # This would reduce bundle overhead
796 # This would reduce bundle overhead
788 repair.strip(ui, repo, c)
797 repair.strip(ui, repo, c)
789 finally:
798 finally:
790 lockmod.release(lock)
799 lockmod.release(lock)
@@ -1,179 +1,179 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 > graphlog=
5 > graphlog=
6 > histedit=
6 > histedit=
7 > EOF
7 > EOF
8
8
9 $ hg init r
9 $ hg init r
10 $ cd r
10 $ cd r
11
11
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 $ hg book -r 1 will-move-backwards
18 $ hg book -r 1 will-move-backwards
19 $ hg book -r 2 two
19 $ hg book -r 2 two
20 $ hg book -r 2 also-two
20 $ hg book -r 2 also-two
21 $ hg book -r 3 three
21 $ hg book -r 3 three
22 $ hg book -r 4 four
22 $ hg book -r 4 four
23 $ hg book -r tip five
23 $ hg book -r tip five
24 $ hg log --graph
24 $ hg log --graph
25 @ changeset: 5:652413bf663e
25 @ changeset: 5:652413bf663e
26 | bookmark: five
26 | bookmark: five
27 | tag: tip
27 | tag: tip
28 | user: test
28 | user: test
29 | date: Thu Jan 01 00:00:00 1970 +0000
29 | date: Thu Jan 01 00:00:00 1970 +0000
30 | summary: f
30 | summary: f
31 |
31 |
32 o changeset: 4:e860deea161a
32 o changeset: 4:e860deea161a
33 | bookmark: four
33 | bookmark: four
34 | user: test
34 | user: test
35 | date: Thu Jan 01 00:00:00 1970 +0000
35 | date: Thu Jan 01 00:00:00 1970 +0000
36 | summary: e
36 | summary: e
37 |
37 |
38 o changeset: 3:055a42cdd887
38 o changeset: 3:055a42cdd887
39 | bookmark: three
39 | bookmark: three
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: d
42 | summary: d
43 |
43 |
44 o changeset: 2:177f92b77385
44 o changeset: 2:177f92b77385
45 | bookmark: also-two
45 | bookmark: also-two
46 | bookmark: two
46 | bookmark: two
47 | user: test
47 | user: test
48 | date: Thu Jan 01 00:00:00 1970 +0000
48 | date: Thu Jan 01 00:00:00 1970 +0000
49 | summary: c
49 | summary: c
50 |
50 |
51 o changeset: 1:d2ae7f538514
51 o changeset: 1:d2ae7f538514
52 | bookmark: will-move-backwards
52 | bookmark: will-move-backwards
53 | user: test
53 | user: test
54 | date: Thu Jan 01 00:00:00 1970 +0000
54 | date: Thu Jan 01 00:00:00 1970 +0000
55 | summary: b
55 | summary: b
56 |
56 |
57 o changeset: 0:cb9a9f314b8b
57 o changeset: 0:cb9a9f314b8b
58 user: test
58 user: test
59 date: Thu Jan 01 00:00:00 1970 +0000
59 date: Thu Jan 01 00:00:00 1970 +0000
60 summary: a
60 summary: a
61
61
62 $ HGEDITOR=cat hg histedit 1
62 $ HGEDITOR=cat hg histedit 1
63 pick d2ae7f538514 1 b
63 pick d2ae7f538514 1 b
64 pick 177f92b77385 2 c
64 pick 177f92b77385 2 c
65 pick 055a42cdd887 3 d
65 pick 055a42cdd887 3 d
66 pick e860deea161a 4 e
66 pick e860deea161a 4 e
67 pick 652413bf663e 5 f
67 pick 652413bf663e 5 f
68
68
69 # Edit history between d2ae7f538514 and 652413bf663e
69 # Edit history between d2ae7f538514 and 652413bf663e
70 #
70 #
71 # Commands:
71 # Commands:
72 # p, pick = use commit
72 # p, pick = use commit
73 # e, edit = use commit, but stop for amending
73 # e, edit = use commit, but stop for amending
74 # f, fold = use commit, but fold into previous commit (combines N and N-1)
74 # f, fold = use commit, but fold into previous commit (combines N and N-1)
75 # d, drop = remove commit from history
75 # d, drop = remove commit from history
76 # m, mess = edit message without changing commit content
76 # m, mess = edit message without changing commit content
77 #
77 #
78 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 $ cat >> commands.txt <<EOF
79 $ cat >> commands.txt <<EOF
80 > pick 177f92b77385 2 c
80 > pick 177f92b77385 2 c
81 > drop d2ae7f538514 1 b
81 > drop d2ae7f538514 1 b
82 > pick 055a42cdd887 3 d
82 > pick 055a42cdd887 3 d
83 > fold e860deea161a 4 e
83 > fold e860deea161a 4 e
84 > pick 652413bf663e 5 f
84 > pick 652413bf663e 5 f
85 > EOF
85 > EOF
86 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
86 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
87 histedit: moving bookmarks also-two from 177f92b77385 to d36c0562f908
87 histedit: moving bookmarks also-two from 177f92b77385 to b346ab9a313d
88 histedit: moving bookmarks five from 652413bf663e to 0efacef7cb48
88 histedit: moving bookmarks five from 652413bf663e to cacdfd884a93
89 histedit: moving bookmarks four from e860deea161a to ae467701c500
89 histedit: moving bookmarks four from e860deea161a to 59d9f330561f
90 histedit: moving bookmarks three from 055a42cdd887 to ae467701c500
90 histedit: moving bookmarks three from 055a42cdd887 to 59d9f330561f
91 histedit: moving bookmarks two from 177f92b77385 to d36c0562f908
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/34a9919932c1-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:0efacef7cb48
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:ae467701c500
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:d36c0562f908
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 d36c0562f908 1 c
124 pick b346ab9a313d 1 c
125 pick ae467701c500 2 d
125 pick 59d9f330561f 2 d
126 pick 0efacef7cb48 3 f
126 pick cacdfd884a93 3 f
127
127
128 # Edit history between d36c0562f908 and 0efacef7cb48
128 # Edit history between b346ab9a313d and cacdfd884a93
129 #
129 #
130 # Commands:
130 # Commands:
131 # p, pick = use commit
131 # p, pick = use commit
132 # e, edit = use commit, but stop for amending
132 # e, edit = use commit, but stop for amending
133 # f, fold = use commit, but fold into previous commit (combines N and N-1)
133 # f, fold = use commit, but fold into previous commit (combines N and N-1)
134 # d, drop = remove commit from history
134 # d, drop = remove commit from history
135 # m, mess = edit message without changing commit content
135 # m, mess = edit message without changing commit content
136 #
136 #
137 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 $ cat > commands.txt << EOF
138 $ cat > commands.txt << EOF
139 > pick d36c0562f908 1 c
139 > pick b346ab9a313d 1 c
140 > pick 0efacef7cb48 3 f
140 > pick cacdfd884a93 3 f
141 > pick ae467701c500 2 d
141 > pick 59d9f330561f 2 d
142 > EOF
142 > EOF
143 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
143 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
144 histedit: moving bookmarks five from 0efacef7cb48 to 1be9c35b4cb2
144 histedit: moving bookmarks five from cacdfd884a93 to c04e50810e4b
145 histedit: moving bookmarks four from ae467701c500 to 1be9c35b4cb2
145 histedit: moving bookmarks four from 59d9f330561f to c04e50810e4b
146 histedit: moving bookmarks three from ae467701c500 to 1be9c35b4cb2
146 histedit: moving bookmarks three from 59d9f330561f to c04e50810e4b
147 saved backup bundle to $TESTTMP/r/.hg/strip-backup/ae467701c500-backup.hg (glob)
147 saved backup bundle to $TESTTMP/r/.hg/strip-backup/59d9f330561f-backup.hg (glob)
148
148
149 We expect 'five' to stay at tip, since the tipmost bookmark is most
149 We expect 'five' to stay at tip, since the tipmost bookmark is most
150 likely the useful signal.
150 likely the useful signal.
151
151
152 $ hg log --graph
152 $ hg log --graph
153 @ changeset: 3:1be9c35b4cb2
153 @ changeset: 3:c04e50810e4b
154 | bookmark: five
154 | bookmark: five
155 | bookmark: four
155 | bookmark: four
156 | bookmark: three
156 | bookmark: three
157 | tag: tip
157 | tag: tip
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:7c044e3e33a9
162 o changeset: 2:c13eb81022ca
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: f
165 | summary: f
166 |
166 |
167 o changeset: 1:d36c0562f908
167 o changeset: 1:b346ab9a313d
168 | bookmark: also-two
168 | bookmark: also-two
169 | bookmark: two
169 | bookmark: two
170 | user: test
170 | user: test
171 | date: Thu Jan 01 00:00:00 1970 +0000
171 | date: Thu Jan 01 00:00:00 1970 +0000
172 | summary: c
172 | summary: c
173 |
173 |
174 o changeset: 0:cb9a9f314b8b
174 o changeset: 0:cb9a9f314b8b
175 bookmark: will-move-backwards
175 bookmark: will-move-backwards
176 user: test
176 user: test
177 date: Thu Jan 01 00:00:00 1970 +0000
177 date: Thu Jan 01 00:00:00 1970 +0000
178 summary: a
178 summary: a
179
179
@@ -1,359 +1,359 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 > graphlog=
5 > graphlog=
6 > histedit=
6 > histedit=
7 > EOF
7 > EOF
8
8
9 $ EDITED="$TESTTMP/editedhistory"
9 $ EDITED="$TESTTMP/editedhistory"
10 $ cat > $EDITED <<EOF
10 $ cat > $EDITED <<EOF
11 > pick 177f92b77385 c
11 > pick 177f92b77385 c
12 > pick e860deea161a e
12 > pick e860deea161a e
13 > pick 652413bf663e f
13 > pick 652413bf663e f
14 > pick 055a42cdd887 d
14 > pick 055a42cdd887 d
15 > EOF
15 > EOF
16 $ initrepo ()
16 $ initrepo ()
17 > {
17 > {
18 > hg init r
18 > hg init r
19 > cd r
19 > cd r
20 > for x in a b c d e f ; do
20 > for x in a b c d e f ; do
21 > echo $x > $x
21 > echo $x > $x
22 > hg add $x
22 > hg add $x
23 > hg ci -m $x
23 > hg ci -m $x
24 > done
24 > done
25 > }
25 > }
26
26
27 $ initrepo
27 $ initrepo
28
28
29 log before edit
29 log before edit
30 $ hg log --graph
30 $ hg log --graph
31 @ changeset: 5:652413bf663e
31 @ changeset: 5:652413bf663e
32 | tag: tip
32 | tag: tip
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: f
35 | summary: f
36 |
36 |
37 o changeset: 4:e860deea161a
37 o changeset: 4:e860deea161a
38 | user: test
38 | user: test
39 | date: Thu Jan 01 00:00:00 1970 +0000
39 | date: Thu Jan 01 00:00:00 1970 +0000
40 | summary: e
40 | summary: e
41 |
41 |
42 o changeset: 3:055a42cdd887
42 o changeset: 3:055a42cdd887
43 | user: test
43 | user: test
44 | date: Thu Jan 01 00:00:00 1970 +0000
44 | date: Thu Jan 01 00:00:00 1970 +0000
45 | summary: d
45 | summary: d
46 |
46 |
47 o changeset: 2:177f92b77385
47 o changeset: 2:177f92b77385
48 | user: test
48 | user: test
49 | date: Thu Jan 01 00:00:00 1970 +0000
49 | date: Thu Jan 01 00:00:00 1970 +0000
50 | summary: c
50 | summary: c
51 |
51 |
52 o changeset: 1:d2ae7f538514
52 o changeset: 1:d2ae7f538514
53 | user: test
53 | user: test
54 | date: Thu Jan 01 00:00:00 1970 +0000
54 | date: Thu Jan 01 00:00:00 1970 +0000
55 | summary: b
55 | summary: b
56 |
56 |
57 o changeset: 0:cb9a9f314b8b
57 o changeset: 0:cb9a9f314b8b
58 user: test
58 user: test
59 date: Thu Jan 01 00:00:00 1970 +0000
59 date: Thu Jan 01 00:00:00 1970 +0000
60 summary: a
60 summary: a
61
61
62
62
63 show the edit commands offered
63 show the edit commands offered
64 $ HGEDITOR=cat hg histedit 177f92b77385
64 $ HGEDITOR=cat hg histedit 177f92b77385
65 pick 177f92b77385 2 c
65 pick 177f92b77385 2 c
66 pick 055a42cdd887 3 d
66 pick 055a42cdd887 3 d
67 pick e860deea161a 4 e
67 pick e860deea161a 4 e
68 pick 652413bf663e 5 f
68 pick 652413bf663e 5 f
69
69
70 # Edit history between 177f92b77385 and 652413bf663e
70 # Edit history between 177f92b77385 and 652413bf663e
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 N and N-1)
75 # f, fold = use commit, but fold into previous commit (combines N and N-1)
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
80
81 edit the history
81 edit the history
82 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
82 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
83 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
83 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 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
86 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
87
87
88 rules should end up in .hg/histedit-last-edit.txt:
88 rules should end up in .hg/histedit-last-edit.txt:
89 $ cat .hg/histedit-last-edit.txt
89 $ cat .hg/histedit-last-edit.txt
90 pick 177f92b77385 c
90 pick 177f92b77385 c
91 pick e860deea161a e
91 pick e860deea161a e
92 pick 652413bf663e f
92 pick 652413bf663e f
93 pick 055a42cdd887 d
93 pick 055a42cdd887 d
94
94
95 log after edit
95 log after edit
96 $ hg log --graph
96 $ hg log --graph
97 @ changeset: 5:853c68da763f
97 @ changeset: 5:07114f51870f
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: d
101 | summary: d
102 |
102 |
103 o changeset: 4:26f6a030ae82
103 o changeset: 4:8ade9693061e
104 | user: test
104 | user: test
105 | date: Thu Jan 01 00:00:00 1970 +0000
105 | date: Thu Jan 01 00:00:00 1970 +0000
106 | summary: f
106 | summary: f
107 |
107 |
108 o changeset: 3:b069cc29fb22
108 o changeset: 3:d8249471110a
109 | user: test
109 | user: test
110 | date: Thu Jan 01 00:00:00 1970 +0000
110 | date: Thu Jan 01 00:00:00 1970 +0000
111 | summary: e
111 | summary: e
112 |
112 |
113 o changeset: 2:177f92b77385
113 o changeset: 2:177f92b77385
114 | user: test
114 | user: test
115 | date: Thu Jan 01 00:00:00 1970 +0000
115 | date: Thu Jan 01 00:00:00 1970 +0000
116 | summary: c
116 | summary: c
117 |
117 |
118 o changeset: 1:d2ae7f538514
118 o changeset: 1:d2ae7f538514
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: b
121 | summary: b
122 |
122 |
123 o changeset: 0:cb9a9f314b8b
123 o changeset: 0:cb9a9f314b8b
124 user: test
124 user: test
125 date: Thu Jan 01 00:00:00 1970 +0000
125 date: Thu Jan 01 00:00:00 1970 +0000
126 summary: a
126 summary: a
127
127
128
128
129 put things back
129 put things back
130
130
131 $ cat > $EDITED <<EOF
131 $ cat > $EDITED <<EOF
132 > pick 177f92b77385 c
132 > pick 177f92b77385 c
133 > pick 853c68da763f d
133 > pick 07114f51870f d
134 > pick b069cc29fb22 e
134 > pick d8249471110a e
135 > pick 26f6a030ae82 f
135 > pick 8ade9693061e f
136 > EOF
136 > EOF
137 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
137 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
138 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
138 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
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 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 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
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142
142
143 $ hg log --graph
143 $ hg log --graph
144 @ changeset: 5:652413bf663e
144 @ changeset: 5:7eca9b5b1148
145 | tag: tip
145 | tag: tip
146 | user: test
146 | user: test
147 | date: Thu Jan 01 00:00:00 1970 +0000
147 | date: Thu Jan 01 00:00:00 1970 +0000
148 | summary: f
148 | summary: f
149 |
149 |
150 o changeset: 4:e860deea161a
150 o changeset: 4:915da888f2de
151 | user: test
151 | user: test
152 | date: Thu Jan 01 00:00:00 1970 +0000
152 | date: Thu Jan 01 00:00:00 1970 +0000
153 | summary: e
153 | summary: e
154 |
154 |
155 o changeset: 3:055a42cdd887
155 o changeset: 3:10517e47bbbb
156 | user: test
156 | user: test
157 | date: Thu Jan 01 00:00:00 1970 +0000
157 | date: Thu Jan 01 00:00:00 1970 +0000
158 | summary: d
158 | summary: d
159 |
159 |
160 o changeset: 2:177f92b77385
160 o changeset: 2:177f92b77385
161 | user: test
161 | user: test
162 | date: Thu Jan 01 00:00:00 1970 +0000
162 | date: Thu Jan 01 00:00:00 1970 +0000
163 | summary: c
163 | summary: c
164 |
164 |
165 o changeset: 1:d2ae7f538514
165 o changeset: 1:d2ae7f538514
166 | user: test
166 | user: test
167 | date: Thu Jan 01 00:00:00 1970 +0000
167 | date: Thu Jan 01 00:00:00 1970 +0000
168 | summary: b
168 | summary: b
169 |
169 |
170 o changeset: 0:cb9a9f314b8b
170 o changeset: 0:cb9a9f314b8b
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: a
173 summary: a
174
174
175
175
176 slightly different this time
176 slightly different this time
177
177
178 $ cat > $EDITED <<EOF
178 $ cat > $EDITED <<EOF
179 > pick 055a42cdd887 d
179 > pick 10517e47bbbb d
180 > pick 652413bf663e f
180 > pick 7eca9b5b1148 f
181 > pick e860deea161a e
181 > pick 915da888f2de e
182 > pick 177f92b77385 c
182 > pick 177f92b77385 c
183 > EOF
183 > EOF
184 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
184 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
185 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
185 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 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
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 $ hg log --graph
190 $ hg log --graph
191 @ changeset: 5:99a62755c625
191 @ changeset: 5:38b92f448761
192 | tag: tip
192 | tag: tip
193 | user: test
193 | user: test
194 | date: Thu Jan 01 00:00:00 1970 +0000
194 | date: Thu Jan 01 00:00:00 1970 +0000
195 | summary: c
195 | summary: c
196 |
196 |
197 o changeset: 4:7c6fdd608667
197 o changeset: 4:de71b079d9ce
198 | user: test
198 | user: test
199 | date: Thu Jan 01 00:00:00 1970 +0000
199 | date: Thu Jan 01 00:00:00 1970 +0000
200 | summary: e
200 | summary: e
201 |
201 |
202 o changeset: 3:c4f52e213402
202 o changeset: 3:be9ae3a309c6
203 | user: test
203 | user: test
204 | date: Thu Jan 01 00:00:00 1970 +0000
204 | date: Thu Jan 01 00:00:00 1970 +0000
205 | summary: f
205 | summary: f
206 |
206 |
207 o changeset: 2:bfe4a5a76b37
207 o changeset: 2:799205341b6b
208 | user: test
208 | user: test
209 | date: Thu Jan 01 00:00:00 1970 +0000
209 | date: Thu Jan 01 00:00:00 1970 +0000
210 | summary: d
210 | summary: d
211 |
211 |
212 o changeset: 1:d2ae7f538514
212 o changeset: 1:d2ae7f538514
213 | user: test
213 | user: test
214 | date: Thu Jan 01 00:00:00 1970 +0000
214 | date: Thu Jan 01 00:00:00 1970 +0000
215 | summary: b
215 | summary: b
216 |
216 |
217 o changeset: 0:cb9a9f314b8b
217 o changeset: 0:cb9a9f314b8b
218 user: test
218 user: test
219 date: Thu Jan 01 00:00:00 1970 +0000
219 date: Thu Jan 01 00:00:00 1970 +0000
220 summary: a
220 summary: a
221
221
222
222
223 keep prevents stripping dead revs
223 keep prevents stripping dead revs
224 $ cat > $EDITED <<EOF
224 $ cat > $EDITED <<EOF
225 > pick bfe4a5a76b37 d
225 > pick 799205341b6b d
226 > pick c4f52e213402 f
226 > pick be9ae3a309c6 f
227 > pick 99a62755c625 c
227 > pick 38b92f448761 c
228 > pick 7c6fdd608667 e
228 > pick de71b079d9ce e
229 > EOF
229 > EOF
230 $ HGEDITOR="cat \"$EDITED\" > " hg histedit bfe4a5a76b37 --keep 2>&1 | fixbundle
230 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 799205341b6b --keep 2>&1 | fixbundle
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 > cat > $EDITED <<EOF
235 > cat > $EDITED <<EOF
236 > pick 7c6fdd608667 e
236 > pick de71b079d9ce e
237 > pick 99a62755c625 c
237 > pick 38b92f448761 c
238 > EOF
238 > EOF
239 @ changeset: 7:99e266581538
239 @ changeset: 7:803ef1c6fcfd
240 | tag: tip
240 | tag: tip
241 | user: test
241 | user: test
242 | date: Thu Jan 01 00:00:00 1970 +0000
242 | date: Thu Jan 01 00:00:00 1970 +0000
243 | summary: e
243 | summary: e
244 |
244 |
245 o changeset: 6:5ad36efb0653
245 o changeset: 6:ece0b8d93dda
246 | parent: 3:c4f52e213402
246 | parent: 3:be9ae3a309c6
247 | user: test
247 | user: test
248 | date: Thu Jan 01 00:00:00 1970 +0000
248 | date: Thu Jan 01 00:00:00 1970 +0000
249 | summary: c
249 | summary: c
250 |
250 |
251 | o changeset: 5:99a62755c625
251 | o changeset: 5:38b92f448761
252 | | user: test
252 | | user: test
253 | | date: Thu Jan 01 00:00:00 1970 +0000
253 | | date: Thu Jan 01 00:00:00 1970 +0000
254 | | summary: c
254 | | summary: c
255 | |
255 | |
256 | o changeset: 4:7c6fdd608667
256 | o changeset: 4:de71b079d9ce
257 |/ user: test
257 |/ user: test
258 | date: Thu Jan 01 00:00:00 1970 +0000
258 | date: Thu Jan 01 00:00:00 1970 +0000
259 | summary: e
259 | summary: e
260 |
260 |
261 o changeset: 3:c4f52e213402
261 o changeset: 3:be9ae3a309c6
262 | user: test
262 | user: test
263 | date: Thu Jan 01 00:00:00 1970 +0000
263 | date: Thu Jan 01 00:00:00 1970 +0000
264 | summary: f
264 | summary: f
265 |
265 |
266 o changeset: 2:bfe4a5a76b37
266 o changeset: 2:799205341b6b
267 | user: test
267 | user: test
268 | date: Thu Jan 01 00:00:00 1970 +0000
268 | date: Thu Jan 01 00:00:00 1970 +0000
269 | summary: d
269 | summary: d
270 |
270 |
271 o changeset: 1:d2ae7f538514
271 o changeset: 1:d2ae7f538514
272 | user: test
272 | user: test
273 | date: Thu Jan 01 00:00:00 1970 +0000
273 | date: Thu Jan 01 00:00:00 1970 +0000
274 | summary: b
274 | summary: b
275 |
275 |
276 o changeset: 0:cb9a9f314b8b
276 o changeset: 0:cb9a9f314b8b
277 user: test
277 user: test
278 date: Thu Jan 01 00:00:00 1970 +0000
278 date: Thu Jan 01 00:00:00 1970 +0000
279 summary: a
279 summary: a
280
280
281
281
282 try with --rev
282 try with --rev
283 $ hg histedit --commands "$EDITED" --rev -2 2>&1 | fixbundle
283 $ hg histedit --commands "$EDITED" --rev -2 2>&1 | fixbundle
284 abort: may not use changesets other than the ones listed
284 abort: may not use changesets other than the ones listed
285 $ hg log --graph
285 $ hg log --graph
286 @ changeset: 7:99e266581538
286 @ changeset: 7:803ef1c6fcfd
287 | tag: tip
287 | tag: tip
288 | user: test
288 | user: test
289 | date: Thu Jan 01 00:00:00 1970 +0000
289 | date: Thu Jan 01 00:00:00 1970 +0000
290 | summary: e
290 | summary: e
291 |
291 |
292 o changeset: 6:5ad36efb0653
292 o changeset: 6:ece0b8d93dda
293 | parent: 3:c4f52e213402
293 | parent: 3:be9ae3a309c6
294 | user: test
294 | user: test
295 | date: Thu Jan 01 00:00:00 1970 +0000
295 | date: Thu Jan 01 00:00:00 1970 +0000
296 | summary: c
296 | summary: c
297 |
297 |
298 | o changeset: 5:99a62755c625
298 | o changeset: 5:38b92f448761
299 | | user: test
299 | | user: test
300 | | date: Thu Jan 01 00:00:00 1970 +0000
300 | | date: Thu Jan 01 00:00:00 1970 +0000
301 | | summary: c
301 | | summary: c
302 | |
302 | |
303 | o changeset: 4:7c6fdd608667
303 | o changeset: 4:de71b079d9ce
304 |/ user: test
304 |/ user: test
305 | date: Thu Jan 01 00:00:00 1970 +0000
305 | date: Thu Jan 01 00:00:00 1970 +0000
306 | summary: e
306 | summary: e
307 |
307 |
308 o changeset: 3:c4f52e213402
308 o changeset: 3:be9ae3a309c6
309 | user: test
309 | user: test
310 | date: Thu Jan 01 00:00:00 1970 +0000
310 | date: Thu Jan 01 00:00:00 1970 +0000
311 | summary: f
311 | summary: f
312 |
312 |
313 o changeset: 2:bfe4a5a76b37
313 o changeset: 2:799205341b6b
314 | user: test
314 | user: test
315 | date: Thu Jan 01 00:00:00 1970 +0000
315 | date: Thu Jan 01 00:00:00 1970 +0000
316 | summary: d
316 | summary: d
317 |
317 |
318 o changeset: 1:d2ae7f538514
318 o changeset: 1:d2ae7f538514
319 | user: test
319 | user: test
320 | date: Thu Jan 01 00:00:00 1970 +0000
320 | date: Thu Jan 01 00:00:00 1970 +0000
321 | summary: b
321 | summary: b
322 |
322 |
323 o changeset: 0:cb9a9f314b8b
323 o changeset: 0:cb9a9f314b8b
324 user: test
324 user: test
325 date: Thu Jan 01 00:00:00 1970 +0000
325 date: Thu Jan 01 00:00:00 1970 +0000
326 summary: a
326 summary: a
327
327
328
328
329 should also work if a commit message is missing
329 should also work if a commit message is missing
330 $ BUNDLE="$TESTDIR/missing-comment.hg"
330 $ BUNDLE="$TESTDIR/missing-comment.hg"
331 $ hg init missing
331 $ hg init missing
332 $ cd missing
332 $ cd missing
333 $ hg unbundle $BUNDLE
333 $ hg unbundle $BUNDLE
334 adding changesets
334 adding changesets
335 adding manifests
335 adding manifests
336 adding file changes
336 adding file changes
337 added 3 changesets with 3 changes to 1 files
337 added 3 changesets with 3 changes to 1 files
338 (run 'hg update' to get a working copy)
338 (run 'hg update' to get a working copy)
339 $ hg co tip
339 $ hg co tip
340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
341 $ hg log --graph
341 $ hg log --graph
342 @ changeset: 2:bd22688093b3
342 @ changeset: 2:bd22688093b3
343 | tag: tip
343 | tag: tip
344 | user: Robert Altman <robert.altman@telventDTN.com>
344 | user: Robert Altman <robert.altman@telventDTN.com>
345 | date: Mon Nov 28 16:40:04 2011 +0000
345 | date: Mon Nov 28 16:40:04 2011 +0000
346 | summary: Update file.
346 | summary: Update file.
347 |
347 |
348 o changeset: 1:3b3e956f9171
348 o changeset: 1:3b3e956f9171
349 | user: Robert Altman <robert.altman@telventDTN.com>
349 | user: Robert Altman <robert.altman@telventDTN.com>
350 | date: Mon Nov 28 16:37:57 2011 +0000
350 | date: Mon Nov 28 16:37:57 2011 +0000
351 |
351 |
352 o changeset: 0:141947992243
352 o changeset: 0:141947992243
353 user: Robert Altman <robert.altman@telventDTN.com>
353 user: Robert Altman <robert.altman@telventDTN.com>
354 date: Mon Nov 28 16:35:28 2011 +0000
354 date: Mon Nov 28 16:35:28 2011 +0000
355 summary: Checked in text file
355 summary: Checked in text file
356
356
357 $ hg histedit 0
357 $ hg histedit 0
358 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 $ cd ..
359 $ cd ..
@@ -1,107 +1,126 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 > graphlog=
5 > graphlog=
6 > histedit=
6 > histedit=
7 > EOF
7 > EOF
8
8
9 $ EDITED="$TESTTMP/editedhistory"
9 $ EDITED="$TESTTMP/editedhistory"
10 $ cat > $EDITED <<EOF
10 $ cat > $EDITED <<EOF
11 > drop 177f92b77385 c
11 > drop 177f92b77385 c
12 > pick e860deea161a e
12 > pick e860deea161a e
13 > pick 652413bf663e f
13 > pick 652413bf663e f
14 > pick 055a42cdd887 d
14 > pick 055a42cdd887 d
15 > EOF
15 > EOF
16 $ initrepo ()
16 $ initrepo ()
17 > {
17 > {
18 > hg init r
18 > hg init r
19 > cd r
19 > cd r
20 > for x in a b c d e f ; do
20 > for x in a b c d e f ; do
21 > echo $x > $x
21 > echo $x > $x
22 > hg add $x
22 > hg add $x
23 > hg ci -m $x
23 > hg ci -m $x
24 > done
24 > done
25 > }
25 > }
26
26
27 $ initrepo
27 $ initrepo
28
28
29 log before edit
29 log before edit
30 $ hg log --graph
30 $ hg log --graph
31 @ changeset: 5:652413bf663e
31 @ changeset: 5:652413bf663e
32 | tag: tip
32 | tag: tip
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: f
35 | summary: f
36 |
36 |
37 o changeset: 4:e860deea161a
37 o changeset: 4:e860deea161a
38 | user: test
38 | user: test
39 | date: Thu Jan 01 00:00:00 1970 +0000
39 | date: Thu Jan 01 00:00:00 1970 +0000
40 | summary: e
40 | summary: e
41 |
41 |
42 o changeset: 3:055a42cdd887
42 o changeset: 3:055a42cdd887
43 | user: test
43 | user: test
44 | date: Thu Jan 01 00:00:00 1970 +0000
44 | date: Thu Jan 01 00:00:00 1970 +0000
45 | summary: d
45 | summary: d
46 |
46 |
47 o changeset: 2:177f92b77385
47 o changeset: 2:177f92b77385
48 | user: test
48 | user: test
49 | date: Thu Jan 01 00:00:00 1970 +0000
49 | date: Thu Jan 01 00:00:00 1970 +0000
50 | summary: c
50 | summary: c
51 |
51 |
52 o changeset: 1:d2ae7f538514
52 o changeset: 1:d2ae7f538514
53 | user: test
53 | user: test
54 | date: Thu Jan 01 00:00:00 1970 +0000
54 | date: Thu Jan 01 00:00:00 1970 +0000
55 | summary: b
55 | summary: b
56 |
56 |
57 o changeset: 0:cb9a9f314b8b
57 o changeset: 0:cb9a9f314b8b
58 user: test
58 user: test
59 date: Thu Jan 01 00:00:00 1970 +0000
59 date: Thu Jan 01 00:00:00 1970 +0000
60 summary: a
60 summary: a
61
61
62
62
63 edit the history
63 edit the history
64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
65 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
65 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
66 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
66 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
69
69
70 log after edit
70 log after edit
71 $ hg log --graph
71 $ hg log --graph
72 @ changeset: 4:708943196e52
72 @ changeset: 4:f518305ce889
73 | tag: tip
73 | tag: tip
74 | user: test
74 | user: test
75 | date: Thu Jan 01 00:00:00 1970 +0000
75 | date: Thu Jan 01 00:00:00 1970 +0000
76 | summary: d
76 | summary: d
77 |
77 |
78 o changeset: 3:75cbdffecadb
78 o changeset: 3:a4f7421b80f7
79 | user: test
79 | user: test
80 | date: Thu Jan 01 00:00:00 1970 +0000
80 | date: Thu Jan 01 00:00:00 1970 +0000
81 | summary: f
81 | summary: f
82 |
82 |
83 o changeset: 2:493dc0964412
83 o changeset: 2:ee283cb5f2d5
84 | user: test
84 | user: test
85 | date: Thu Jan 01 00:00:00 1970 +0000
85 | date: Thu Jan 01 00:00:00 1970 +0000
86 | summary: e
86 | summary: e
87 |
87 |
88 o changeset: 1:d2ae7f538514
88 o changeset: 1:d2ae7f538514
89 | user: test
89 | user: test
90 | date: Thu Jan 01 00:00:00 1970 +0000
90 | date: Thu Jan 01 00:00:00 1970 +0000
91 | summary: b
91 | summary: b
92 |
92 |
93 o changeset: 0:cb9a9f314b8b
93 o changeset: 0:cb9a9f314b8b
94 user: test
94 user: test
95 date: Thu Jan 01 00:00:00 1970 +0000
95 date: Thu Jan 01 00:00:00 1970 +0000
96 summary: a
96 summary: a
97
97
98
98
99 Check histedit_source
100
101 $ hg log --debug --rev f518305ce889
102 changeset: 4:f518305ce889c07cb5bd05522176d75590ef3324
103 tag: tip
104 phase: draft
105 parent: 3:a4f7421b80f79fcc59fff01bcbf4a53d127dd6d3
106 parent: -1:0000000000000000000000000000000000000000
107 manifest: 4:d3d4f51c157ff242c32ff745d4799aaa26ccda44
108 user: test
109 date: Thu Jan 01 00:00:00 1970 +0000
110 files+: d
111 extra: branch=default
112 extra: histedit_source=055a42cdd88768532f9cf79daa407fc8d138de9b
113 description:
114 d
115
116
117
99 manifest after edit
118 manifest after edit
100 $ hg manifest
119 $ hg manifest
101 a
120 a
102 b
121 b
103 d
122 d
104 e
123 e
105 f
124 f
106
125
107 $ cd ..
126 $ cd ..
@@ -1,191 +1,211 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 > graphlog=
5 > graphlog=
6 > histedit=
6 > histedit=
7 > EOF
7 > EOF
8
8
9 $ EDITED="$TESTTMP/editedhistory"
9 $ EDITED="$TESTTMP/editedhistory"
10 $ cat > $EDITED <<EOF
10 $ cat > $EDITED <<EOF
11 > pick 177f92b77385 c
11 > pick 177f92b77385 c
12 > pick 055a42cdd887 d
12 > pick 055a42cdd887 d
13 > edit e860deea161a e
13 > edit e860deea161a e
14 > pick 652413bf663e f
14 > pick 652413bf663e f
15 > EOF
15 > EOF
16 $ initrepo ()
16 $ initrepo ()
17 > {
17 > {
18 > hg init r
18 > hg init r
19 > cd r
19 > cd r
20 > for x in a b c d e f ; do
20 > for x in a b c d e f ; do
21 > echo $x > $x
21 > echo $x > $x
22 > hg add $x
22 > hg add $x
23 > hg ci -m $x
23 > hg ci -m $x
24 > done
24 > done
25 > }
25 > }
26
26
27 $ initrepo
27 $ initrepo
28
28
29 log before edit
29 log before edit
30 $ hg log --graph
30 $ hg log --graph
31 @ changeset: 5:652413bf663e
31 @ changeset: 5:652413bf663e
32 | tag: tip
32 | tag: tip
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: f
35 | summary: f
36 |
36 |
37 o changeset: 4:e860deea161a
37 o changeset: 4:e860deea161a
38 | user: test
38 | user: test
39 | date: Thu Jan 01 00:00:00 1970 +0000
39 | date: Thu Jan 01 00:00:00 1970 +0000
40 | summary: e
40 | summary: e
41 |
41 |
42 o changeset: 3:055a42cdd887
42 o changeset: 3:055a42cdd887
43 | user: test
43 | user: test
44 | date: Thu Jan 01 00:00:00 1970 +0000
44 | date: Thu Jan 01 00:00:00 1970 +0000
45 | summary: d
45 | summary: d
46 |
46 |
47 o changeset: 2:177f92b77385
47 o changeset: 2:177f92b77385
48 | user: test
48 | user: test
49 | date: Thu Jan 01 00:00:00 1970 +0000
49 | date: Thu Jan 01 00:00:00 1970 +0000
50 | summary: c
50 | summary: c
51 |
51 |
52 o changeset: 1:d2ae7f538514
52 o changeset: 1:d2ae7f538514
53 | user: test
53 | user: test
54 | date: Thu Jan 01 00:00:00 1970 +0000
54 | date: Thu Jan 01 00:00:00 1970 +0000
55 | summary: b
55 | summary: b
56 |
56 |
57 o changeset: 0:cb9a9f314b8b
57 o changeset: 0:cb9a9f314b8b
58 user: test
58 user: test
59 date: Thu Jan 01 00:00:00 1970 +0000
59 date: Thu Jan 01 00:00:00 1970 +0000
60 summary: a
60 summary: a
61
61
62
62
63 edit the history
63 edit the history
64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
65 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
65 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
66 abort: Make changes as needed, you may commit or record as needed now.
66 abort: Make changes as needed, you may commit or record as needed now.
67 When you are finished, run hg histedit --continue to resume.
67 When you are finished, run hg histedit --continue to resume.
68
68
69 Go at a random point and try to continue
69 Go at a random point and try to continue
70
70
71 $ hg id -n
71 $ hg id -n
72 3+
72 3+
73 $ hg up 0
73 $ hg up 0
74 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
74 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
75 $ HGEDITOR='echo foobaz > ' hg histedit --continue
75 $ HGEDITOR='echo foobaz > ' hg histedit --continue
76 abort: working directory parent is not a descendant of 055a42cdd887
76 abort: working directory parent is not a descendant of 055a42cdd887
77 (update to 055a42cdd887 or descendant and run "hg histedit --continue" again)
77 (update to 055a42cdd887 or descendant and run "hg histedit --continue" again)
78 [255]
78 [255]
79 $ hg up 3
79 $ hg up 3
80 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
80 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
81
81
82 commit, then edit the revision
82 commit, then edit the revision
83 $ hg ci -m 'wat'
83 $ hg ci -m 'wat'
84 created new head
84 created new head
85 $ echo a > e
85 $ echo a > e
86 $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle
86 $ HGEDITOR='echo foobaz > ' hg histedit --continue 2>&1 | fixbundle
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
89
90 $ hg log --graph
90 $ hg log --graph
91 @ changeset: 6:bf757c081cd0
91 @ changeset: 6:b5f70786f9b0
92 | tag: tip
92 | tag: tip
93 | user: test
93 | user: test
94 | date: Thu Jan 01 00:00:00 1970 +0000
94 | date: Thu Jan 01 00:00:00 1970 +0000
95 | summary: f
95 | summary: f
96 |
96 |
97 o changeset: 5:d6b15fed32d4
97 o changeset: 5:a5e1ba2f7afb
98 | user: test
98 | user: test
99 | date: Thu Jan 01 00:00:00 1970 +0000
99 | date: Thu Jan 01 00:00:00 1970 +0000
100 | summary: foobaz
100 | summary: foobaz
101 |
101 |
102 o changeset: 4:1a60820cd1f6
102 o changeset: 4:1a60820cd1f6
103 | user: test
103 | user: test
104 | date: Thu Jan 01 00:00:00 1970 +0000
104 | date: Thu Jan 01 00:00:00 1970 +0000
105 | summary: wat
105 | summary: wat
106 |
106 |
107 o changeset: 3:055a42cdd887
107 o changeset: 3:055a42cdd887
108 | user: test
108 | user: test
109 | date: Thu Jan 01 00:00:00 1970 +0000
109 | date: Thu Jan 01 00:00:00 1970 +0000
110 | summary: d
110 | summary: d
111 |
111 |
112 o changeset: 2:177f92b77385
112 o changeset: 2:177f92b77385
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: 1:d2ae7f538514
117 o changeset: 1:d2ae7f538514
118 | user: test
118 | user: test
119 | date: Thu Jan 01 00:00:00 1970 +0000
119 | date: Thu Jan 01 00:00:00 1970 +0000
120 | summary: b
120 | summary: b
121 |
121 |
122 o changeset: 0:cb9a9f314b8b
122 o changeset: 0:cb9a9f314b8b
123 user: test
123 user: test
124 date: Thu Jan 01 00:00:00 1970 +0000
124 date: Thu Jan 01 00:00:00 1970 +0000
125 summary: a
125 summary: a
126
126
127
127
128 $ hg cat e
128 $ hg cat e
129 a
129 a
130
130
131 check histedit_source
132
133 $ hg log --debug --rev 5
134 changeset: 5:a5e1ba2f7afb899ef1581cea528fd885d2fca70d
135 phase: draft
136 parent: 4:1a60820cd1f6004a362aa622ebc47d59bc48eb34
137 parent: -1:0000000000000000000000000000000000000000
138 manifest: 5:5ad3be8791f39117565557781f5464363b918a45
139 user: test
140 date: Thu Jan 01 00:00:00 1970 +0000
141 files: e
142 extra: branch=default
143 extra: histedit_source=e860deea161a2f77de56603b340ebbb4536308ae
144 description:
145 foobaz
146
147
148
131 $ cat > $EDITED <<EOF
149 $ cat > $EDITED <<EOF
132 > edit bf757c081cd0 f
150 > edit b5f70786f9b0 f
133 > EOF
151 > EOF
134 $ HGEDITOR="cat \"$EDITED\" > " hg histedit tip 2>&1 | fixbundle
152 $ HGEDITOR="cat \"$EDITED\" > " hg histedit tip 2>&1 | fixbundle
135 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
153 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
136 abort: Make changes as needed, you may commit or record as needed now.
154 abort: Make changes as needed, you may commit or record as needed now.
137 When you are finished, run hg histedit --continue to resume.
155 When you are finished, run hg histedit --continue to resume.
138 $ hg status
156 $ hg status
139 A f
157 A f
140 $ HGEDITOR='true' hg histedit --continue
158 $ HGEDITOR='true' hg histedit --continue
141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 saved backup bundle to $TESTTMP/r/.hg/strip-backup/b5f70786f9b0-backup.hg (glob)
161
142 $ hg status
162 $ hg status
143
163
144 log after edit
164 log after edit
145 $ hg log --limit 1
165 $ hg log --limit 1
146 changeset: 6:bf757c081cd0
166 changeset: 6:a107ee126658
147 tag: tip
167 tag: tip
148 user: test
168 user: test
149 date: Thu Jan 01 00:00:00 1970 +0000
169 date: Thu Jan 01 00:00:00 1970 +0000
150 summary: f
170 summary: f
151
171
152
172
153 say we'll change the message, but don't.
173 say we'll change the message, but don't.
154 $ cat > ../edit.sh <<EOF
174 $ cat > ../edit.sh <<EOF
155 > cat "\$1" | sed s/pick/mess/ > tmp
175 > cat "\$1" | sed s/pick/mess/ > tmp
156 > mv tmp "\$1"
176 > mv tmp "\$1"
157 > EOF
177 > EOF
158 $ HGEDITOR="sh ../edit.sh" hg histedit tip 2>&1 | fixbundle
178 $ HGEDITOR="sh ../edit.sh" hg histedit tip 2>&1 | fixbundle
159 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
179 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
160 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
180 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 $ hg status
181 $ hg status
162 $ hg log --limit 1
182 $ hg log --limit 1
163 changeset: 6:bf757c081cd0
183 changeset: 6:1fd3b2fe7754
164 tag: tip
184 tag: tip
165 user: test
185 user: test
166 date: Thu Jan 01 00:00:00 1970 +0000
186 date: Thu Jan 01 00:00:00 1970 +0000
167 summary: f
187 summary: f
168
188
169
189
170 modify the message
190 modify the message
171 $ cat > $EDITED <<EOF
191 $ cat > $EDITED <<EOF
172 > mess bf757c081cd0 f
192 > mess 1fd3b2fe7754 f
173 > EOF
193 > EOF
174 $ HGEDITOR="cat \"$EDITED\" > " hg histedit tip 2>&1 | fixbundle
194 $ HGEDITOR="cat \"$EDITED\" > " hg histedit tip 2>&1 | fixbundle
175 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
195 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
176 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
196 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 $ hg status
197 $ hg status
178 $ hg log --limit 1
198 $ hg log --limit 1
179 changeset: 6:0b16746f8e89
199 changeset: 6:5585e802ef99
180 tag: tip
200 tag: tip
181 user: test
201 user: test
182 date: Thu Jan 01 00:00:00 1970 +0000
202 date: Thu Jan 01 00:00:00 1970 +0000
183 summary: mess bf757c081cd0 f
203 summary: mess 1fd3b2fe7754 f
184
204
185
205
186 rollback should not work after a histedit
206 rollback should not work after a histedit
187 $ hg rollback
207 $ hg rollback
188 no rollback information available
208 no rollback information available
189 [1]
209 [1]
190
210
191 $ cd ..
211 $ cd ..
@@ -1,184 +1,184 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 > graphlog=
5 > graphlog=
6 > histedit=
6 > histedit=
7 > EOF
7 > EOF
8
8
9 $ initrepo ()
9 $ initrepo ()
10 > {
10 > {
11 > hg init $1
11 > hg init $1
12 > cd $1
12 > cd $1
13 > for x in a b c d e f ; do
13 > for x in a b c d e f ; do
14 > echo $x$x$x$x$x > $x
14 > echo $x$x$x$x$x > $x
15 > hg add $x
15 > hg add $x
16 > done
16 > done
17 > hg ci -m 'Initial commit'
17 > hg ci -m 'Initial commit'
18 > for x in a b c d e f ; do
18 > for x in a b c d e f ; do
19 > echo $x > $x
19 > echo $x > $x
20 > hg ci -m $x
20 > hg ci -m $x
21 > done
21 > done
22 > echo 'I can haz no commute' > e
22 > echo 'I can haz no commute' > e
23 > hg ci -m 'does not commute with e'
23 > hg ci -m 'does not commute with e'
24 > cd ..
24 > cd ..
25 > }
25 > }
26
26
27 $ initrepo r
27 $ initrepo r
28 $ cd r
28 $ cd r
29 Initial generation of the command files
29 Initial generation of the command files
30
30
31 $ EDITED="$TESTTMP/editedhistory"
31 $ EDITED="$TESTTMP/editedhistory"
32 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
32 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
33 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
33 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
34 $ hg log --template 'fold {node|short} {rev} {desc}\n' -r 7 >> $EDITED
34 $ hg log --template 'fold {node|short} {rev} {desc}\n' -r 7 >> $EDITED
35 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
35 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
36 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
36 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
37 $ cat $EDITED
37 $ cat $EDITED
38 pick 65a9a84f33fd 3 c
38 pick 65a9a84f33fd 3 c
39 pick 00f1c5383965 4 d
39 pick 00f1c5383965 4 d
40 fold 39522b764e3d 7 does not commute with e
40 fold 39522b764e3d 7 does not commute with e
41 pick 7b4e2f4b7bcd 5 e
41 pick 7b4e2f4b7bcd 5 e
42 pick 500cac37a696 6 f
42 pick 500cac37a696 6 f
43
43
44 log before edit
44 log before edit
45 $ hg log --graph
45 $ hg log --graph
46 @ changeset: 7:39522b764e3d
46 @ changeset: 7:39522b764e3d
47 | tag: tip
47 | tag: tip
48 | user: test
48 | user: test
49 | date: Thu Jan 01 00:00:00 1970 +0000
49 | date: Thu Jan 01 00:00:00 1970 +0000
50 | summary: does not commute with e
50 | summary: does not commute with e
51 |
51 |
52 o changeset: 6:500cac37a696
52 o changeset: 6:500cac37a696
53 | user: test
53 | user: test
54 | date: Thu Jan 01 00:00:00 1970 +0000
54 | date: Thu Jan 01 00:00:00 1970 +0000
55 | summary: f
55 | summary: f
56 |
56 |
57 o changeset: 5:7b4e2f4b7bcd
57 o changeset: 5:7b4e2f4b7bcd
58 | user: test
58 | user: test
59 | date: Thu Jan 01 00:00:00 1970 +0000
59 | date: Thu Jan 01 00:00:00 1970 +0000
60 | summary: e
60 | summary: e
61 |
61 |
62 o changeset: 4:00f1c5383965
62 o changeset: 4:00f1c5383965
63 | user: test
63 | user: test
64 | date: Thu Jan 01 00:00:00 1970 +0000
64 | date: Thu Jan 01 00:00:00 1970 +0000
65 | summary: d
65 | summary: d
66 |
66 |
67 o changeset: 3:65a9a84f33fd
67 o changeset: 3:65a9a84f33fd
68 | user: test
68 | user: test
69 | date: Thu Jan 01 00:00:00 1970 +0000
69 | date: Thu Jan 01 00:00:00 1970 +0000
70 | summary: c
70 | summary: c
71 |
71 |
72 o changeset: 2:da6535b52e45
72 o changeset: 2:da6535b52e45
73 | user: test
73 | user: test
74 | date: Thu Jan 01 00:00:00 1970 +0000
74 | date: Thu Jan 01 00:00:00 1970 +0000
75 | summary: b
75 | summary: b
76 |
76 |
77 o changeset: 1:c1f09da44841
77 o changeset: 1:c1f09da44841
78 | user: test
78 | user: test
79 | date: Thu Jan 01 00:00:00 1970 +0000
79 | date: Thu Jan 01 00:00:00 1970 +0000
80 | summary: a
80 | summary: a
81 |
81 |
82 o changeset: 0:1715188a53c7
82 o changeset: 0:1715188a53c7
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:00 1970 +0000
84 date: Thu Jan 01 00:00:00 1970 +0000
85 summary: Initial commit
85 summary: Initial commit
86
86
87
87
88 edit the history
88 edit the history
89 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
89 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
90 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 merging e
91 merging e
92 warning: conflicts during merge.
92 warning: conflicts during merge.
93 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
93 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
94 abort: Fix up the change and run hg histedit --continue
94 abort: Fix up the change and run hg histedit --continue
95
95
96 fix up
96 fix up
97 $ echo 'I can haz no commute' > e
97 $ echo 'I can haz no commute' > e
98 $ hg resolve --mark e
98 $ hg resolve --mark e
99 $ cat > cat.py <<EOF
99 $ cat > cat.py <<EOF
100 > import sys
100 > import sys
101 > print open(sys.argv[1]).read()
101 > print open(sys.argv[1]).read()
102 > print
102 > print
103 > print
103 > print
104 > EOF
104 > EOF
105 $ HGEDITOR="python cat.py" hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
105 $ HGEDITOR="python cat.py" hg histedit --continue 2>&1 | fixbundle | grep -v '2 files removed'
106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 d
107 d
108 ***
108 ***
109 does not commute with e
109 does not commute with e
110
110
111
111
112
112
113 HG: Enter commit message. Lines beginning with 'HG:' are removed.
113 HG: Enter commit message. Lines beginning with 'HG:' are removed.
114 HG: Leave message empty to abort commit.
114 HG: Leave message empty to abort commit.
115 HG: --
115 HG: --
116 HG: user: test
116 HG: user: test
117 HG: branch 'default'
117 HG: branch 'default'
118 HG: changed d
118 HG: changed d
119 HG: changed e
119 HG: changed e
120
120
121
121
122
122
123 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
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 merging e
125 merging e
126 warning: conflicts during merge.
126 warning: conflicts during merge.
127 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
127 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
128 abort: Fix up the change and run hg histedit --continue
128 abort: Fix up the change and run hg histedit --continue
129
129
130 just continue this time
130 just continue this time
131 $ hg revert -r 'p1()' e
131 $ hg revert -r 'p1()' e
132 $ hg resolve --mark e
132 $ hg resolve --mark e
133 $ hg histedit --continue 2>&1 | fixbundle
133 $ hg histedit --continue 2>&1 | fixbundle
134 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
134 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
136
136
137 log after edit
137 log after edit
138 $ hg log --graph
138 $ hg log --graph
139 @ changeset: 5:2696a654c663
139 @ changeset: 5:d9cf42e54966
140 | tag: tip
140 | tag: tip
141 | user: test
141 | user: test
142 | date: Thu Jan 01 00:00:00 1970 +0000
142 | date: Thu Jan 01 00:00:00 1970 +0000
143 | summary: f
143 | summary: f
144 |
144 |
145 o changeset: 4:ec2c1cf833a8
145 o changeset: 4:10486af2e984
146 | user: test
146 | user: test
147 | date: Thu Jan 01 00:00:00 1970 +0000
147 | date: Thu Jan 01 00:00:00 1970 +0000
148 | summary: d
148 | summary: d
149 |
149 |
150 o changeset: 3:65a9a84f33fd
150 o changeset: 3:65a9a84f33fd
151 | user: test
151 | user: test
152 | date: Thu Jan 01 00:00:00 1970 +0000
152 | date: Thu Jan 01 00:00:00 1970 +0000
153 | summary: c
153 | summary: c
154 |
154 |
155 o changeset: 2:da6535b52e45
155 o changeset: 2:da6535b52e45
156 | user: test
156 | user: test
157 | date: Thu Jan 01 00:00:00 1970 +0000
157 | date: Thu Jan 01 00:00:00 1970 +0000
158 | summary: b
158 | summary: b
159 |
159 |
160 o changeset: 1:c1f09da44841
160 o changeset: 1:c1f09da44841
161 | user: test
161 | user: test
162 | date: Thu Jan 01 00:00:00 1970 +0000
162 | date: Thu Jan 01 00:00:00 1970 +0000
163 | summary: a
163 | summary: a
164 |
164 |
165 o changeset: 0:1715188a53c7
165 o changeset: 0:1715188a53c7
166 user: test
166 user: test
167 date: Thu Jan 01 00:00:00 1970 +0000
167 date: Thu Jan 01 00:00:00 1970 +0000
168 summary: Initial commit
168 summary: Initial commit
169
169
170
170
171 contents of e
171 contents of e
172 $ hg cat e
172 $ hg cat e
173 I can haz no commute
173 I can haz no commute
174
174
175 manifest
175 manifest
176 $ hg manifest
176 $ hg manifest
177 a
177 a
178 b
178 b
179 c
179 c
180 d
180 d
181 e
181 e
182 f
182 f
183
183
184 $ cd ..
184 $ cd ..
@@ -1,295 +1,317 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 > graphlog=
5 > graphlog=
6 > histedit=
6 > histedit=
7 > EOF
7 > EOF
8
8
9 $ EDITED="$TESTTMP/editedhistory"
9 $ EDITED="$TESTTMP/editedhistory"
10 $ cat > $EDITED <<EOF
10 $ cat > $EDITED <<EOF
11 > pick e860deea161a e
11 > pick e860deea161a e
12 > pick 652413bf663e f
12 > pick 652413bf663e f
13 > fold 177f92b77385 c
13 > fold 177f92b77385 c
14 > pick 055a42cdd887 d
14 > pick 055a42cdd887 d
15 > EOF
15 > EOF
16 $ initrepo ()
16 $ initrepo ()
17 > {
17 > {
18 > hg init r
18 > hg init r
19 > cd r
19 > cd r
20 > for x in a b c d e f ; do
20 > for x in a b c d e f ; do
21 > echo $x > $x
21 > echo $x > $x
22 > hg add $x
22 > hg add $x
23 > hg ci -m $x
23 > hg ci -m $x
24 > done
24 > done
25 > }
25 > }
26
26
27 $ initrepo
27 $ initrepo
28
28
29 log before edit
29 log before edit
30 $ hg log --graph
30 $ hg log --graph
31 @ changeset: 5:652413bf663e
31 @ changeset: 5:652413bf663e
32 | tag: tip
32 | tag: tip
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: f
35 | summary: f
36 |
36 |
37 o changeset: 4:e860deea161a
37 o changeset: 4:e860deea161a
38 | user: test
38 | user: test
39 | date: Thu Jan 01 00:00:00 1970 +0000
39 | date: Thu Jan 01 00:00:00 1970 +0000
40 | summary: e
40 | summary: e
41 |
41 |
42 o changeset: 3:055a42cdd887
42 o changeset: 3:055a42cdd887
43 | user: test
43 | user: test
44 | date: Thu Jan 01 00:00:00 1970 +0000
44 | date: Thu Jan 01 00:00:00 1970 +0000
45 | summary: d
45 | summary: d
46 |
46 |
47 o changeset: 2:177f92b77385
47 o changeset: 2:177f92b77385
48 | user: test
48 | user: test
49 | date: Thu Jan 01 00:00:00 1970 +0000
49 | date: Thu Jan 01 00:00:00 1970 +0000
50 | summary: c
50 | summary: c
51 |
51 |
52 o changeset: 1:d2ae7f538514
52 o changeset: 1:d2ae7f538514
53 | user: test
53 | user: test
54 | date: Thu Jan 01 00:00:00 1970 +0000
54 | date: Thu Jan 01 00:00:00 1970 +0000
55 | summary: b
55 | summary: b
56 |
56 |
57 o changeset: 0:cb9a9f314b8b
57 o changeset: 0:cb9a9f314b8b
58 user: test
58 user: test
59 date: Thu Jan 01 00:00:00 1970 +0000
59 date: Thu Jan 01 00:00:00 1970 +0000
60 summary: a
60 summary: a
61
61
62
62
63 edit the history
63 edit the history
64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
64 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 177f92b77385 2>&1 | fixbundle
65 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
65 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
66 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
66 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
68 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
72
72
73 log after edit
73 log after edit
74 $ hg log --graph
74 $ hg log --graph
75 @ changeset: 4:82b0c1ff1777
75 @ changeset: 4:7e0a290363ed
76 | tag: tip
76 | tag: tip
77 | user: test
77 | user: test
78 | date: Thu Jan 01 00:00:00 1970 +0000
78 | date: Thu Jan 01 00:00:00 1970 +0000
79 | summary: d
79 | summary: d
80 |
80 |
81 o changeset: 3:150aafb44a91
81 o changeset: 3:5e24935bad3d
82 | user: test
82 | user: test
83 | date: Thu Jan 01 00:00:00 1970 +0000
83 | date: Thu Jan 01 00:00:00 1970 +0000
84 | summary: pick e860deea161a e
84 | summary: pick e860deea161a e
85 |
85 |
86 o changeset: 2:493dc0964412
86 o changeset: 2:ee283cb5f2d5
87 | user: test
87 | user: test
88 | date: Thu Jan 01 00:00:00 1970 +0000
88 | date: Thu Jan 01 00:00:00 1970 +0000
89 | summary: e
89 | summary: e
90 |
90 |
91 o changeset: 1:d2ae7f538514
91 o changeset: 1:d2ae7f538514
92 | user: test
92 | user: test
93 | date: Thu Jan 01 00:00:00 1970 +0000
93 | date: Thu Jan 01 00:00:00 1970 +0000
94 | summary: b
94 | summary: b
95 |
95 |
96 o changeset: 0:cb9a9f314b8b
96 o changeset: 0:cb9a9f314b8b
97 user: test
97 user: test
98 date: Thu Jan 01 00:00:00 1970 +0000
98 date: Thu Jan 01 00:00:00 1970 +0000
99 summary: a
99 summary: a
100
100
101
101
102 post-fold manifest
102 post-fold manifest
103 $ hg manifest
103 $ hg manifest
104 a
104 a
105 b
105 b
106 c
106 c
107 d
107 d
108 e
108 e
109 f
109 f
110
110
111
112 check histedit_source
113
114 $ hg log --debug --rev 3
115 changeset: 3:5e24935bad3d5a4486de3b90f233e991465ced72
116 phase: draft
117 parent: 2:ee283cb5f2d5955443f23a27b697a04339e9a39a
118 parent: -1:0000000000000000000000000000000000000000
119 manifest: 3:81eede616954057198ead0b2c73b41d1f392829a
120 user: test
121 date: Thu Jan 01 00:00:00 1970 +0000
122 files+: c f
123 extra: branch=default
124 extra: histedit_source=a4f7421b80f79fcc59fff01bcbf4a53d127dd6d3,177f92b773850b59254aa5e923436f921b55483b
125 description:
126 pick e860deea161a e
127 pick 652413bf663e f
128 fold 177f92b77385 c
129 pick 055a42cdd887 d
130
131
132
111 $ cd ..
133 $ cd ..
112
134
113 folding and creating no new change doesn't break:
135 folding and creating no new change doesn't break:
114 $ mkdir fold-to-empty-test
136 $ mkdir fold-to-empty-test
115 $ cd fold-to-empty-test
137 $ cd fold-to-empty-test
116 $ hg init
138 $ hg init
117 $ printf "1\n2\n3\n" > file
139 $ printf "1\n2\n3\n" > file
118 $ hg add file
140 $ hg add file
119 $ hg commit -m '1+2+3'
141 $ hg commit -m '1+2+3'
120 $ echo 4 >> file
142 $ echo 4 >> file
121 $ hg commit -m '+4'
143 $ hg commit -m '+4'
122 $ echo 5 >> file
144 $ echo 5 >> file
123 $ hg commit -m '+5'
145 $ hg commit -m '+5'
124 $ echo 6 >> file
146 $ echo 6 >> file
125 $ hg commit -m '+6'
147 $ hg commit -m '+6'
126 $ hg log --graph
148 $ hg log --graph
127 @ changeset: 3:251d831eeec5
149 @ changeset: 3:251d831eeec5
128 | tag: tip
150 | tag: tip
129 | user: test
151 | user: test
130 | date: Thu Jan 01 00:00:00 1970 +0000
152 | date: Thu Jan 01 00:00:00 1970 +0000
131 | summary: +6
153 | summary: +6
132 |
154 |
133 o changeset: 2:888f9082bf99
155 o changeset: 2:888f9082bf99
134 | user: test
156 | user: test
135 | date: Thu Jan 01 00:00:00 1970 +0000
157 | date: Thu Jan 01 00:00:00 1970 +0000
136 | summary: +5
158 | summary: +5
137 |
159 |
138 o changeset: 1:617f94f13c0f
160 o changeset: 1:617f94f13c0f
139 | user: test
161 | user: test
140 | date: Thu Jan 01 00:00:00 1970 +0000
162 | date: Thu Jan 01 00:00:00 1970 +0000
141 | summary: +4
163 | summary: +4
142 |
164 |
143 o changeset: 0:0189ba417d34
165 o changeset: 0:0189ba417d34
144 user: test
166 user: test
145 date: Thu Jan 01 00:00:00 1970 +0000
167 date: Thu Jan 01 00:00:00 1970 +0000
146 summary: 1+2+3
168 summary: 1+2+3
147
169
148
170
149 $ cat > editor.py <<EOF
171 $ cat > editor.py <<EOF
150 > import re, sys
172 > import re, sys
151 > rules = sys.argv[1]
173 > rules = sys.argv[1]
152 > data = open(rules).read()
174 > data = open(rules).read()
153 > data = re.sub(r'pick ([0-9a-f]{12} 2 \+5)', r'drop \1', data)
175 > data = re.sub(r'pick ([0-9a-f]{12} 2 \+5)', r'drop \1', data)
154 > data = re.sub(r'pick ([0-9a-f]{12} 2 \+6)', r'fold \1', data)
176 > data = re.sub(r'pick ([0-9a-f]{12} 2 \+6)', r'fold \1', data)
155 > open(rules, 'w').write(data)
177 > open(rules, 'w').write(data)
156 > EOF
178 > EOF
157
179
158 $ HGEDITOR='python editor.py' hg histedit 1
180 $ HGEDITOR='python editor.py' hg histedit 1
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
181 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 merging file
182 merging file
161 warning: conflicts during merge.
183 warning: conflicts during merge.
162 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
184 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
163 abort: Fix up the change and run hg histedit --continue
185 abort: Fix up the change and run hg histedit --continue
164 [255]
186 [255]
165 There were conflicts, we keep P1 content. This
187 There were conflicts, we keep P1 content. This
166 should effectively drop the changes from +6.
188 should effectively drop the changes from +6.
167 $ hg status
189 $ hg status
168 M file
190 M file
169 ? editor.py
191 ? editor.py
170 ? file.orig
192 ? file.orig
171 $ hg resolve -l
193 $ hg resolve -l
172 U file
194 U file
173 $ hg revert -r 'p1()' file
195 $ hg revert -r 'p1()' file
174 $ hg resolve --mark file
196 $ hg resolve --mark file
175 $ hg histedit --continue
197 $ hg histedit --continue
176 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
198 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
177 saved backup bundle to $TESTTMP/*-backup.hg (glob)
199 saved backup bundle to $TESTTMP/*-backup.hg (glob)
178 $ hg log --graph
200 $ hg log --graph
179 @ changeset: 1:617f94f13c0f
201 @ changeset: 1:617f94f13c0f
180 | tag: tip
202 | tag: tip
181 | user: test
203 | user: test
182 | date: Thu Jan 01 00:00:00 1970 +0000
204 | date: Thu Jan 01 00:00:00 1970 +0000
183 | summary: +4
205 | summary: +4
184 |
206 |
185 o changeset: 0:0189ba417d34
207 o changeset: 0:0189ba417d34
186 user: test
208 user: test
187 date: Thu Jan 01 00:00:00 1970 +0000
209 date: Thu Jan 01 00:00:00 1970 +0000
188 summary: 1+2+3
210 summary: 1+2+3
189
211
190
212
191 $ cd ..
213 $ cd ..
192
214
193 Test corner case where folded revision is separated from its parent by a
215 Test corner case where folded revision is separated from its parent by a
194 dropped revision.
216 dropped revision.
195
217
196
218
197 $ hg init fold-with-dropped
219 $ hg init fold-with-dropped
198 $ cd fold-with-dropped
220 $ cd fold-with-dropped
199 $ printf "1\n2\n3\n" > file
221 $ printf "1\n2\n3\n" > file
200 $ hg commit -Am '1+2+3'
222 $ hg commit -Am '1+2+3'
201 adding file
223 adding file
202 $ echo 4 >> file
224 $ echo 4 >> file
203 $ hg commit -m '+4'
225 $ hg commit -m '+4'
204 $ echo 5 >> file
226 $ echo 5 >> file
205 $ hg commit -m '+5'
227 $ hg commit -m '+5'
206 $ echo 6 >> file
228 $ echo 6 >> file
207 $ hg commit -m '+6'
229 $ hg commit -m '+6'
208 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
230 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
209 @ 3:251d831eeec5 +6
231 @ 3:251d831eeec5 +6
210 |
232 |
211 o 2:888f9082bf99 +5
233 o 2:888f9082bf99 +5
212 |
234 |
213 o 1:617f94f13c0f +4
235 o 1:617f94f13c0f +4
214 |
236 |
215 o 0:0189ba417d34 1+2+3
237 o 0:0189ba417d34 1+2+3
216
238
217 $ EDITED="$TESTTMP/editcommands"
239 $ EDITED="$TESTTMP/editcommands"
218 $ cat > $EDITED <<EOF
240 $ cat > $EDITED <<EOF
219 > pick 617f94f13c0f 1 +4
241 > pick 617f94f13c0f 1 +4
220 > drop 888f9082bf99 2 +5
242 > drop 888f9082bf99 2 +5
221 > fold 251d831eeec5 3 +6
243 > fold 251d831eeec5 3 +6
222 > EOF
244 > EOF
223 $ HGEDITOR="cat $EDITED >" hg histedit 1
245 $ HGEDITOR="cat $EDITED >" hg histedit 1
224 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
225 merging file
247 merging file
226 warning: conflicts during merge.
248 warning: conflicts during merge.
227 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
249 merging file incomplete! (edit conflicts, then use 'hg resolve --mark')
228 abort: Fix up the change and run hg histedit --continue
250 abort: Fix up the change and run hg histedit --continue
229 [255]
251 [255]
230 $ cat > file << EOF
252 $ cat > file << EOF
231 > 1
253 > 1
232 > 2
254 > 2
233 > 3
255 > 3
234 > 4
256 > 4
235 > 5
257 > 5
236 > EOF
258 > EOF
237 $ hg resolve --mark file
259 $ hg resolve --mark file
238 $ hg commit -m '+5.2'
260 $ hg commit -m '+5.2'
239 created new head
261 created new head
240 $ echo 6 >> file
262 $ echo 6 >> file
241 $ HGEDITOR=cat hg histedit --continue
263 $ HGEDITOR=cat hg histedit --continue
242 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
264 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
243 +4
265 +4
244 ***
266 ***
245 +5.2
267 +5.2
246 ***
268 ***
247 +6
269 +6
248
270
249
271
250
272
251 HG: Enter commit message. Lines beginning with 'HG:' are removed.
273 HG: Enter commit message. Lines beginning with 'HG:' are removed.
252 HG: Leave message empty to abort commit.
274 HG: Leave message empty to abort commit.
253 HG: --
275 HG: --
254 HG: user: test
276 HG: user: test
255 HG: branch 'default'
277 HG: branch 'default'
256 HG: changed file
278 HG: changed file
257 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
259 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-backup.hg (glob)
281 saved backup bundle to $TESTTMP/fold-with-dropped/.hg/strip-backup/617f94f13c0f-backup.hg (glob)
260 $ hg log -G
282 $ hg log -G
261 @ changeset: 1:e29e02896e6c
283 @ changeset: 1:10c647b2cdd5
262 | tag: tip
284 | tag: tip
263 | user: test
285 | user: test
264 | date: Thu Jan 01 00:00:00 1970 +0000
286 | date: Thu Jan 01 00:00:00 1970 +0000
265 | summary: +4
287 | summary: +4
266 |
288 |
267 o changeset: 0:0189ba417d34
289 o changeset: 0:0189ba417d34
268 user: test
290 user: test
269 date: Thu Jan 01 00:00:00 1970 +0000
291 date: Thu Jan 01 00:00:00 1970 +0000
270 summary: 1+2+3
292 summary: 1+2+3
271
293
272 $ hg export tip
294 $ hg export tip
273 # HG changeset patch
295 # HG changeset patch
274 # User test
296 # User test
275 # Date 0 0
297 # Date 0 0
276 # Node ID e29e02896e6c2b149d2228a0a64b4f3a9a4237f3
298 # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
277 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
299 # Parent 0189ba417d34df9dda55f88b637dcae9917b5964
278 +4
300 +4
279 ***
301 ***
280 +5.2
302 +5.2
281 ***
303 ***
282 +6
304 +6
283
305
284 diff -r 0189ba417d34 -r e29e02896e6c file
306 diff -r 0189ba417d34 -r 10c647b2cdd5 file
285 --- a/file Thu Jan 01 00:00:00 1970 +0000
307 --- a/file Thu Jan 01 00:00:00 1970 +0000
286 +++ b/file Thu Jan 01 00:00:00 1970 +0000
308 +++ b/file Thu Jan 01 00:00:00 1970 +0000
287 @@ -1,3 +1,6 @@
309 @@ -1,3 +1,6 @@
288 1
310 1
289 2
311 2
290 3
312 3
291 +4
313 +4
292 +5
314 +5
293 +6
315 +6
294 $ cd ..
316 $ cd ..
295
317
@@ -1,187 +1,191 b''
1 test for old histedit issue #6:
1 test for old histedit issue #6:
2 editing a changeset without any actual change would corrupt the repository
2 editing a changeset without any actual change would corrupt the repository
3
3
4 $ . "$TESTDIR/histedit-helpers.sh"
4 $ . "$TESTDIR/histedit-helpers.sh"
5
5
6 $ cat >> $HGRCPATH <<EOF
6 $ cat >> $HGRCPATH <<EOF
7 > [extensions]
7 > [extensions]
8 > graphlog=
8 > graphlog=
9 > histedit=
9 > histedit=
10 > EOF
10 > EOF
11
11
12 $ initrepo ()
12 $ initrepo ()
13 > {
13 > {
14 > dir="$1"
14 > dir="$1"
15 > comment="$2"
15 > comment="$2"
16 > if [ -n "${comment}" ]; then
16 > if [ -n "${comment}" ]; then
17 > echo % ${comment}
17 > echo % ${comment}
18 > echo % ${comment} | sed 's:.:-:g'
18 > echo % ${comment} | sed 's:.:-:g'
19 > fi
19 > fi
20 > hg init ${dir}
20 > hg init ${dir}
21 > cd ${dir}
21 > cd ${dir}
22 > for x in a b c d e f ; do
22 > for x in a b c d e f ; do
23 > echo $x > $x
23 > echo $x > $x
24 > hg add $x
24 > hg add $x
25 > hg ci -m $x
25 > hg ci -m $x
26 > done
26 > done
27 > cd ..
27 > cd ..
28 > }
28 > }
29
29
30 $ geneditor ()
30 $ geneditor ()
31 > {
31 > {
32 > # generate an editor script for selecting changesets to be edited
32 > # generate an editor script for selecting changesets to be edited
33 > choice=$1 # changesets that should be edited (using sed line ranges)
33 > choice=$1 # changesets that should be edited (using sed line ranges)
34 > cat <<EOF | sed 's:^....::'
34 > cat <<EOF | sed 's:^....::'
35 > # editing the rules, replacing 'pick' with 'edit' for the chosen lines
35 > # editing the rules, replacing 'pick' with 'edit' for the chosen lines
36 > sed '${choice}s:^pick:edit:' "\$1" > "\${1}.tmp"
36 > sed '${choice}s:^pick:edit:' "\$1" > "\${1}.tmp"
37 > mv "\${1}.tmp" "\$1"
37 > mv "\${1}.tmp" "\$1"
38 > # displaying the resulting rules, minus comments and empty lines
38 > # displaying the resulting rules, minus comments and empty lines
39 > sed '/^#/d;/^$/d;s:^:| :' "\$1" >&2
39 > sed '/^#/d;/^$/d;s:^:| :' "\$1" >&2
40 > EOF
40 > EOF
41 > }
41 > }
42
42
43 $ startediting ()
43 $ startediting ()
44 > {
44 > {
45 > # begin an editing session
45 > # begin an editing session
46 > choice="$1" # changesets that should be edited
46 > choice="$1" # changesets that should be edited
47 > number="$2" # number of changesets considered (from tip)
47 > number="$2" # number of changesets considered (from tip)
48 > comment="$3"
48 > comment="$3"
49 > geneditor "${choice}" > edit.sh
49 > geneditor "${choice}" > edit.sh
50 > echo % start editing the history ${comment}
50 > echo % start editing the history ${comment}
51 > HGEDITOR="sh ./edit.sh" hg histedit -- -${number} 2>&1 | fixbundle
51 > HGEDITOR="sh ./edit.sh" hg histedit -- -${number} 2>&1 | fixbundle
52 > }
52 > }
53
53
54 $ continueediting ()
54 $ continueediting ()
55 > {
55 > {
56 > # continue an edit already in progress
56 > # continue an edit already in progress
57 > editor="$1" # message editor when finalizing editing
57 > editor="$1" # message editor when finalizing editing
58 > comment="$2"
58 > comment="$2"
59 > echo % finalize changeset editing ${comment}
59 > echo % finalize changeset editing ${comment}
60 > HGEDITOR=${editor} hg histedit --continue 2>&1 | fixbundle
60 > HGEDITOR=${editor} hg histedit --continue 2>&1 | fixbundle
61 > }
61 > }
62
62
63 $ graphlog ()
63 $ graphlog ()
64 > {
64 > {
65 > comment="${1:-log}"
65 > comment="${1:-log}"
66 > echo % "${comment}"
66 > echo % "${comment}"
67 > hg glog --template '{rev} {node} \"{desc|firstline}\"\n'
67 > hg glog --template '{rev} {node} \"{desc|firstline}\"\n'
68 > }
68 > }
69
69
70
70
71 $ initrepo r1 "test editing with no change"
71 $ initrepo r1 "test editing with no change"
72 % test editing with no change
72 % test editing with no change
73 -----------------------------
73 -----------------------------
74 $ cd r1
74 $ cd r1
75 $ graphlog "log before editing"
75 $ graphlog "log before editing"
76 % log before editing
76 % log before editing
77 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
77 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
78 |
78 |
79 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
79 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
80 |
80 |
81 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
81 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
82 |
82 |
83 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
83 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
84 |
84 |
85 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
85 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
86 |
86 |
87 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
87 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
88
88
89 $ startediting 2 3 "(not changing anything)" # edit the 2nd of 3 changesets
89 $ startediting 2 3 "(not changing anything)" # edit the 2nd of 3 changesets
90 % start editing the history (not changing anything)
90 % start editing the history (not changing anything)
91 | pick 055a42cdd887 3 d
91 | pick 055a42cdd887 3 d
92 | edit e860deea161a 4 e
92 | edit e860deea161a 4 e
93 | pick 652413bf663e 5 f
93 | pick 652413bf663e 5 f
94 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
94 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
95 abort: Make changes as needed, you may commit or record as needed now.
95 abort: Make changes as needed, you may commit or record as needed now.
96 When you are finished, run hg histedit --continue to resume.
96 When you are finished, run hg histedit --continue to resume.
97 $ continueediting true "(leaving commit message unaltered)"
97 $ continueediting true "(leaving commit message unaltered)"
98 % finalize changeset editing (leaving commit message unaltered)
98 % finalize changeset editing (leaving commit message unaltered)
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
101
100
102
101 check state of working copy
103 check state of working copy
102 $ hg id
104 $ hg id
103 652413bf663e tip
105 794fe033d0a0 tip
104
106
105 $ graphlog "log after history editing"
107 $ graphlog "log after history editing"
106 % log after history editing
108 % log after history editing
107 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
109 @ 5 794fe033d0a030f8df77c5de945fca35c9181c30 "f"
108 |
110 |
109 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
111 o 4 04d2fab980779f332dec458cc944f28de8b43435 "e"
110 |
112 |
111 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
113 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
112 |
114 |
113 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
115 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
114 |
116 |
115 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
117 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
116 |
118 |
117 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
119 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
118
120
119
121
120 $ cd ..
122 $ cd ..
121
123
122 $ initrepo r2 "test editing with no change, then abort"
124 $ initrepo r2 "test editing with no change, then abort"
123 % test editing with no change, then abort
125 % test editing with no change, then abort
124 -----------------------------------------
126 -----------------------------------------
125 $ cd r2
127 $ cd r2
126 $ graphlog "log before editing"
128 $ graphlog "log before editing"
127 % log before editing
129 % log before editing
128 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
130 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
129 |
131 |
130 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
132 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
131 |
133 |
132 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
134 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
133 |
135 |
134 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
136 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
135 |
137 |
136 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
138 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
137 |
139 |
138 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
140 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
139
141
140 $ startediting 1,2 3 "(not changing anything)" # edit the 1st two of 3 changesets
142 $ startediting 1,2 3 "(not changing anything)" # edit the 1st two of 3 changesets
141 % start editing the history (not changing anything)
143 % start editing the history (not changing anything)
142 | edit 055a42cdd887 3 d
144 | edit 055a42cdd887 3 d
143 | edit e860deea161a 4 e
145 | edit e860deea161a 4 e
144 | pick 652413bf663e 5 f
146 | pick 652413bf663e 5 f
145 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
147 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
146 abort: Make changes as needed, you may commit or record as needed now.
148 abort: Make changes as needed, you may commit or record as needed now.
147 When you are finished, run hg histedit --continue to resume.
149 When you are finished, run hg histedit --continue to resume.
148 $ continueediting true "(leaving commit message unaltered)"
150 $ continueediting true "(leaving commit message unaltered)"
149 % finalize changeset editing (leaving commit message unaltered)
151 % finalize changeset editing (leaving commit message unaltered)
150 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
152 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 abort: Make changes as needed, you may commit or record as needed now.
153 abort: Make changes as needed, you may commit or record as needed now.
152 When you are finished, run hg histedit --continue to resume.
154 When you are finished, run hg histedit --continue to resume.
153 $ graphlog "log after first edit"
155 $ graphlog "log after first edit"
154 % log after first edit
156 % log after first edit
155 o 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
157 @ 6 e5ae3ca2f1ffdbd89ec41ebc273a231f7c3022f2 "d"
156 |
158 |
157 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
159 | o 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
158 |
160 | |
159 @ 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
161 | o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
160 |
162 | |
163 | o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
164 |/
161 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
165 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
162 |
166 |
163 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
167 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
164 |
168 |
165 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
169 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
166
170
167
171
168 abort editing session
172 abort editing session
169 $ hg histedit --abort 2>&1 | fixbundle
173 $ hg histedit --abort 2>&1 | fixbundle
170 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
171
175
172 $ graphlog "log after abort"
176 $ graphlog "log after abort"
173 % log after abort
177 % log after abort
174 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
178 @ 5 652413bf663ef2a641cab26574e46d5f5a64a55a "f"
175 |
179 |
176 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
180 o 4 e860deea161a2f77de56603b340ebbb4536308ae "e"
177 |
181 |
178 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
182 o 3 055a42cdd88768532f9cf79daa407fc8d138de9b "d"
179 |
183 |
180 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
184 o 2 177f92b773850b59254aa5e923436f921b55483b "c"
181 |
185 |
182 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
186 o 1 d2ae7f538514cd87c17547b0de4cea71fe1af9fb "b"
183 |
187 |
184 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
188 o 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b "a"
185
189
186
190
187 $ cd ..
191 $ cd ..
@@ -1,295 +1,295 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 > graphlog=
5 > graphlog=
6 > histedit=
6 > histedit=
7 > EOF
7 > EOF
8
8
9 $ initrepo ()
9 $ initrepo ()
10 > {
10 > {
11 > hg init $1
11 > hg init $1
12 > cd $1
12 > cd $1
13 > for x in a b c d e f ; do
13 > for x in a b c d e f ; do
14 > echo $x$x$x$x$x > $x
14 > echo $x$x$x$x$x > $x
15 > hg add $x
15 > hg add $x
16 > done
16 > done
17 > hg ci -m 'Initial commit'
17 > hg ci -m 'Initial commit'
18 > for x in a b c d e f ; do
18 > for x in a b c d e f ; do
19 > echo $x > $x
19 > echo $x > $x
20 > hg ci -m $x
20 > hg ci -m $x
21 > done
21 > done
22 > echo 'I can haz no commute' > e
22 > echo 'I can haz no commute' > e
23 > hg ci -m 'does not commute with e'
23 > hg ci -m 'does not commute with e'
24 > cd ..
24 > cd ..
25 > }
25 > }
26
26
27 $ initrepo r1
27 $ initrepo r1
28 $ cd r1
28 $ cd r1
29
29
30 Initial generation of the command files
30 Initial generation of the command files
31
31
32 $ EDITED="$TESTTMP/editedhistory"
32 $ EDITED="$TESTTMP/editedhistory"
33 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
33 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
34 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
34 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
35 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 7 >> $EDITED
35 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 7 >> $EDITED
36 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
36 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
37 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
37 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
38 $ cat $EDITED
38 $ cat $EDITED
39 pick 65a9a84f33fd 3 c
39 pick 65a9a84f33fd 3 c
40 pick 00f1c5383965 4 d
40 pick 00f1c5383965 4 d
41 pick 39522b764e3d 7 does not commute with e
41 pick 39522b764e3d 7 does not commute with e
42 pick 7b4e2f4b7bcd 5 e
42 pick 7b4e2f4b7bcd 5 e
43 pick 500cac37a696 6 f
43 pick 500cac37a696 6 f
44
44
45 log before edit
45 log before edit
46 $ hg log --graph
46 $ hg log --graph
47 @ changeset: 7:39522b764e3d
47 @ changeset: 7:39522b764e3d
48 | tag: tip
48 | tag: tip
49 | user: test
49 | user: test
50 | date: Thu Jan 01 00:00:00 1970 +0000
50 | date: Thu Jan 01 00:00:00 1970 +0000
51 | summary: does not commute with e
51 | summary: does not commute with e
52 |
52 |
53 o changeset: 6:500cac37a696
53 o changeset: 6:500cac37a696
54 | user: test
54 | user: test
55 | date: Thu Jan 01 00:00:00 1970 +0000
55 | date: Thu Jan 01 00:00:00 1970 +0000
56 | summary: f
56 | summary: f
57 |
57 |
58 o changeset: 5:7b4e2f4b7bcd
58 o changeset: 5:7b4e2f4b7bcd
59 | user: test
59 | user: test
60 | date: Thu Jan 01 00:00:00 1970 +0000
60 | date: Thu Jan 01 00:00:00 1970 +0000
61 | summary: e
61 | summary: e
62 |
62 |
63 o changeset: 4:00f1c5383965
63 o changeset: 4:00f1c5383965
64 | user: test
64 | user: test
65 | date: Thu Jan 01 00:00:00 1970 +0000
65 | date: Thu Jan 01 00:00:00 1970 +0000
66 | summary: d
66 | summary: d
67 |
67 |
68 o changeset: 3:65a9a84f33fd
68 o changeset: 3:65a9a84f33fd
69 | user: test
69 | user: test
70 | date: Thu Jan 01 00:00:00 1970 +0000
70 | date: Thu Jan 01 00:00:00 1970 +0000
71 | summary: c
71 | summary: c
72 |
72 |
73 o changeset: 2:da6535b52e45
73 o changeset: 2:da6535b52e45
74 | user: test
74 | user: test
75 | date: Thu Jan 01 00:00:00 1970 +0000
75 | date: Thu Jan 01 00:00:00 1970 +0000
76 | summary: b
76 | summary: b
77 |
77 |
78 o changeset: 1:c1f09da44841
78 o changeset: 1:c1f09da44841
79 | user: test
79 | user: test
80 | date: Thu Jan 01 00:00:00 1970 +0000
80 | date: Thu Jan 01 00:00:00 1970 +0000
81 | summary: a
81 | summary: a
82 |
82 |
83 o changeset: 0:1715188a53c7
83 o changeset: 0:1715188a53c7
84 user: test
84 user: test
85 date: Thu Jan 01 00:00:00 1970 +0000
85 date: Thu Jan 01 00:00:00 1970 +0000
86 summary: Initial commit
86 summary: Initial commit
87
87
88
88
89 edit the history
89 edit the history
90 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
90 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
91 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 merging e
92 merging e
93 warning: conflicts during merge.
93 warning: conflicts during merge.
94 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
94 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
95 abort: Fix up the change and run hg histedit --continue
95 abort: Fix up the change and run hg histedit --continue
96
96
97 abort the edit
97 abort the edit
98 $ hg histedit --abort 2>&1 | fixbundle
98 $ hg histedit --abort 2>&1 | fixbundle
99 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
100
100
101
101
102 second edit set
102 second edit set
103
103
104 $ hg log --graph
104 $ hg log --graph
105 @ changeset: 7:39522b764e3d
105 @ changeset: 7:39522b764e3d
106 | tag: tip
106 | tag: tip
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: does not commute with e
109 | summary: does not commute with e
110 |
110 |
111 o changeset: 6:500cac37a696
111 o changeset: 6:500cac37a696
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: f
114 | summary: f
115 |
115 |
116 o changeset: 5:7b4e2f4b7bcd
116 o changeset: 5:7b4e2f4b7bcd
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: e
119 | summary: e
120 |
120 |
121 o changeset: 4:00f1c5383965
121 o changeset: 4:00f1c5383965
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: d
124 | summary: d
125 |
125 |
126 o changeset: 3:65a9a84f33fd
126 o changeset: 3:65a9a84f33fd
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: c
129 | summary: c
130 |
130 |
131 o changeset: 2:da6535b52e45
131 o changeset: 2:da6535b52e45
132 | user: test
132 | user: test
133 | date: Thu Jan 01 00:00:00 1970 +0000
133 | date: Thu Jan 01 00:00:00 1970 +0000
134 | summary: b
134 | summary: b
135 |
135 |
136 o changeset: 1:c1f09da44841
136 o changeset: 1:c1f09da44841
137 | user: test
137 | user: test
138 | date: Thu Jan 01 00:00:00 1970 +0000
138 | date: Thu Jan 01 00:00:00 1970 +0000
139 | summary: a
139 | summary: a
140 |
140 |
141 o changeset: 0:1715188a53c7
141 o changeset: 0:1715188a53c7
142 user: test
142 user: test
143 date: Thu Jan 01 00:00:00 1970 +0000
143 date: Thu Jan 01 00:00:00 1970 +0000
144 summary: Initial commit
144 summary: Initial commit
145
145
146
146
147 edit the history
147 edit the history
148 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
148 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
149 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 merging e
150 merging e
151 warning: conflicts during merge.
151 warning: conflicts during merge.
152 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
152 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
153 abort: Fix up the change and run hg histedit --continue
153 abort: Fix up the change and run hg histedit --continue
154
154
155 fix up
155 fix up
156 $ echo 'I can haz no commute' > e
156 $ echo 'I can haz no commute' > e
157 $ hg resolve --mark e
157 $ hg resolve --mark e
158 $ hg histedit --continue 2>&1 | fixbundle
158 $ hg histedit --continue 2>&1 | fixbundle
159 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 merging e
160 merging e
161 warning: conflicts during merge.
161 warning: conflicts during merge.
162 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
162 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
163 abort: Fix up the change and run hg histedit --continue
163 abort: Fix up the change and run hg histedit --continue
164
164
165 This failure is caused by 7b4e2f4b7bcd "e" not rebasing the non commutative
165 This failure is caused by 7b4e2f4b7bcd "e" not rebasing the non commutative
166 former children.
166 former children.
167
167
168 just continue this time
168 just continue this time
169 $ hg revert -r 'p1()' e
169 $ hg revert -r 'p1()' e
170 $ hg resolve --mark e
170 $ hg resolve --mark e
171 $ hg histedit --continue 2>&1 | fixbundle
171 $ hg histedit --continue 2>&1 | fixbundle
172 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
172 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
174
174
175 log after edit
175 log after edit
176 $ hg log --graph
176 $ hg log --graph
177 @ changeset: 6:8e082d1a72ea
177 @ changeset: 6:7efe1373e4bc
178 | tag: tip
178 | tag: tip
179 | user: test
179 | user: test
180 | date: Thu Jan 01 00:00:00 1970 +0000
180 | date: Thu Jan 01 00:00:00 1970 +0000
181 | summary: f
181 | summary: f
182 |
182 |
183 o changeset: 5:13b04d775b81
183 o changeset: 5:e334d87a1e55
184 | user: test
184 | user: test
185 | date: Thu Jan 01 00:00:00 1970 +0000
185 | date: Thu Jan 01 00:00:00 1970 +0000
186 | summary: does not commute with e
186 | summary: does not commute with e
187 |
187 |
188 o changeset: 4:00f1c5383965
188 o changeset: 4:00f1c5383965
189 | user: test
189 | user: test
190 | date: Thu Jan 01 00:00:00 1970 +0000
190 | date: Thu Jan 01 00:00:00 1970 +0000
191 | summary: d
191 | summary: d
192 |
192 |
193 o changeset: 3:65a9a84f33fd
193 o changeset: 3:65a9a84f33fd
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: 2:da6535b52e45
198 o changeset: 2:da6535b52e45
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: b
201 | summary: b
202 |
202 |
203 o changeset: 1:c1f09da44841
203 o changeset: 1:c1f09da44841
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: a
206 | summary: a
207 |
207 |
208 o changeset: 0:1715188a53c7
208 o changeset: 0:1715188a53c7
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: Initial commit
211 summary: Initial commit
212
212
213
213
214 start over
214 start over
215
215
216 $ cd ..
216 $ cd ..
217
217
218 $ initrepo r2
218 $ initrepo r2
219 $ cd r2
219 $ cd r2
220 $ rm $EDITED
220 $ rm $EDITED
221 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
221 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 3 >> $EDITED
222 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
222 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 4 >> $EDITED
223 $ hg log --template 'mess {node|short} {rev} {desc}\n' -r 7 >> $EDITED
223 $ hg log --template 'mess {node|short} {rev} {desc}\n' -r 7 >> $EDITED
224 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
224 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 5 >> $EDITED
225 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
225 $ hg log --template 'pick {node|short} {rev} {desc}\n' -r 6 >> $EDITED
226 $ cat $EDITED
226 $ cat $EDITED
227 pick 65a9a84f33fd 3 c
227 pick 65a9a84f33fd 3 c
228 pick 00f1c5383965 4 d
228 pick 00f1c5383965 4 d
229 mess 39522b764e3d 7 does not commute with e
229 mess 39522b764e3d 7 does not commute with e
230 pick 7b4e2f4b7bcd 5 e
230 pick 7b4e2f4b7bcd 5 e
231 pick 500cac37a696 6 f
231 pick 500cac37a696 6 f
232
232
233 edit the history, this time with a fold action
233 edit the history, this time with a fold action
234 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
234 $ HGEDITOR="cat \"$EDITED\" > " hg histedit 3 2>&1 | fixbundle
235 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
235 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
236 merging e
236 merging e
237 warning: conflicts during merge.
237 warning: conflicts during merge.
238 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
238 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
239 abort: Fix up the change and run hg histedit --continue
239 abort: Fix up the change and run hg histedit --continue
240
240
241 $ echo 'I can haz no commute' > e
241 $ echo 'I can haz no commute' > e
242 $ hg resolve --mark e
242 $ hg resolve --mark e
243 $ HGEDITOR="cat \"$EDITED\" > " hg histedit --continue 2>&1 | fixbundle
243 $ HGEDITOR="cat \"$EDITED\" > " hg histedit --continue 2>&1 | fixbundle
244 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
244 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 merging e
245 merging e
246 warning: conflicts during merge.
246 warning: conflicts during merge.
247 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
247 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
248 abort: Fix up the change and run hg histedit --continue
248 abort: Fix up the change and run hg histedit --continue
249 second edit also fails, but just continue
249 second edit also fails, but just continue
250 $ hg revert -r 'p1()' e
250 $ hg revert -r 'p1()' e
251 $ hg resolve --mark e
251 $ hg resolve --mark e
252 $ hg histedit --continue 2>&1 | fixbundle
252 $ hg histedit --continue 2>&1 | fixbundle
253 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
254 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
255
255
256 post message fix
256 post message fix
257 $ hg log --graph
257 $ hg log --graph
258 @ changeset: 6:f14da722aa4b
258 @ changeset: 6:521c4c32c5e2
259 | tag: tip
259 | tag: tip
260 | user: test
260 | user: test
261 | date: Thu Jan 01 00:00:00 1970 +0000
261 | date: Thu Jan 01 00:00:00 1970 +0000
262 | summary: f
262 | summary: f
263 |
263 |
264 o changeset: 5:382ff1adf0ed
264 o changeset: 5:f4f088e8adf6
265 | user: test
265 | user: test
266 | date: Thu Jan 01 00:00:00 1970 +0000
266 | date: Thu Jan 01 00:00:00 1970 +0000
267 | summary: pick 65a9a84f33fd 3 c
267 | summary: pick 65a9a84f33fd 3 c
268 |
268 |
269 o changeset: 4:00f1c5383965
269 o changeset: 4:00f1c5383965
270 | user: test
270 | user: test
271 | date: Thu Jan 01 00:00:00 1970 +0000
271 | date: Thu Jan 01 00:00:00 1970 +0000
272 | summary: d
272 | summary: d
273 |
273 |
274 o changeset: 3:65a9a84f33fd
274 o changeset: 3:65a9a84f33fd
275 | user: test
275 | user: test
276 | date: Thu Jan 01 00:00:00 1970 +0000
276 | date: Thu Jan 01 00:00:00 1970 +0000
277 | summary: c
277 | summary: c
278 |
278 |
279 o changeset: 2:da6535b52e45
279 o changeset: 2:da6535b52e45
280 | user: test
280 | user: test
281 | date: Thu Jan 01 00:00:00 1970 +0000
281 | date: Thu Jan 01 00:00:00 1970 +0000
282 | summary: b
282 | summary: b
283 |
283 |
284 o changeset: 1:c1f09da44841
284 o changeset: 1:c1f09da44841
285 | user: test
285 | user: test
286 | date: Thu Jan 01 00:00:00 1970 +0000
286 | date: Thu Jan 01 00:00:00 1970 +0000
287 | summary: a
287 | summary: a
288 |
288 |
289 o changeset: 0:1715188a53c7
289 o changeset: 0:1715188a53c7
290 user: test
290 user: test
291 date: Thu Jan 01 00:00:00 1970 +0000
291 date: Thu Jan 01 00:00:00 1970 +0000
292 summary: Initial commit
292 summary: Initial commit
293
293
294
294
295 $ cd ..
295 $ cd ..
@@ -1,155 +1,155 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 >
17 >
18 > obs=${TESTTMP}/obs.py
18 > obs=${TESTTMP}/obs.py
19 > EOF
19 > EOF
20
20
21 $ hg init base
21 $ hg init base
22 $ cd base
22 $ cd base
23
23
24 $ for x in a b c d e f ; do
24 $ for x in a b c d e f ; do
25 > echo $x > $x
25 > echo $x > $x
26 > hg add $x
26 > hg add $x
27 > hg ci -m $x
27 > hg ci -m $x
28 > done
28 > done
29
29
30 $ hg log --graph
30 $ hg log --graph
31 @ 5:652413bf663e f
31 @ 5:652413bf663e f
32 |
32 |
33 o 4:e860deea161a e
33 o 4:e860deea161a e
34 |
34 |
35 o 3:055a42cdd887 d
35 o 3:055a42cdd887 d
36 |
36 |
37 o 2:177f92b77385 c
37 o 2:177f92b77385 c
38 |
38 |
39 o 1:d2ae7f538514 b
39 o 1:d2ae7f538514 b
40 |
40 |
41 o 0:cb9a9f314b8b a
41 o 0:cb9a9f314b8b a
42
42
43
43
44 $ HGEDITOR=cat hg histedit 1
44 $ HGEDITOR=cat hg histedit 1
45 pick d2ae7f538514 1 b
45 pick d2ae7f538514 1 b
46 pick 177f92b77385 2 c
46 pick 177f92b77385 2 c
47 pick 055a42cdd887 3 d
47 pick 055a42cdd887 3 d
48 pick e860deea161a 4 e
48 pick e860deea161a 4 e
49 pick 652413bf663e 5 f
49 pick 652413bf663e 5 f
50
50
51 # Edit history between d2ae7f538514 and 652413bf663e
51 # Edit history between d2ae7f538514 and 652413bf663e
52 #
52 #
53 # Commands:
53 # Commands:
54 # p, pick = use commit
54 # p, pick = use commit
55 # e, edit = use commit, but stop for amending
55 # e, edit = use commit, but stop for amending
56 # f, fold = use commit, but fold into previous commit (combines N and N-1)
56 # f, fold = use commit, but fold into previous commit (combines N and N-1)
57 # d, drop = remove commit from history
57 # d, drop = remove commit from history
58 # m, mess = edit message without changing commit content
58 # m, mess = edit message without changing commit content
59 #
59 #
60 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
60 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 $ cat > commands.txt <<EOF
61 $ cat > commands.txt <<EOF
62 > pick 177f92b77385 2 c
62 > pick 177f92b77385 2 c
63 > drop d2ae7f538514 1 b
63 > drop d2ae7f538514 1 b
64 > pick 055a42cdd887 3 d
64 > pick 055a42cdd887 3 d
65 > fold e860deea161a 4 e
65 > fold e860deea161a 4 e
66 > pick 652413bf663e 5 f
66 > pick 652413bf663e 5 f
67 > EOF
67 > EOF
68 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
68 $ hg histedit 1 --commands commands.txt --verbose | grep histedit
69 saved backup bundle to $TESTTMP/base/.hg/strip-backup/34a9919932c1-backup.hg (glob)
69 saved backup bundle to $TESTTMP/base/.hg/strip-backup/96e494a2d553-backup.hg (glob)
70 $ hg log --graph --hidden
70 $ hg log --graph --hidden
71 @ 8:0efacef7cb48 f
71 @ 8:cacdfd884a93 f
72 |
72 |
73 o 7:ae467701c500 d
73 o 7:59d9f330561f d
74 |
74 |
75 o 6:d36c0562f908 c
75 o 6:b346ab9a313d c
76 |
76 |
77 | x 5:652413bf663e f
77 | x 5:652413bf663e f
78 | |
78 | |
79 | x 4:e860deea161a e
79 | x 4:e860deea161a e
80 | |
80 | |
81 | x 3:055a42cdd887 d
81 | x 3:055a42cdd887 d
82 | |
82 | |
83 | x 2:177f92b77385 c
83 | x 2:177f92b77385 c
84 | |
84 | |
85 | x 1:d2ae7f538514 b
85 | x 1:d2ae7f538514 b
86 |/
86 |/
87 o 0:cb9a9f314b8b a
87 o 0:cb9a9f314b8b a
88
88
89 $ hg debugobsolete
89 $ hg debugobsolete
90 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {'date': '* *', 'user': 'test'} (glob)
90 d2ae7f538514cd87c17547b0de4cea71fe1af9fb 0 {'date': '* *', 'user': 'test'} (glob)
91 177f92b773850b59254aa5e923436f921b55483b d36c0562f908c692f5204d606d4ff3537d41f1bf 0 {'date': '* *', 'user': 'test'} (glob)
91 177f92b773850b59254aa5e923436f921b55483b b346ab9a313db8537ecf96fca3ca3ca984ef3bd7 0 {'date': '* *', 'user': 'test'} (glob)
92 055a42cdd88768532f9cf79daa407fc8d138de9b ae467701c5006bf21ffcfdb555b3d6b63280b6b7 0 {'date': '* *', 'user': 'test'} (glob)
92 055a42cdd88768532f9cf79daa407fc8d138de9b 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
93 e860deea161a2f77de56603b340ebbb4536308ae ae467701c5006bf21ffcfdb555b3d6b63280b6b7 0 {'date': '* *', 'user': 'test'} (glob)
93 e860deea161a2f77de56603b340ebbb4536308ae 59d9f330561fd6c88b1a6b32f0e45034d88db784 0 {'date': '* *', 'user': 'test'} (glob)
94 652413bf663ef2a641cab26574e46d5f5a64a55a 0efacef7cb481bf574f69075b82d044fdbe5c20f 0 {'date': '* *', 'user': 'test'} (glob)
94 652413bf663ef2a641cab26574e46d5f5a64a55a cacdfd884a9321ec4e1de275ef3949fa953a1f83 0 {'date': '* *', 'user': 'test'} (glob)
95
95
96
96
97 Ensure hidden revision does not prevent histedit
97 Ensure hidden revision does not prevent histedit
98 -------------------------------------------------
98 -------------------------------------------------
99
99
100 create an hidden revision
100 create an hidden revision
101
101
102 $ cat > commands.txt <<EOF
102 $ cat > commands.txt <<EOF
103 > pick d36c0562f908 6 c
103 > pick b346ab9a313d 6 c
104 > drop ae467701c500 7 d
104 > drop 59d9f330561f 7 d
105 > pick 0efacef7cb48 8 f
105 > pick cacdfd884a93 8 f
106 > EOF
106 > EOF
107 $ hg histedit 6 --commands commands.txt
107 $ hg histedit 6 --commands commands.txt
108 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
108 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
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 $ hg log --graph
110 $ hg log --graph
111 @ 9:7c044e3e33a9 f
111 @ 9:c13eb81022ca f
112 |
112 |
113 o 6:d36c0562f908 c
113 o 6:b346ab9a313d c
114 |
114 |
115 o 0:cb9a9f314b8b a
115 o 0:cb9a9f314b8b a
116
116
117 check hidden revision are ignored (6 have hidden children 7 and 8)
117 check hidden revision are ignored (6 have hidden children 7 and 8)
118
118
119 $ cat > commands.txt <<EOF
119 $ cat > commands.txt <<EOF
120 > pick d36c0562f908 6 c
120 > pick b346ab9a313d 6 c
121 > pick 7c044e3e33a9 8 f
121 > pick c13eb81022ca 8 f
122 > EOF
122 > EOF
123 $ hg histedit 6 --commands commands.txt
123 $ hg histedit 6 --commands commands.txt
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 Check that histedit respect phases
127 Check that histedit respect phases
128 =========================================
128 =========================================
129
129
130 (not directly related to the test file but doesn't deserve it's own test case)
130 (not directly related to the test file but doesn't deserve it's own test case)
131
131
132 $ hg log -G
132 $ hg log -G
133 @ 9:7c044e3e33a9 f
133 @ 9:c13eb81022ca f
134 |
134 |
135 o 6:d36c0562f908 c
135 o 6:b346ab9a313d c
136 |
136 |
137 o 0:cb9a9f314b8b a
137 o 0:cb9a9f314b8b a
138
138
139 $ hg ph -pv '.^'
139 $ hg ph -pv '.^'
140 phase changed for 2 changesets
140 phase changed for 2 changesets
141 $ hg histedit -r '.~2'
141 $ hg histedit -r '.~2'
142 abort: cannot edit immutable changeset: cb9a9f314b8b
142 abort: cannot edit immutable changeset: cb9a9f314b8b
143 [255]
143 [255]
144
144
145
145
146 Test that rewriting leaving instability behind is allowed
146 Test that rewriting leaving instability behind is allowed
147 ---------------------------------------------------------------------
147 ---------------------------------------------------------------------
148
148
149 $ hg up '.^'
149 $ hg up '.^'
150 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
150 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
151 $ hg phase --force --draft .
151 $ hg phase --force --draft .
152 $ hg log -r 'children(.)'
152 $ hg log -r 'children(.)'
153 9:7c044e3e33a9 f (no-eol)
153 9:c13eb81022ca f (no-eol)
154 $ hg histedit -r '.'
154 $ hg histedit -r '.'
155 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
General Comments 0
You need to be logged in to leave comments. Login now