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