##// END OF EJS Templates
templatekw: compare target context and its parent exactly (issue4690)...
FUJIWARA Katsunori -
r25392:ed18f4ac 3.4.1 stable
parent child Browse files
Show More
@@ -1,466 +1,466 b''
1 1 # templatekw.py - common changeset template keywords
2 2 #
3 3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import hex
9 9 import patch, util, error
10 10 import hbisect
11 11
12 12 # This helper class allows us to handle both:
13 13 # "{files}" (legacy command-line-specific list hack) and
14 14 # "{files % '{file}\n'}" (hgweb-style with inlining and function support)
15 15 # and to access raw values:
16 16 # "{ifcontains(file, files, ...)}", "{ifcontains(key, extras, ...)}"
17 17 # "{get(extras, key)}"
18 18
19 19 class _hybrid(object):
20 20 def __init__(self, gen, values, makemap, joinfmt=None):
21 21 self.gen = gen
22 22 self.values = values
23 23 self._makemap = makemap
24 24 if joinfmt:
25 25 self.joinfmt = joinfmt
26 26 else:
27 27 self.joinfmt = lambda x: x.values()[0]
28 28 def __iter__(self):
29 29 return self.gen
30 30 def __call__(self):
31 31 makemap = self._makemap
32 32 for x in self.values:
33 33 yield makemap(x)
34 34 def __contains__(self, x):
35 35 return x in self.values
36 36 def __len__(self):
37 37 return len(self.values)
38 38 def __getattr__(self, name):
39 39 if name != 'get':
40 40 raise AttributeError(name)
41 41 return getattr(self.values, name)
42 42
43 43 def showlist(name, values, plural=None, element=None, **args):
44 44 if not element:
45 45 element = name
46 46 f = _showlist(name, values, plural, **args)
47 47 return _hybrid(f, values, lambda x: {element: x})
48 48
49 49 def _showlist(name, values, plural=None, **args):
50 50 '''expand set of values.
51 51 name is name of key in template map.
52 52 values is list of strings or dicts.
53 53 plural is plural of name, if not simply name + 's'.
54 54
55 55 expansion works like this, given name 'foo'.
56 56
57 57 if values is empty, expand 'no_foos'.
58 58
59 59 if 'foo' not in template map, return values as a string,
60 60 joined by space.
61 61
62 62 expand 'start_foos'.
63 63
64 64 for each value, expand 'foo'. if 'last_foo' in template
65 65 map, expand it instead of 'foo' for last key.
66 66
67 67 expand 'end_foos'.
68 68 '''
69 69 templ = args['templ']
70 70 if plural:
71 71 names = plural
72 72 else: names = name + 's'
73 73 if not values:
74 74 noname = 'no_' + names
75 75 if noname in templ:
76 76 yield templ(noname, **args)
77 77 return
78 78 if name not in templ:
79 79 if isinstance(values[0], str):
80 80 yield ' '.join(values)
81 81 else:
82 82 for v in values:
83 83 yield dict(v, **args)
84 84 return
85 85 startname = 'start_' + names
86 86 if startname in templ:
87 87 yield templ(startname, **args)
88 88 vargs = args.copy()
89 89 def one(v, tag=name):
90 90 try:
91 91 vargs.update(v)
92 92 except (AttributeError, ValueError):
93 93 try:
94 94 for a, b in v:
95 95 vargs[a] = b
96 96 except ValueError:
97 97 vargs[name] = v
98 98 return templ(tag, **vargs)
99 99 lastname = 'last_' + name
100 100 if lastname in templ:
101 101 last = values.pop()
102 102 else:
103 103 last = None
104 104 for v in values:
105 105 yield one(v)
106 106 if last is not None:
107 107 yield one(last, tag=lastname)
108 108 endname = 'end_' + names
109 109 if endname in templ:
110 110 yield templ(endname, **args)
111 111
112 112 def getfiles(repo, ctx, revcache):
113 113 if 'files' not in revcache:
114 revcache['files'] = repo.status(ctx.p1().node(), ctx.node())[:3]
114 revcache['files'] = repo.status(ctx.p1(), ctx)[:3]
115 115 return revcache['files']
116 116
117 117 def getlatesttags(repo, ctx, cache):
118 118 '''return date, distance and name for the latest tag of rev'''
119 119
120 120 if 'latesttags' not in cache:
121 121 # Cache mapping from rev to a tuple with tag date, tag
122 122 # distance and tag name
123 123 cache['latesttags'] = {-1: (0, 0, 'null')}
124 124 latesttags = cache['latesttags']
125 125
126 126 rev = ctx.rev()
127 127 todo = [rev]
128 128 while todo:
129 129 rev = todo.pop()
130 130 if rev in latesttags:
131 131 continue
132 132 ctx = repo[rev]
133 133 tags = [t for t in ctx.tags()
134 134 if (repo.tagtype(t) and repo.tagtype(t) != 'local')]
135 135 if tags:
136 136 latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
137 137 continue
138 138 try:
139 139 # The tuples are laid out so the right one can be found by
140 140 # comparison.
141 141 pdate, pdist, ptag = max(
142 142 latesttags[p.rev()] for p in ctx.parents())
143 143 except KeyError:
144 144 # Cache miss - recurse
145 145 todo.append(rev)
146 146 todo.extend(p.rev() for p in ctx.parents())
147 147 continue
148 148 latesttags[rev] = pdate, pdist + 1, ptag
149 149 return latesttags[rev]
150 150
151 151 def getrenamedfn(repo, endrev=None):
152 152 rcache = {}
153 153 if endrev is None:
154 154 endrev = len(repo)
155 155
156 156 def getrenamed(fn, rev):
157 157 '''looks up all renames for a file (up to endrev) the first
158 158 time the file is given. It indexes on the changerev and only
159 159 parses the manifest if linkrev != changerev.
160 160 Returns rename info for fn at changerev rev.'''
161 161 if fn not in rcache:
162 162 rcache[fn] = {}
163 163 fl = repo.file(fn)
164 164 for i in fl:
165 165 lr = fl.linkrev(i)
166 166 renamed = fl.renamed(fl.node(i))
167 167 rcache[fn][lr] = renamed
168 168 if lr >= endrev:
169 169 break
170 170 if rev in rcache[fn]:
171 171 return rcache[fn][rev]
172 172
173 173 # If linkrev != rev (i.e. rev not found in rcache) fallback to
174 174 # filectx logic.
175 175 try:
176 176 return repo[rev][fn].renamed()
177 177 except error.LookupError:
178 178 return None
179 179
180 180 return getrenamed
181 181
182 182
183 183 def showauthor(repo, ctx, templ, **args):
184 184 """:author: String. The unmodified author of the changeset."""
185 185 return ctx.user()
186 186
187 187 def showbisect(repo, ctx, templ, **args):
188 188 """:bisect: String. The changeset bisection status."""
189 189 return hbisect.label(repo, ctx.node())
190 190
191 191 def showbranch(**args):
192 192 """:branch: String. The name of the branch on which the changeset was
193 193 committed.
194 194 """
195 195 return args['ctx'].branch()
196 196
197 197 def showbranches(**args):
198 198 """:branches: List of strings. The name of the branch on which the
199 199 changeset was committed. Will be empty if the branch name was
200 200 default.
201 201 """
202 202 branch = args['ctx'].branch()
203 203 if branch != 'default':
204 204 return showlist('branch', [branch], plural='branches', **args)
205 205 return showlist('branch', [], plural='branches', **args)
206 206
207 207 def showbookmarks(**args):
208 208 """:bookmarks: List of strings. Any bookmarks associated with the
209 209 changeset.
210 210 """
211 211 repo = args['ctx']._repo
212 212 bookmarks = args['ctx'].bookmarks()
213 213 current = repo._bookmarkcurrent
214 214 makemap = lambda v: {'bookmark': v, 'current': current}
215 215 f = _showlist('bookmark', bookmarks, **args)
216 216 return _hybrid(f, bookmarks, makemap, lambda x: x['bookmark'])
217 217
218 218 def showchildren(**args):
219 219 """:children: List of strings. The children of the changeset."""
220 220 ctx = args['ctx']
221 221 childrevs = ['%d:%s' % (cctx, cctx) for cctx in ctx.children()]
222 222 return showlist('children', childrevs, element='child', **args)
223 223
224 224 def showcurrentbookmark(**args):
225 225 """:currentbookmark: String. The active bookmark, if it is
226 226 associated with the changeset"""
227 227 import bookmarks as bookmarks # to avoid circular import issues
228 228 repo = args['repo']
229 229 if bookmarks.iscurrent(repo):
230 230 current = repo._bookmarkcurrent
231 231 if current in args['ctx'].bookmarks():
232 232 return current
233 233 return ''
234 234
235 235 def showdate(repo, ctx, templ, **args):
236 236 """:date: Date information. The date when the changeset was committed."""
237 237 return ctx.date()
238 238
239 239 def showdescription(repo, ctx, templ, **args):
240 240 """:desc: String. The text of the changeset description."""
241 241 return ctx.description().strip()
242 242
243 243 def showdiffstat(repo, ctx, templ, **args):
244 244 """:diffstat: String. Statistics of changes with the following format:
245 245 "modified files: +added/-removed lines"
246 246 """
247 247 stats = patch.diffstatdata(util.iterlines(ctx.diff()))
248 248 maxname, maxtotal, adds, removes, binary = patch.diffstatsum(stats)
249 249 return '%s: +%s/-%s' % (len(stats), adds, removes)
250 250
251 251 def showextras(**args):
252 252 """:extras: List of dicts with key, value entries of the 'extras'
253 253 field of this changeset."""
254 254 extras = args['ctx'].extra()
255 255 extras = util.sortdict((k, extras[k]) for k in sorted(extras))
256 256 makemap = lambda k: {'key': k, 'value': extras[k]}
257 257 c = [makemap(k) for k in extras]
258 258 f = _showlist('extra', c, plural='extras', **args)
259 259 return _hybrid(f, extras, makemap,
260 260 lambda x: '%s=%s' % (x['key'], x['value']))
261 261
262 262 def showfileadds(**args):
263 263 """:file_adds: List of strings. Files added by this changeset."""
264 264 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
265 265 return showlist('file_add', getfiles(repo, ctx, revcache)[1],
266 266 element='file', **args)
267 267
268 268 def showfilecopies(**args):
269 269 """:file_copies: List of strings. Files copied in this changeset with
270 270 their sources.
271 271 """
272 272 cache, ctx = args['cache'], args['ctx']
273 273 copies = args['revcache'].get('copies')
274 274 if copies is None:
275 275 if 'getrenamed' not in cache:
276 276 cache['getrenamed'] = getrenamedfn(args['repo'])
277 277 copies = []
278 278 getrenamed = cache['getrenamed']
279 279 for fn in ctx.files():
280 280 rename = getrenamed(fn, ctx.rev())
281 281 if rename:
282 282 copies.append((fn, rename[0]))
283 283
284 284 copies = util.sortdict(copies)
285 285 makemap = lambda k: {'name': k, 'source': copies[k]}
286 286 c = [makemap(k) for k in copies]
287 287 f = _showlist('file_copy', c, plural='file_copies', **args)
288 288 return _hybrid(f, copies, makemap,
289 289 lambda x: '%s (%s)' % (x['name'], x['source']))
290 290
291 291 # showfilecopiesswitch() displays file copies only if copy records are
292 292 # provided before calling the templater, usually with a --copies
293 293 # command line switch.
294 294 def showfilecopiesswitch(**args):
295 295 """:file_copies_switch: List of strings. Like "file_copies" but displayed
296 296 only if the --copied switch is set.
297 297 """
298 298 copies = args['revcache'].get('copies') or []
299 299 copies = util.sortdict(copies)
300 300 makemap = lambda k: {'name': k, 'source': copies[k]}
301 301 c = [makemap(k) for k in copies]
302 302 f = _showlist('file_copy', c, plural='file_copies', **args)
303 303 return _hybrid(f, copies, makemap,
304 304 lambda x: '%s (%s)' % (x['name'], x['source']))
305 305
306 306 def showfiledels(**args):
307 307 """:file_dels: List of strings. Files removed by this changeset."""
308 308 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
309 309 return showlist('file_del', getfiles(repo, ctx, revcache)[2],
310 310 element='file', **args)
311 311
312 312 def showfilemods(**args):
313 313 """:file_mods: List of strings. Files modified by this changeset."""
314 314 repo, ctx, revcache = args['repo'], args['ctx'], args['revcache']
315 315 return showlist('file_mod', getfiles(repo, ctx, revcache)[0],
316 316 element='file', **args)
317 317
318 318 def showfiles(**args):
319 319 """:files: List of strings. All files modified, added, or removed by this
320 320 changeset.
321 321 """
322 322 return showlist('file', args['ctx'].files(), **args)
323 323
324 324 def showlatesttag(repo, ctx, templ, cache, **args):
325 325 """:latesttag: String. Most recent global tag in the ancestors of this
326 326 changeset.
327 327 """
328 328 return getlatesttags(repo, ctx, cache)[2]
329 329
330 330 def showlatesttagdistance(repo, ctx, templ, cache, **args):
331 331 """:latesttagdistance: Integer. Longest path to the latest tag."""
332 332 return getlatesttags(repo, ctx, cache)[1]
333 333
334 334 def showmanifest(**args):
335 335 repo, ctx, templ = args['repo'], args['ctx'], args['templ']
336 336 mnode = ctx.manifestnode()
337 337 args = args.copy()
338 338 args.update({'rev': repo.manifest.rev(mnode), 'node': hex(mnode)})
339 339 return templ('manifest', **args)
340 340
341 341 def shownode(repo, ctx, templ, **args):
342 342 """:node: String. The changeset identification hash, as a 40 hexadecimal
343 343 digit string.
344 344 """
345 345 return ctx.hex()
346 346
347 347 def showp1rev(repo, ctx, templ, **args):
348 348 """:p1rev: Integer. The repository-local revision number of the changeset's
349 349 first parent, or -1 if the changeset has no parents."""
350 350 return ctx.p1().rev()
351 351
352 352 def showp2rev(repo, ctx, templ, **args):
353 353 """:p2rev: Integer. The repository-local revision number of the changeset's
354 354 second parent, or -1 if the changeset has no second parent."""
355 355 return ctx.p2().rev()
356 356
357 357 def showp1node(repo, ctx, templ, **args):
358 358 """:p1node: String. The identification hash of the changeset's first parent,
359 359 as a 40 digit hexadecimal string. If the changeset has no parents, all
360 360 digits are 0."""
361 361 return ctx.p1().hex()
362 362
363 363 def showp2node(repo, ctx, templ, **args):
364 364 """:p2node: String. The identification hash of the changeset's second
365 365 parent, as a 40 digit hexadecimal string. If the changeset has no second
366 366 parent, all digits are 0."""
367 367 return ctx.p2().hex()
368 368
369 369 def showphase(repo, ctx, templ, **args):
370 370 """:phase: String. The changeset phase name."""
371 371 return ctx.phasestr()
372 372
373 373 def showphaseidx(repo, ctx, templ, **args):
374 374 """:phaseidx: Integer. The changeset phase index."""
375 375 return ctx.phase()
376 376
377 377 def showrev(repo, ctx, templ, **args):
378 378 """:rev: Integer. The repository-local changeset revision number."""
379 379 return ctx.rev()
380 380
381 381 def showsubrepos(**args):
382 382 """:subrepos: List of strings. Updated subrepositories in the changeset."""
383 383 ctx = args['ctx']
384 384 substate = ctx.substate
385 385 if not substate:
386 386 return showlist('subrepo', [], **args)
387 387 psubstate = ctx.parents()[0].substate or {}
388 388 subrepos = []
389 389 for sub in substate:
390 390 if sub not in psubstate or substate[sub] != psubstate[sub]:
391 391 subrepos.append(sub) # modified or newly added in ctx
392 392 for sub in psubstate:
393 393 if sub not in substate:
394 394 subrepos.append(sub) # removed in ctx
395 395 return showlist('subrepo', sorted(subrepos), **args)
396 396
397 397 def shownames(namespace, **args):
398 398 """helper method to generate a template keyword for a namespace"""
399 399 ctx = args['ctx']
400 400 repo = ctx.repo()
401 401 ns = repo.names[namespace]
402 402 names = ns.names(repo, ctx.node())
403 403 return showlist(ns.templatename, names, plural=namespace, **args)
404 404
405 405 # don't remove "showtags" definition, even though namespaces will put
406 406 # a helper function for "tags" keyword into "keywords" map automatically,
407 407 # because online help text is built without namespaces initialization
408 408 def showtags(**args):
409 409 """:tags: List of strings. Any tags associated with the changeset."""
410 410 return shownames('tags', **args)
411 411
412 412 # keywords are callables like:
413 413 # fn(repo, ctx, templ, cache, revcache, **args)
414 414 # with:
415 415 # repo - current repository instance
416 416 # ctx - the changectx being displayed
417 417 # templ - the templater instance
418 418 # cache - a cache dictionary for the whole templater run
419 419 # revcache - a cache dictionary for the current revision
420 420 keywords = {
421 421 'author': showauthor,
422 422 'bisect': showbisect,
423 423 'branch': showbranch,
424 424 'branches': showbranches,
425 425 'bookmarks': showbookmarks,
426 426 'children': showchildren,
427 427 'currentbookmark': showcurrentbookmark,
428 428 'date': showdate,
429 429 'desc': showdescription,
430 430 'diffstat': showdiffstat,
431 431 'extras': showextras,
432 432 'file_adds': showfileadds,
433 433 'file_copies': showfilecopies,
434 434 'file_copies_switch': showfilecopiesswitch,
435 435 'file_dels': showfiledels,
436 436 'file_mods': showfilemods,
437 437 'files': showfiles,
438 438 'latesttag': showlatesttag,
439 439 'latesttagdistance': showlatesttagdistance,
440 440 'manifest': showmanifest,
441 441 'node': shownode,
442 442 'p1rev': showp1rev,
443 443 'p1node': showp1node,
444 444 'p2rev': showp2rev,
445 445 'p2node': showp2node,
446 446 'phase': showphase,
447 447 'phaseidx': showphaseidx,
448 448 'rev': showrev,
449 449 'subrepos': showsubrepos,
450 450 'tags': showtags,
451 451 }
452 452
453 453 def _showparents(**args):
454 454 """:parents: List of strings. The parents of the changeset in "rev:node"
455 455 format. If the changeset has only one "natural" parent (the predecessor
456 456 revision) nothing is shown."""
457 457 pass
458 458
459 459 dockeywords = {
460 460 'parents': _showparents,
461 461 }
462 462 dockeywords.update(keywords)
463 463 del dockeywords['branches']
464 464
465 465 # tell hggettext to extract docstrings from these functions:
466 466 i18nfunctions = dockeywords.values()
@@ -1,1122 +1,1153 b''
1 1 $ hg init
2 2
3 3 Setup:
4 4
5 5 $ echo a >> a
6 6 $ hg ci -Am 'base'
7 7 adding a
8 8
9 9 Refuse to amend public csets:
10 10
11 11 $ hg phase -r . -p
12 12 $ hg ci --amend
13 13 abort: cannot amend public changesets
14 14 [255]
15 15 $ hg phase -r . -f -d
16 16
17 17 $ echo a >> a
18 18 $ hg ci -Am 'base1'
19 19
20 20 Nothing to amend:
21 21
22 22 $ hg ci --amend
23 23 nothing changed
24 24 [1]
25 25
26 26 $ cat >> $HGRCPATH <<EOF
27 27 > [hooks]
28 28 > pretxncommit.foo = sh -c "echo \\"pretxncommit \$HG_NODE\\"; hg id -r \$HG_NODE"
29 29 > EOF
30 30
31 31 Amending changeset with changes in working dir:
32 32 (and check that --message does not trigger an editor)
33 33
34 34 $ echo a >> a
35 35 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -m 'amend base1'
36 36 pretxncommit 43f1ba15f28a50abf0aae529cf8a16bfced7b149
37 37 43f1ba15f28a tip
38 38 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-f1bf3ab8-amend-backup.hg (glob)
39 39 $ echo 'pretxncommit.foo = ' >> $HGRCPATH
40 40 $ hg diff -c .
41 41 diff -r ad120869acf0 -r 43f1ba15f28a a
42 42 --- a/a Thu Jan 01 00:00:00 1970 +0000
43 43 +++ b/a Thu Jan 01 00:00:00 1970 +0000
44 44 @@ -1,1 +1,3 @@
45 45 a
46 46 +a
47 47 +a
48 48 $ hg log
49 49 changeset: 1:43f1ba15f28a
50 50 tag: tip
51 51 user: test
52 52 date: Thu Jan 01 00:00:00 1970 +0000
53 53 summary: amend base1
54 54
55 55 changeset: 0:ad120869acf0
56 56 user: test
57 57 date: Thu Jan 01 00:00:00 1970 +0000
58 58 summary: base
59 59
60 60
61 61 Check proper abort for empty message
62 62
63 63 $ cat > editor.sh << '__EOF__'
64 64 > #!/bin/sh
65 65 > echo "" > "$1"
66 66 > __EOF__
67 67 $ echo b > b
68 68 $ hg add b
69 69 $ hg summary
70 70 parent: 1:43f1ba15f28a tip
71 71 amend base1
72 72 branch: default
73 73 commit: 1 added, 1 unknown
74 74 update: (current)
75 75 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
76 76 transaction abort!
77 77 rollback completed
78 78 abort: empty commit message
79 79 [255]
80 80 $ hg summary
81 81 parent: 1:43f1ba15f28a tip
82 82 amend base1
83 83 branch: default
84 84 commit: 1 added, 1 unknown
85 85 update: (current)
86 86
87 87 Add new file:
88 88 $ hg ci --amend -m 'amend base1 new file'
89 89 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-7a3b3496-amend-backup.hg (glob)
90 90
91 91 Remove file that was added in amended commit:
92 92 (and test logfile option)
93 93 (and test that logfile option do not trigger an editor)
94 94
95 95 $ hg rm b
96 96 $ echo 'amend base1 remove new file' > ../logfile
97 97 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg ci --amend --logfile ../logfile
98 98 saved backup bundle to $TESTTMP/.hg/strip-backup/b8e3cb2b3882-0b55739a-amend-backup.hg (glob)
99 99
100 100 $ hg cat b
101 101 b: no such file in rev 74609c7f506e
102 102 [1]
103 103
104 104 No changes, just a different message:
105 105
106 106 $ hg ci -v --amend -m 'no changes, new message'
107 107 amending changeset 74609c7f506e
108 108 copying changeset 74609c7f506e to ad120869acf0
109 109 committing files:
110 110 a
111 111 committing manifest
112 112 committing changelog
113 113 stripping amended changeset 74609c7f506e
114 114 1 changesets found
115 115 uncompressed size of bundle content:
116 116 250 (changelog)
117 117 143 (manifests)
118 118 109 a
119 119 saved backup bundle to $TESTTMP/.hg/strip-backup/74609c7f506e-1bfde511-amend-backup.hg (glob)
120 120 1 changesets found
121 121 uncompressed size of bundle content:
122 122 246 (changelog)
123 123 143 (manifests)
124 124 109 a
125 125 adding branch
126 126 adding changesets
127 127 adding manifests
128 128 adding file changes
129 129 added 1 changesets with 1 changes to 1 files
130 130 committed changeset 1:1cd866679df8
131 131 $ hg diff -c .
132 132 diff -r ad120869acf0 -r 1cd866679df8 a
133 133 --- a/a Thu Jan 01 00:00:00 1970 +0000
134 134 +++ b/a Thu Jan 01 00:00:00 1970 +0000
135 135 @@ -1,1 +1,3 @@
136 136 a
137 137 +a
138 138 +a
139 139 $ hg log
140 140 changeset: 1:1cd866679df8
141 141 tag: tip
142 142 user: test
143 143 date: Thu Jan 01 00:00:00 1970 +0000
144 144 summary: no changes, new message
145 145
146 146 changeset: 0:ad120869acf0
147 147 user: test
148 148 date: Thu Jan 01 00:00:00 1970 +0000
149 149 summary: base
150 150
151 151
152 152 Disable default date on commit so when -d isn't given, the old date is preserved:
153 153
154 154 $ echo '[defaults]' >> $HGRCPATH
155 155 $ echo 'commit=' >> $HGRCPATH
156 156
157 157 Test -u/-d:
158 158
159 159 $ cat > .hg/checkeditform.sh <<EOF
160 160 > env | grep HGEDITFORM
161 161 > true
162 162 > EOF
163 163 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -u foo -d '1 0'
164 164 HGEDITFORM=commit.amend.normal
165 165 saved backup bundle to $TESTTMP/.hg/strip-backup/1cd866679df8-5f5bcb85-amend-backup.hg (glob)
166 166 $ echo a >> a
167 167 $ hg ci --amend -u foo -d '1 0'
168 168 saved backup bundle to $TESTTMP/.hg/strip-backup/780e6f23e03d-83b10a27-amend-backup.hg (glob)
169 169 $ hg log -r .
170 170 changeset: 1:5f357c7560ab
171 171 tag: tip
172 172 user: foo
173 173 date: Thu Jan 01 00:00:01 1970 +0000
174 174 summary: no changes, new message
175 175
176 176
177 177 Open editor with old commit message if a message isn't given otherwise:
178 178
179 179 $ cat > editor.sh << '__EOF__'
180 180 > #!/bin/sh
181 181 > cat $1
182 182 > echo "another precious commit message" > "$1"
183 183 > __EOF__
184 184
185 185 at first, test saving last-message.txt
186 186
187 187 $ cat > .hg/hgrc << '__EOF__'
188 188 > [hooks]
189 189 > pretxncommit.test-saving-last-message = false
190 190 > __EOF__
191 191
192 192 $ rm -f .hg/last-message.txt
193 193 $ hg commit --amend -v -m "message given from command line"
194 194 amending changeset 5f357c7560ab
195 195 copying changeset 5f357c7560ab to ad120869acf0
196 196 committing files:
197 197 a
198 198 committing manifest
199 199 committing changelog
200 200 running hook pretxncommit.test-saving-last-message: false
201 201 transaction abort!
202 202 rollback completed
203 203 abort: pretxncommit.test-saving-last-message hook exited with status 1
204 204 [255]
205 205 $ cat .hg/last-message.txt
206 206 message given from command line (no-eol)
207 207
208 208 $ rm -f .hg/last-message.txt
209 209 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
210 210 amending changeset 5f357c7560ab
211 211 copying changeset 5f357c7560ab to ad120869acf0
212 212 no changes, new message
213 213
214 214
215 215 HG: Enter commit message. Lines beginning with 'HG:' are removed.
216 216 HG: Leave message empty to abort commit.
217 217 HG: --
218 218 HG: user: foo
219 219 HG: branch 'default'
220 220 HG: changed a
221 221 committing files:
222 222 a
223 223 committing manifest
224 224 committing changelog
225 225 running hook pretxncommit.test-saving-last-message: false
226 226 transaction abort!
227 227 rollback completed
228 228 abort: pretxncommit.test-saving-last-message hook exited with status 1
229 229 [255]
230 230
231 231 $ cat .hg/last-message.txt
232 232 another precious commit message
233 233
234 234 $ cat > .hg/hgrc << '__EOF__'
235 235 > [hooks]
236 236 > pretxncommit.test-saving-last-message =
237 237 > __EOF__
238 238
239 239 then, test editing custom commit message
240 240
241 241 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
242 242 amending changeset 5f357c7560ab
243 243 copying changeset 5f357c7560ab to ad120869acf0
244 244 no changes, new message
245 245
246 246
247 247 HG: Enter commit message. Lines beginning with 'HG:' are removed.
248 248 HG: Leave message empty to abort commit.
249 249 HG: --
250 250 HG: user: foo
251 251 HG: branch 'default'
252 252 HG: changed a
253 253 committing files:
254 254 a
255 255 committing manifest
256 256 committing changelog
257 257 stripping amended changeset 5f357c7560ab
258 258 1 changesets found
259 259 uncompressed size of bundle content:
260 260 238 (changelog)
261 261 143 (manifests)
262 262 111 a
263 263 saved backup bundle to $TESTTMP/.hg/strip-backup/5f357c7560ab-e7c84ade-amend-backup.hg (glob)
264 264 1 changesets found
265 265 uncompressed size of bundle content:
266 266 246 (changelog)
267 267 143 (manifests)
268 268 111 a
269 269 adding branch
270 270 adding changesets
271 271 adding manifests
272 272 adding file changes
273 273 added 1 changesets with 1 changes to 1 files
274 274 committed changeset 1:7ab3bf440b54
275 275
276 276 Same, but with changes in working dir (different code path):
277 277
278 278 $ echo a >> a
279 279 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
280 280 amending changeset 7ab3bf440b54
281 281 committing files:
282 282 a
283 283 committing manifest
284 284 committing changelog
285 285 copying changeset a0ea9b1a4c8c to ad120869acf0
286 286 another precious commit message
287 287
288 288
289 289 HG: Enter commit message. Lines beginning with 'HG:' are removed.
290 290 HG: Leave message empty to abort commit.
291 291 HG: --
292 292 HG: user: foo
293 293 HG: branch 'default'
294 294 HG: changed a
295 295 committing files:
296 296 a
297 297 committing manifest
298 298 committing changelog
299 299 stripping intermediate changeset a0ea9b1a4c8c
300 300 stripping amended changeset 7ab3bf440b54
301 301 2 changesets found
302 302 uncompressed size of bundle content:
303 303 450 (changelog)
304 304 282 (manifests)
305 305 209 a
306 306 saved backup bundle to $TESTTMP/.hg/strip-backup/7ab3bf440b54-8e3b5088-amend-backup.hg (glob)
307 307 1 changesets found
308 308 uncompressed size of bundle content:
309 309 246 (changelog)
310 310 143 (manifests)
311 311 113 a
312 312 adding branch
313 313 adding changesets
314 314 adding manifests
315 315 adding file changes
316 316 added 1 changesets with 1 changes to 1 files
317 317 committed changeset 1:ea22a388757c
318 318
319 319 $ rm editor.sh
320 320 $ hg log -r .
321 321 changeset: 1:ea22a388757c
322 322 tag: tip
323 323 user: foo
324 324 date: Thu Jan 01 00:00:01 1970 +0000
325 325 summary: another precious commit message
326 326
327 327
328 328 Moving bookmarks, preserve active bookmark:
329 329
330 330 $ hg book book1
331 331 $ hg book book2
332 332 $ hg ci --amend -m 'move bookmarks'
333 333 saved backup bundle to $TESTTMP/.hg/strip-backup/ea22a388757c-e51094db-amend-backup.hg (glob)
334 334 $ hg book
335 335 book1 1:6cec5aa930e2
336 336 * book2 1:6cec5aa930e2
337 337 $ echo a >> a
338 338 $ hg ci --amend -m 'move bookmarks'
339 339 saved backup bundle to $TESTTMP/.hg/strip-backup/6cec5aa930e2-e9b06de4-amend-backup.hg (glob)
340 340 $ hg book
341 341 book1 1:48bb6e53a15f
342 342 * book2 1:48bb6e53a15f
343 343
344 344 abort does not loose bookmarks
345 345
346 346 $ cat > editor.sh << '__EOF__'
347 347 > #!/bin/sh
348 348 > echo "" > "$1"
349 349 > __EOF__
350 350 $ echo a >> a
351 351 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
352 352 transaction abort!
353 353 rollback completed
354 354 abort: empty commit message
355 355 [255]
356 356 $ hg book
357 357 book1 1:48bb6e53a15f
358 358 * book2 1:48bb6e53a15f
359 359 $ hg revert -Caq
360 360 $ rm editor.sh
361 361
362 362 $ echo '[defaults]' >> $HGRCPATH
363 363 $ echo "commit=-d '0 0'" >> $HGRCPATH
364 364
365 365 Moving branches:
366 366
367 367 $ hg branch foo
368 368 marked working directory as branch foo
369 369 (branches are permanent and global, did you want a bookmark?)
370 370 $ echo a >> a
371 371 $ hg ci -m 'branch foo'
372 372 $ hg branch default -f
373 373 marked working directory as branch default
374 374 (branches are permanent and global, did you want a bookmark?)
375 375 $ hg ci --amend -m 'back to default'
376 376 saved backup bundle to $TESTTMP/.hg/strip-backup/8ac881fbf49d-fd962fef-amend-backup.hg (glob)
377 377 $ hg branches
378 378 default 2:ce12b0b57d46
379 379
380 380 Close branch:
381 381
382 382 $ hg up -q 0
383 383 $ echo b >> b
384 384 $ hg branch foo
385 385 marked working directory as branch foo
386 386 (branches are permanent and global, did you want a bookmark?)
387 387 $ hg ci -Am 'fork'
388 388 adding b
389 389 $ echo b >> b
390 390 $ hg ci -mb
391 391 $ hg ci --amend --close-branch -m 'closing branch foo'
392 392 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-6701c392-amend-backup.hg (glob)
393 393
394 394 Same thing, different code path:
395 395
396 396 $ echo b >> b
397 397 $ hg ci -m 'reopen branch'
398 398 reopening closed branch head 4
399 399 $ echo b >> b
400 400 $ hg ci --amend --close-branch
401 401 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-49c0c55d-amend-backup.hg (glob)
402 402 $ hg branches
403 403 default 2:ce12b0b57d46
404 404
405 405 Refuse to amend during a merge:
406 406
407 407 $ hg up -q default
408 408 $ hg merge foo
409 409 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 410 (branch merge, don't forget to commit)
411 411 $ hg ci --amend
412 412 abort: cannot amend while merging
413 413 [255]
414 414 $ hg ci -m 'merge'
415 415
416 416 Follow copies/renames:
417 417
418 418 $ hg mv b c
419 419 $ hg ci -m 'b -> c'
420 420 $ hg mv c d
421 421 $ hg ci --amend -m 'b -> d'
422 422 saved backup bundle to $TESTTMP/.hg/strip-backup/b8c6eac7f12e-adaaa8b1-amend-backup.hg (glob)
423 423 $ hg st --rev '.^' --copies d
424 424 A d
425 425 b
426 426 $ hg cp d e
427 427 $ hg ci -m 'e = d'
428 428 $ hg cp e f
429 429 $ hg ci --amend -m 'f = d'
430 430 saved backup bundle to $TESTTMP/.hg/strip-backup/7f9761d65613-d37aa788-amend-backup.hg (glob)
431 431 $ hg st --rev '.^' --copies f
432 432 A f
433 433 d
434 434
435 435 $ mv f f.orig
436 436 $ hg rm -A f
437 437 $ hg ci -m removef
438 438 $ hg cp a f
439 439 $ mv f.orig f
440 440 $ hg ci --amend -m replacef
441 441 saved backup bundle to $TESTTMP/.hg/strip-backup/9e8c5f7e3d95-90259f67-amend-backup.hg (glob)
442 442 $ hg st --change . --copies
443 443 $ hg log -r . --template "{file_copies}\n"
444 444
445 445
446 446 Move added file (issue3410):
447 447
448 448 $ echo g >> g
449 449 $ hg ci -Am g
450 450 adding g
451 451 $ hg mv g h
452 452 $ hg ci --amend
453 453 saved backup bundle to $TESTTMP/.hg/strip-backup/24aa8eacce2b-7059e0f1-amend-backup.hg (glob)
454 454 $ hg st --change . --copies h
455 455 A h
456 456 $ hg log -r . --template "{file_copies}\n"
457 457
458 458
459 459 Can't rollback an amend:
460 460
461 461 $ hg rollback
462 462 no rollback information available
463 463 [1]
464 464
465 465 Preserve extra dict (issue3430):
466 466
467 467 $ hg branch a
468 468 marked working directory as branch a
469 469 (branches are permanent and global, did you want a bookmark?)
470 470 $ echo a >> a
471 471 $ hg ci -ma
472 472 $ hg ci --amend -m "a'"
473 473 saved backup bundle to $TESTTMP/.hg/strip-backup/3837aa2a2fdb-2be01fd1-amend-backup.hg (glob)
474 474 $ hg log -r . --template "{branch}\n"
475 475 a
476 476 $ hg ci --amend -m "a''"
477 477 saved backup bundle to $TESTTMP/.hg/strip-backup/c05c06be7514-ed28c4cd-amend-backup.hg (glob)
478 478 $ hg log -r . --template "{branch}\n"
479 479 a
480 480
481 481 Also preserve other entries in the dict that are in the old commit,
482 482 first graft something so there's an additional entry:
483 483
484 484 $ hg up 0 -q
485 485 $ echo z > z
486 486 $ hg ci -Am 'fork'
487 487 adding z
488 488 created new head
489 489 $ hg up 11
490 490 5 files updated, 0 files merged, 1 files removed, 0 files unresolved
491 491 $ hg graft 12
492 492 grafting 12:2647734878ef "fork" (tip)
493 493 $ hg ci --amend -m 'graft amend'
494 494 saved backup bundle to $TESTTMP/.hg/strip-backup/bd010aea3f39-eedb103b-amend-backup.hg (glob)
495 495 $ hg log -r . --debug | grep extra
496 496 extra: amend_source=bd010aea3f39f3fb2a2f884b9ccb0471cd77398e
497 497 extra: branch=a
498 498 extra: source=2647734878ef0236dda712fae9c1651cf694ea8a
499 499
500 500 Preserve phase
501 501
502 502 $ hg phase '.^::.'
503 503 11: draft
504 504 13: draft
505 505 $ hg phase --secret --force .
506 506 $ hg phase '.^::.'
507 507 11: draft
508 508 13: secret
509 509 $ hg commit --amend -m 'amend for phase' -q
510 510 $ hg phase '.^::.'
511 511 11: draft
512 512 13: secret
513 513
514 514 Test amend with obsolete
515 515 ---------------------------
516 516
517 517 Enable obsolete
518 518
519 519 $ cat >> $HGRCPATH << EOF
520 520 > [experimental]
521 521 > evolution=createmarkers,allowunstable
522 522 > EOF
523 523
524 524 Amend with no files changes
525 525
526 526 $ hg id -n
527 527 13
528 528 $ hg ci --amend -m 'babar'
529 529 $ hg id -n
530 530 14
531 531 $ hg log -Gl 3 --style=compact
532 532 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
533 533 | babar
534 534 |
535 535 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
536 536 | | fork
537 537 | |
538 538 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
539 539 | | a''
540 540 | |
541 541 $ hg log -Gl 4 --hidden --style=compact
542 542 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
543 543 | babar
544 544 |
545 545 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
546 546 |/ amend for phase
547 547 |
548 548 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
549 549 | | fork
550 550 | |
551 551 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
552 552 | | a''
553 553 | |
554 554
555 555 Amend with files changes
556 556
557 557 (note: the extra commit over 15 is a temporary junk I would be happy to get
558 558 ride of)
559 559
560 560 $ echo 'babar' >> a
561 561 $ hg commit --amend
562 562 $ hg log -Gl 6 --hidden --style=compact
563 563 @ 16[tip]:11 9f9e9bccf56c 1970-01-01 00:00 +0000 test
564 564 | babar
565 565 |
566 566 | x 15 90fef497c56f 1970-01-01 00:00 +0000 test
567 567 | | temporary amend commit for b650e6ee8614
568 568 | |
569 569 | x 14:11 b650e6ee8614 1970-01-01 00:00 +0000 test
570 570 |/ babar
571 571 |
572 572 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
573 573 |/ amend for phase
574 574 |
575 575 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
576 576 | | fork
577 577 | |
578 578 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
579 579 | | a''
580 580 | |
581 581
582 582
583 583 Test that amend does not make it easy to create obsolescence cycle
584 584 ---------------------------------------------------------------------
585 585
586 586 $ hg id -r 14 --hidden
587 587 b650e6ee8614 (a)
588 588 $ hg revert -ar 14 --hidden
589 589 reverting a
590 590 $ hg commit --amend
591 591 $ hg id
592 592 b99e5df575f7 (a) tip
593 593
594 594 Test that rewriting leaving instability behind is allowed
595 595 ---------------------------------------------------------------------
596 596
597 597 $ hg up '.^'
598 598 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
599 599 $ echo 'b' >> a
600 600 $ hg log --style compact -r 'children(.)'
601 601 18[tip]:11 b99e5df575f7 1970-01-01 00:00 +0000 test
602 602 babar
603 603
604 604 $ hg commit --amend
605 605 $ hg log -r 'unstable()'
606 606 changeset: 18:b99e5df575f7
607 607 branch: a
608 608 parent: 11:3334b7925910
609 609 user: test
610 610 date: Thu Jan 01 00:00:00 1970 +0000
611 611 summary: babar
612 612
613 613
614 614 Amend a merge changeset (with renames and conflicts from the second parent):
615 615
616 616 $ hg up -q default
617 617 $ hg branch -q bar
618 618 $ hg cp a aa
619 619 $ hg mv z zz
620 620 $ echo cc > cc
621 621 $ hg add cc
622 622 $ hg ci -m aazzcc
623 623 $ hg up -q default
624 624 $ echo a >> a
625 625 $ echo dd > cc
626 626 $ hg add cc
627 627 $ hg ci -m aa
628 628 $ hg merge -q bar
629 629 warning: conflicts during merge.
630 630 merging cc incomplete! (edit conflicts, then use 'hg resolve --mark')
631 631 [1]
632 632 $ hg resolve -m cc
633 633 (no more unresolved files)
634 634 $ hg ci -m 'merge bar'
635 635 $ hg log --config diff.git=1 -pr .
636 636 changeset: 23:93cd4445f720
637 637 tag: tip
638 638 parent: 22:30d96aeaf27b
639 639 parent: 21:1aa437659d19
640 640 user: test
641 641 date: Thu Jan 01 00:00:00 1970 +0000
642 642 summary: merge bar
643 643
644 644 diff --git a/a b/aa
645 645 copy from a
646 646 copy to aa
647 647 diff --git a/cc b/cc
648 648 --- a/cc
649 649 +++ b/cc
650 650 @@ -1,1 +1,5 @@
651 651 +<<<<<<< local: 30d96aeaf27b - test: aa
652 652 dd
653 653 +=======
654 654 +cc
655 655 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
656 656 diff --git a/z b/zz
657 657 rename from z
658 658 rename to zz
659 659
660 660 $ hg debugrename aa
661 661 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
662 662 $ hg debugrename zz
663 663 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
664 664 $ hg debugrename cc
665 665 cc not renamed
666 666 $ HGEDITOR="sh .hg/checkeditform.sh" hg ci --amend -m 'merge bar (amend message)' --edit
667 667 HGEDITFORM=commit.amend.merge
668 668 $ hg log --config diff.git=1 -pr .
669 669 changeset: 24:832b50f2c271
670 670 tag: tip
671 671 parent: 22:30d96aeaf27b
672 672 parent: 21:1aa437659d19
673 673 user: test
674 674 date: Thu Jan 01 00:00:00 1970 +0000
675 675 summary: merge bar (amend message)
676 676
677 677 diff --git a/a b/aa
678 678 copy from a
679 679 copy to aa
680 680 diff --git a/cc b/cc
681 681 --- a/cc
682 682 +++ b/cc
683 683 @@ -1,1 +1,5 @@
684 684 +<<<<<<< local: 30d96aeaf27b - test: aa
685 685 dd
686 686 +=======
687 687 +cc
688 688 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
689 689 diff --git a/z b/zz
690 690 rename from z
691 691 rename to zz
692 692
693 693 $ hg debugrename aa
694 694 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
695 695 $ hg debugrename zz
696 696 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
697 697 $ hg debugrename cc
698 698 cc not renamed
699 699 $ hg mv zz z
700 700 $ hg ci --amend -m 'merge bar (undo rename)'
701 701 $ hg log --config diff.git=1 -pr .
702 702 changeset: 26:bdafc5c72f74
703 703 tag: tip
704 704 parent: 22:30d96aeaf27b
705 705 parent: 21:1aa437659d19
706 706 user: test
707 707 date: Thu Jan 01 00:00:00 1970 +0000
708 708 summary: merge bar (undo rename)
709 709
710 710 diff --git a/a b/aa
711 711 copy from a
712 712 copy to aa
713 713 diff --git a/cc b/cc
714 714 --- a/cc
715 715 +++ b/cc
716 716 @@ -1,1 +1,5 @@
717 717 +<<<<<<< local: 30d96aeaf27b - test: aa
718 718 dd
719 719 +=======
720 720 +cc
721 721 +>>>>>>> other: 1aa437659d19 bar - test: aazzcc
722 722
723 723 $ hg debugrename z
724 724 z not renamed
725 725
726 726 Amend a merge changeset (with renames during the merge):
727 727
728 728 $ hg up -q bar
729 729 $ echo x > x
730 730 $ hg add x
731 731 $ hg ci -m x
732 732 $ hg up -q default
733 733 $ hg merge -q bar
734 734 $ hg mv aa aaa
735 735 $ echo aa >> aaa
736 736 $ hg ci -m 'merge bar again'
737 737 $ hg log --config diff.git=1 -pr .
738 738 changeset: 28:32f19415b634
739 739 tag: tip
740 740 parent: 26:bdafc5c72f74
741 741 parent: 27:4c94d5bc65f5
742 742 user: test
743 743 date: Thu Jan 01 00:00:00 1970 +0000
744 744 summary: merge bar again
745 745
746 746 diff --git a/aa b/aa
747 747 deleted file mode 100644
748 748 --- a/aa
749 749 +++ /dev/null
750 750 @@ -1,2 +0,0 @@
751 751 -a
752 752 -a
753 753 diff --git a/aaa b/aaa
754 754 new file mode 100644
755 755 --- /dev/null
756 756 +++ b/aaa
757 757 @@ -0,0 +1,3 @@
758 758 +a
759 759 +a
760 760 +aa
761 761 diff --git a/x b/x
762 762 new file mode 100644
763 763 --- /dev/null
764 764 +++ b/x
765 765 @@ -0,0 +1,1 @@
766 766 +x
767 767
768 768 $ hg debugrename aaa
769 769 aaa renamed from aa:37d9b5d994eab34eda9c16b195ace52c7b129980
770 770 $ hg mv aaa aa
771 771 $ hg ci --amend -m 'merge bar again (undo rename)'
772 772 $ hg log --config diff.git=1 -pr .
773 773 changeset: 30:1e2a06b3d312
774 774 tag: tip
775 775 parent: 26:bdafc5c72f74
776 776 parent: 27:4c94d5bc65f5
777 777 user: test
778 778 date: Thu Jan 01 00:00:00 1970 +0000
779 779 summary: merge bar again (undo rename)
780 780
781 781 diff --git a/aa b/aa
782 782 --- a/aa
783 783 +++ b/aa
784 784 @@ -1,2 +1,3 @@
785 785 a
786 786 a
787 787 +aa
788 788 diff --git a/x b/x
789 789 new file mode 100644
790 790 --- /dev/null
791 791 +++ b/x
792 792 @@ -0,0 +1,1 @@
793 793 +x
794 794
795 795 $ hg debugrename aa
796 796 aa not renamed
797 797 $ hg debugrename -r '.^' aa
798 798 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
799 799
800 800 Amend a merge changeset (with manifest-level conflicts):
801 801
802 802 $ hg up -q bar
803 803 $ hg rm aa
804 804 $ hg ci -m 'rm aa'
805 805 $ hg up -q default
806 806 $ echo aa >> aa
807 807 $ hg ci -m aa
808 808 $ hg merge -q bar
809 809 local changed aa which remote deleted
810 810 use (c)hanged version or (d)elete? c
811 811 $ hg ci -m 'merge bar (with conflicts)'
812 812 $ hg log --config diff.git=1 -pr .
813 813 changeset: 33:97a298b0c59f
814 814 tag: tip
815 815 parent: 32:3d78ce4226b8
816 816 parent: 31:67db8847a540
817 817 user: test
818 818 date: Thu Jan 01 00:00:00 1970 +0000
819 819 summary: merge bar (with conflicts)
820 820
821 821
822 822 $ hg rm aa
823 823 $ hg ci --amend -m 'merge bar (with conflicts, amended)'
824 824 $ hg log --config diff.git=1 -pr .
825 825 changeset: 35:6de0c1bde1c8
826 826 tag: tip
827 827 parent: 32:3d78ce4226b8
828 828 parent: 31:67db8847a540
829 829 user: test
830 830 date: Thu Jan 01 00:00:00 1970 +0000
831 831 summary: merge bar (with conflicts, amended)
832 832
833 833 diff --git a/aa b/aa
834 834 deleted file mode 100644
835 835 --- a/aa
836 836 +++ /dev/null
837 837 @@ -1,4 +0,0 @@
838 838 -a
839 839 -a
840 840 -aa
841 841 -aa
842 842
843 843 Issue 3445: amending with --close-branch a commit that created a new head should fail
844 844 This shouldn't be possible:
845 845
846 846 $ hg up -q default
847 847 $ hg branch closewithamend
848 848 marked working directory as branch closewithamend
849 849 (branches are permanent and global, did you want a bookmark?)
850 850 $ echo foo > foo
851 851 $ hg add foo
852 852 $ hg ci -m..
853 853 $ hg ci --amend --close-branch -m 'closing'
854 854 abort: can only close branch heads
855 855 [255]
856 856
857 857 This silliness fails:
858 858
859 859 $ hg branch silliness
860 860 marked working directory as branch silliness
861 861 (branches are permanent and global, did you want a bookmark?)
862 862 $ echo b >> b
863 863 $ hg ci --close-branch -m'open and close'
864 864 abort: can only close branch heads
865 865 [255]
866 866
867 867 Test that amend with --secret creates new secret changeset forcibly
868 868 ---------------------------------------------------------------------
869 869
870 870 $ hg phase '.^::.'
871 871 35: draft
872 872 36: draft
873 873 $ hg commit --amend --secret -m 'amend as secret' -q
874 874 $ hg phase '.^::.'
875 875 35: draft
876 876 38: secret
877 877
878 878 Test that amend with --edit invokes editor forcibly
879 879 ---------------------------------------------------
880 880
881 881 $ hg parents --template "{desc}\n"
882 882 amend as secret
883 883 $ HGEDITOR=cat hg commit --amend -m "editor should be suppressed"
884 884 $ hg parents --template "{desc}\n"
885 885 editor should be suppressed
886 886
887 887 $ hg status --rev '.^1::.'
888 888 A foo
889 889 $ HGEDITOR=cat hg commit --amend -m "editor should be invoked" --edit
890 890 editor should be invoked
891 891
892 892
893 893 HG: Enter commit message. Lines beginning with 'HG:' are removed.
894 894 HG: Leave message empty to abort commit.
895 895 HG: --
896 896 HG: user: test
897 897 HG: branch 'silliness'
898 898 HG: added foo
899 899 $ hg parents --template "{desc}\n"
900 900 editor should be invoked
901 901
902 902 Test that "diff()" in committemplate works correctly for amending
903 903 -----------------------------------------------------------------
904 904
905 905 $ cat >> .hg/hgrc <<EOF
906 906 > [committemplate]
907 907 > changeset.commit.amend = {desc}\n
908 908 > HG: M: {file_mods}
909 909 > HG: A: {file_adds}
910 910 > HG: R: {file_dels}
911 911 > {splitlines(diff()) % 'HG: {line}\n'}
912 912 > EOF
913 913
914 914 $ hg parents --template "M: {file_mods}\nA: {file_adds}\nR: {file_dels}\n"
915 915 M:
916 916 A: foo
917 917 R:
918 918 $ hg status -amr
919 919 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of foo"
920 920 expecting diff of foo
921 921
922 922 HG: M:
923 923 HG: A: foo
924 924 HG: R:
925 925 HG: diff -r 6de0c1bde1c8 foo
926 926 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
927 927 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
928 928 HG: @@ -0,0 +1,1 @@
929 929 HG: +foo
930 930
931 931 $ echo y > y
932 932 $ hg add y
933 933 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of foo and y"
934 934 expecting diff of foo and y
935 935
936 936 HG: M:
937 937 HG: A: foo y
938 938 HG: R:
939 939 HG: diff -r 6de0c1bde1c8 foo
940 940 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
941 941 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
942 942 HG: @@ -0,0 +1,1 @@
943 943 HG: +foo
944 944 HG: diff -r 6de0c1bde1c8 y
945 945 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
946 946 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
947 947 HG: @@ -0,0 +1,1 @@
948 948 HG: +y
949 949
950 950 $ hg rm a
951 951 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of a, foo and y"
952 952 expecting diff of a, foo and y
953 953
954 954 HG: M:
955 955 HG: A: foo y
956 956 HG: R: a
957 957 HG: diff -r 6de0c1bde1c8 a
958 958 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
959 959 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
960 960 HG: @@ -1,2 +0,0 @@
961 961 HG: -a
962 962 HG: -a
963 963 HG: diff -r 6de0c1bde1c8 foo
964 964 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
965 965 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
966 966 HG: @@ -0,0 +1,1 @@
967 967 HG: +foo
968 968 HG: diff -r 6de0c1bde1c8 y
969 969 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
970 970 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
971 971 HG: @@ -0,0 +1,1 @@
972 972 HG: +y
973 973
974 974 $ hg rm x
975 975 $ HGEDITOR=cat hg commit --amend -e -m "expecting diff of a, foo, x and y"
976 976 expecting diff of a, foo, x and y
977 977
978 978 HG: M:
979 979 HG: A: foo y
980 980 HG: R: a x
981 981 HG: diff -r 6de0c1bde1c8 a
982 982 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
983 983 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
984 984 HG: @@ -1,2 +0,0 @@
985 985 HG: -a
986 986 HG: -a
987 987 HG: diff -r 6de0c1bde1c8 foo
988 988 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
989 989 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
990 990 HG: @@ -0,0 +1,1 @@
991 991 HG: +foo
992 992 HG: diff -r 6de0c1bde1c8 x
993 993 HG: --- a/x Thu Jan 01 00:00:00 1970 +0000
994 994 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
995 995 HG: @@ -1,1 +0,0 @@
996 996 HG: -x
997 997 HG: diff -r 6de0c1bde1c8 y
998 998 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
999 999 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
1000 1000 HG: @@ -0,0 +1,1 @@
1001 1001 HG: +y
1002 1002
1003 $ echo cccc >> cc
1004 $ hg status -amr
1005 M cc
1006 $ HGEDITOR=cat hg commit --amend -e -m "cc should be excluded" -X cc
1007 cc should be excluded
1008
1009 HG: M:
1010 HG: A: foo y
1011 HG: R: a x
1012 HG: diff -r 6de0c1bde1c8 a
1013 HG: --- a/a Thu Jan 01 00:00:00 1970 +0000
1014 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1015 HG: @@ -1,2 +0,0 @@
1016 HG: -a
1017 HG: -a
1018 HG: diff -r 6de0c1bde1c8 foo
1019 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1020 HG: +++ b/foo Thu Jan 01 00:00:00 1970 +0000
1021 HG: @@ -0,0 +1,1 @@
1022 HG: +foo
1023 HG: diff -r 6de0c1bde1c8 x
1024 HG: --- a/x Thu Jan 01 00:00:00 1970 +0000
1025 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1026 HG: @@ -1,1 +0,0 @@
1027 HG: -x
1028 HG: diff -r 6de0c1bde1c8 y
1029 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1030 HG: +++ b/y Thu Jan 01 00:00:00 1970 +0000
1031 HG: @@ -0,0 +1,1 @@
1032 HG: +y
1033
1003 1034 Check for issue4405
1004 1035 -------------------
1005 1036
1006 1037 Setup the repo with a file that gets moved in a second commit.
1007 1038 $ hg init repo
1008 1039 $ cd repo
1009 1040 $ touch a0
1010 1041 $ hg add a0
1011 1042 $ hg commit -m a0
1012 1043 $ hg mv a0 a1
1013 1044 $ hg commit -m a1
1014 1045 $ hg up -q 0
1015 1046 $ hg log -G --template '{rev} {desc}'
1016 1047 o 1 a1
1017 1048 |
1018 1049 @ 0 a0
1019 1050
1020 1051
1021 1052 Now we branch the repro, but re-use the file contents, so we have a divergence
1022 1053 in the file revlog topology and the changelog topology.
1023 1054 $ hg revert --rev 1 --all
1024 1055 removing a0
1025 1056 adding a1
1026 1057 $ hg ci -qm 'a1-amend'
1027 1058 $ hg log -G --template '{rev} {desc}'
1028 1059 @ 2 a1-amend
1029 1060 |
1030 1061 | o 1 a1
1031 1062 |/
1032 1063 o 0 a0
1033 1064
1034 1065
1035 1066 The way mercurial does amends is to create a temporary commit (rev 3) and then
1036 1067 fold the new and old commits together into another commit (rev 4). During this
1037 1068 process, _findlimit is called to check how far back to look for the transitive
1038 1069 closure of file copy information, but due to the divergence of the filelog
1039 1070 and changelog graph topologies, before _findlimit was fixed, it returned a rev
1040 1071 which was not far enough back in this case.
1041 1072 $ hg mv a1 a2
1042 1073 $ hg status --copies --rev 0
1043 1074 A a2
1044 1075 a0
1045 1076 R a0
1046 1077 $ hg ci --amend -q
1047 1078 $ hg log -G --template '{rev} {desc}'
1048 1079 @ 4 a1-amend
1049 1080 |
1050 1081 | o 1 a1
1051 1082 |/
1052 1083 o 0 a0
1053 1084
1054 1085
1055 1086 Before the fix, the copy information was lost.
1056 1087 $ hg status --copies --rev 0
1057 1088 A a2
1058 1089 a0
1059 1090 R a0
1060 1091 $ cd ..
1061 1092
1062 1093 Check that amend properly preserve rename from directory rename (issue-4516)
1063 1094
1064 1095 If a parent of the merge renames a full directory, any files added to the old
1065 1096 directory in the other parent will be renamed to the new directory. For some
1066 1097 reason, the rename metadata was when amending such merge. This test ensure we
1067 1098 do not regress. We have a dedicated repo because it needs a setup with renamed
1068 1099 directory)
1069 1100
1070 1101 $ hg init issue4516
1071 1102 $ cd issue4516
1072 1103 $ mkdir olddirname
1073 1104 $ echo line1 > olddirname/commonfile.py
1074 1105 $ hg add olddirname/commonfile.py
1075 1106 $ hg ci -m first
1076 1107
1077 1108 $ hg branch newdirname
1078 1109 marked working directory as branch newdirname
1079 1110 (branches are permanent and global, did you want a bookmark?)
1080 1111 $ hg mv olddirname newdirname
1081 1112 moving olddirname/commonfile.py to newdirname/commonfile.py (glob)
1082 1113 $ hg ci -m rename
1083 1114
1084 1115 $ hg update default
1085 1116 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1086 1117 $ echo line1 > olddirname/newfile.py
1087 1118 $ hg add olddirname/newfile.py
1088 1119 $ hg ci -m log
1089 1120
1090 1121 $ hg up newdirname
1091 1122 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1092 1123 $ # create newdirname/newfile.py
1093 1124 $ hg merge default
1094 1125 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1095 1126 (branch merge, don't forget to commit)
1096 1127 $ hg ci -m add
1097 1128 $
1098 1129 $ hg debugrename newdirname/newfile.py
1099 1130 newdirname/newfile.py renamed from olddirname/newfile.py:690b295714aed510803d3020da9c70fca8336def (glob)
1100 1131 $ hg status -C --change .
1101 1132 A newdirname/newfile.py
1102 1133 $ hg status -C --rev 1
1103 1134 A newdirname/newfile.py
1104 1135 $ hg status -C --rev 2
1105 1136 A newdirname/commonfile.py
1106 1137 olddirname/commonfile.py
1107 1138 A newdirname/newfile.py
1108 1139 olddirname/newfile.py
1109 1140 R olddirname/commonfile.py
1110 1141 R olddirname/newfile.py
1111 1142 $ hg debugindex newdirname/newfile.py
1112 1143 rev offset length base linkrev nodeid p1 p2
1113 1144 0 0 88 0 3 34a4d536c0c0 000000000000 000000000000
1114 1145
1115 1146 $ echo a >> newdirname/commonfile.py
1116 1147 $ hg ci --amend -m bug
1117 1148 $ hg debugrename newdirname/newfile.py
1118 1149 newdirname/newfile.py renamed from olddirname/newfile.py:690b295714aed510803d3020da9c70fca8336def (glob)
1119 1150 $ hg debugindex newdirname/newfile.py
1120 1151 rev offset length base linkrev nodeid p1 p2
1121 1152 0 0 88 0 3 34a4d536c0c0 000000000000 000000000000
1122 1153
@@ -1,604 +1,640 b''
1 1 commit date test
2 2
3 3 $ hg init test
4 4 $ cd test
5 5 $ echo foo > foo
6 6 $ hg add foo
7 7 $ cat > $TESTTMP/checkeditform.sh <<EOF
8 8 > env | grep HGEDITFORM
9 9 > true
10 10 > EOF
11 11 $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg commit -m ""
12 12 HGEDITFORM=commit.normal.normal
13 13 abort: empty commit message
14 14 [255]
15 15 $ hg commit -d '0 0' -m commit-1
16 16 $ echo foo >> foo
17 17 $ hg commit -d '1 4444444' -m commit-3
18 18 abort: impossible time zone offset: 4444444
19 19 [255]
20 20 $ hg commit -d '1 15.1' -m commit-4
21 21 abort: invalid date: '1\t15.1'
22 22 [255]
23 23 $ hg commit -d 'foo bar' -m commit-5
24 24 abort: invalid date: 'foo bar'
25 25 [255]
26 26 $ hg commit -d ' 1 4444' -m commit-6
27 27 $ hg commit -d '111111111111 0' -m commit-7
28 28 abort: date exceeds 32 bits: 111111111111
29 29 [255]
30 30 $ hg commit -d '-7654321 3600' -m commit-7
31 31 abort: negative date value: -7654321
32 32 [255]
33 33
34 34 commit added file that has been deleted
35 35
36 36 $ echo bar > bar
37 37 $ hg add bar
38 38 $ rm bar
39 39 $ hg commit -m commit-8
40 40 nothing changed (1 missing files, see 'hg status')
41 41 [1]
42 42 $ hg commit -m commit-8-2 bar
43 43 abort: bar: file not found!
44 44 [255]
45 45
46 46 $ hg -q revert -a --no-backup
47 47
48 48 $ mkdir dir
49 49 $ echo boo > dir/file
50 50 $ hg add
51 51 adding dir/file (glob)
52 52 $ hg -v commit -m commit-9 dir
53 53 committing files:
54 54 dir/file
55 55 committing manifest
56 56 committing changelog
57 57 committed changeset 2:d2a76177cb42
58 58
59 59 $ echo > dir.file
60 60 $ hg add
61 61 adding dir.file
62 62 $ hg commit -m commit-10 dir dir.file
63 63 abort: dir: no match under directory!
64 64 [255]
65 65
66 66 $ echo >> dir/file
67 67 $ mkdir bleh
68 68 $ mkdir dir2
69 69 $ cd bleh
70 70 $ hg commit -m commit-11 .
71 71 abort: bleh: no match under directory!
72 72 [255]
73 73 $ hg commit -m commit-12 ../dir ../dir2
74 74 abort: dir2: no match under directory!
75 75 [255]
76 76 $ hg -v commit -m commit-13 ../dir
77 77 committing files:
78 78 dir/file
79 79 committing manifest
80 80 committing changelog
81 81 committed changeset 3:1cd62a2d8db5
82 82 $ cd ..
83 83
84 84 $ hg commit -m commit-14 does-not-exist
85 85 abort: does-not-exist: * (glob)
86 86 [255]
87 87
88 88 #if symlink
89 89 $ ln -s foo baz
90 90 $ hg commit -m commit-15 baz
91 91 abort: baz: file not tracked!
92 92 [255]
93 93 #endif
94 94
95 95 $ touch quux
96 96 $ hg commit -m commit-16 quux
97 97 abort: quux: file not tracked!
98 98 [255]
99 99 $ echo >> dir/file
100 100 $ hg -v commit -m commit-17 dir/file
101 101 committing files:
102 102 dir/file
103 103 committing manifest
104 104 committing changelog
105 105 committed changeset 4:49176991390e
106 106
107 107 An empty date was interpreted as epoch origin
108 108
109 109 $ echo foo >> foo
110 110 $ hg commit -d '' -m commit-no-date
111 111 $ hg tip --template '{date|isodate}\n' | grep '1970'
112 112 [1]
113 113
114 114 Make sure we do not obscure unknown requires file entries (issue2649)
115 115
116 116 $ echo foo >> foo
117 117 $ echo fake >> .hg/requires
118 118 $ hg commit -m bla
119 119 abort: repository requires features unknown to this Mercurial: fake!
120 120 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
121 121 [255]
122 122
123 123 $ cd ..
124 124
125 125
126 126 partial subdir commit test
127 127
128 128 $ hg init test2
129 129 $ cd test2
130 130 $ mkdir foo
131 131 $ echo foo > foo/foo
132 132 $ mkdir bar
133 133 $ echo bar > bar/bar
134 134 $ hg add
135 135 adding bar/bar (glob)
136 136 adding foo/foo (glob)
137 137 $ HGEDITOR=cat hg ci -e -m commit-subdir-1 foo
138 138 commit-subdir-1
139 139
140 140
141 141 HG: Enter commit message. Lines beginning with 'HG:' are removed.
142 142 HG: Leave message empty to abort commit.
143 143 HG: --
144 144 HG: user: test
145 145 HG: branch 'default'
146 146 HG: added foo/foo
147 147
148 148
149 149 $ hg ci -m commit-subdir-2 bar
150 150
151 151 subdir log 1
152 152
153 153 $ hg log -v foo
154 154 changeset: 0:f97e73a25882
155 155 user: test
156 156 date: Thu Jan 01 00:00:00 1970 +0000
157 157 files: foo/foo
158 158 description:
159 159 commit-subdir-1
160 160
161 161
162 162
163 163 subdir log 2
164 164
165 165 $ hg log -v bar
166 166 changeset: 1:aa809156d50d
167 167 tag: tip
168 168 user: test
169 169 date: Thu Jan 01 00:00:00 1970 +0000
170 170 files: bar/bar
171 171 description:
172 172 commit-subdir-2
173 173
174 174
175 175
176 176 full log
177 177
178 178 $ hg log -v
179 179 changeset: 1:aa809156d50d
180 180 tag: tip
181 181 user: test
182 182 date: Thu Jan 01 00:00:00 1970 +0000
183 183 files: bar/bar
184 184 description:
185 185 commit-subdir-2
186 186
187 187
188 188 changeset: 0:f97e73a25882
189 189 user: test
190 190 date: Thu Jan 01 00:00:00 1970 +0000
191 191 files: foo/foo
192 192 description:
193 193 commit-subdir-1
194 194
195 195
196 196 $ cd ..
197 197
198 198
199 199 dot and subdir commit test
200 200
201 201 $ hg init test3
202 202 $ echo commit-foo-subdir > commit-log-test
203 203 $ cd test3
204 204 $ mkdir foo
205 205 $ echo foo content > foo/plain-file
206 206 $ hg add foo/plain-file
207 207 $ HGEDITOR=cat hg ci --edit -l ../commit-log-test foo
208 208 commit-foo-subdir
209 209
210 210
211 211 HG: Enter commit message. Lines beginning with 'HG:' are removed.
212 212 HG: Leave message empty to abort commit.
213 213 HG: --
214 214 HG: user: test
215 215 HG: branch 'default'
216 216 HG: added foo/plain-file
217 217
218 218
219 219 $ echo modified foo content > foo/plain-file
220 220 $ hg ci -m commit-foo-dot .
221 221
222 222 full log
223 223
224 224 $ hg log -v
225 225 changeset: 1:95b38e3a5b2e
226 226 tag: tip
227 227 user: test
228 228 date: Thu Jan 01 00:00:00 1970 +0000
229 229 files: foo/plain-file
230 230 description:
231 231 commit-foo-dot
232 232
233 233
234 234 changeset: 0:65d4e9386227
235 235 user: test
236 236 date: Thu Jan 01 00:00:00 1970 +0000
237 237 files: foo/plain-file
238 238 description:
239 239 commit-foo-subdir
240 240
241 241
242 242
243 243 subdir log
244 244
245 245 $ cd foo
246 246 $ hg log .
247 247 changeset: 1:95b38e3a5b2e
248 248 tag: tip
249 249 user: test
250 250 date: Thu Jan 01 00:00:00 1970 +0000
251 251 summary: commit-foo-dot
252 252
253 253 changeset: 0:65d4e9386227
254 254 user: test
255 255 date: Thu Jan 01 00:00:00 1970 +0000
256 256 summary: commit-foo-subdir
257 257
258 258 $ cd ..
259 259 $ cd ..
260 260
261 261 Issue1049: Hg permits partial commit of merge without warning
262 262
263 263 $ hg init issue1049
264 264 $ cd issue1049
265 265 $ echo a > a
266 266 $ hg ci -Ama
267 267 adding a
268 268 $ echo a >> a
269 269 $ hg ci -mb
270 270 $ hg up 0
271 271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
272 272 $ echo b >> a
273 273 $ hg ci -mc
274 274 created new head
275 275 $ HGMERGE=true hg merge
276 276 merging a
277 277 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
278 278 (branch merge, don't forget to commit)
279 279
280 280 should fail because we are specifying a file name
281 281
282 282 $ hg ci -mmerge a
283 283 abort: cannot partially commit a merge (do not specify files or patterns)
284 284 [255]
285 285
286 286 should fail because we are specifying a pattern
287 287
288 288 $ hg ci -mmerge -I a
289 289 abort: cannot partially commit a merge (do not specify files or patterns)
290 290 [255]
291 291
292 292 should succeed
293 293
294 294 $ HGEDITOR="sh $TESTTMP/checkeditform.sh" hg ci -mmerge --edit
295 295 HGEDITFORM=commit.normal.merge
296 296 $ cd ..
297 297
298 298
299 299 test commit message content
300 300
301 301 $ hg init commitmsg
302 302 $ cd commitmsg
303 303 $ echo changed > changed
304 304 $ echo removed > removed
305 305 $ hg book currentbookmark
306 306 $ hg ci -qAm init
307 307
308 308 $ hg rm removed
309 309 $ echo changed >> changed
310 310 $ echo added > added
311 311 $ hg add added
312 312 $ HGEDITOR=cat hg ci -A
313 313
314 314
315 315 HG: Enter commit message. Lines beginning with 'HG:' are removed.
316 316 HG: Leave message empty to abort commit.
317 317 HG: --
318 318 HG: user: test
319 319 HG: branch 'default'
320 320 HG: bookmark 'currentbookmark'
321 321 HG: added added
322 322 HG: changed changed
323 323 HG: removed removed
324 324 abort: empty commit message
325 325 [255]
326 326
327 327 test saving last-message.txt
328 328
329 329 $ hg init sub
330 330 $ echo a > sub/a
331 331 $ hg -R sub add sub/a
332 332 $ cat > sub/.hg/hgrc <<EOF
333 333 > [hooks]
334 334 > precommit.test-saving-last-message = false
335 335 > EOF
336 336
337 337 $ echo 'sub = sub' > .hgsub
338 338 $ hg add .hgsub
339 339
340 340 $ cat > $TESTTMP/editor.sh <<EOF
341 341 > echo "==== before editing:"
342 342 > cat \$1
343 343 > echo "===="
344 344 > echo "test saving last-message.txt" >> \$1
345 345 > EOF
346 346
347 347 $ rm -f .hg/last-message.txt
348 348 $ HGEDITOR="sh $TESTTMP/editor.sh" hg commit -S -q
349 349 ==== before editing:
350 350
351 351
352 352 HG: Enter commit message. Lines beginning with 'HG:' are removed.
353 353 HG: Leave message empty to abort commit.
354 354 HG: --
355 355 HG: user: test
356 356 HG: branch 'default'
357 357 HG: bookmark 'currentbookmark'
358 358 HG: subrepo sub
359 359 HG: added .hgsub
360 360 HG: added added
361 361 HG: changed .hgsubstate
362 362 HG: changed changed
363 363 HG: removed removed
364 364 ====
365 365 abort: precommit.test-saving-last-message hook exited with status 1 (in subrepo sub)
366 366 [255]
367 367 $ cat .hg/last-message.txt
368 368
369 369
370 370 test saving last-message.txt
371 371
372 372 test that '[committemplate] changeset' definition and commit log
373 373 specific template keywords work well
374 374
375 375 $ cat >> .hg/hgrc <<EOF
376 376 > [committemplate]
377 377 > changeset.commit.normal = HG: this is "commit.normal" template
378 378 > HG: {extramsg}
379 379 > {if(currentbookmark,
380 380 > "HG: bookmark '{currentbookmark}' is activated\n",
381 381 > "HG: no bookmark is activated\n")}{subrepos %
382 382 > "HG: subrepo '{subrepo}' is changed\n"}
383 383 >
384 384 > changeset.commit = HG: this is "commit" template
385 385 > HG: {extramsg}
386 386 > {if(currentbookmark,
387 387 > "HG: bookmark '{currentbookmark}' is activated\n",
388 388 > "HG: no bookmark is activated\n")}{subrepos %
389 389 > "HG: subrepo '{subrepo}' is changed\n"}
390 390 >
391 391 > changeset = HG: this is customized commit template
392 392 > HG: {extramsg}
393 393 > {if(currentbookmark,
394 394 > "HG: bookmark '{currentbookmark}' is activated\n",
395 395 > "HG: no bookmark is activated\n")}{subrepos %
396 396 > "HG: subrepo '{subrepo}' is changed\n"}
397 397 > EOF
398 398
399 399 $ hg init sub2
400 400 $ echo a > sub2/a
401 401 $ hg -R sub2 add sub2/a
402 402 $ echo 'sub2 = sub2' >> .hgsub
403 403
404 404 $ HGEDITOR=cat hg commit -S -q
405 405 HG: this is "commit.normal" template
406 406 HG: Leave message empty to abort commit.
407 407 HG: bookmark 'currentbookmark' is activated
408 408 HG: subrepo 'sub' is changed
409 409 HG: subrepo 'sub2' is changed
410 410 abort: empty commit message
411 411 [255]
412 412
413 413 $ cat >> .hg/hgrc <<EOF
414 414 > [committemplate]
415 415 > changeset.commit.normal =
416 416 > # now, "changeset.commit" should be chosen for "hg commit"
417 417 > EOF
418 418
419 419 $ hg bookmark --inactive currentbookmark
420 420 $ hg forget .hgsub
421 421 $ HGEDITOR=cat hg commit -q
422 422 HG: this is "commit" template
423 423 HG: Leave message empty to abort commit.
424 424 HG: no bookmark is activated
425 425 abort: empty commit message
426 426 [255]
427 427
428 428 $ cat >> .hg/hgrc <<EOF
429 429 > [committemplate]
430 430 > changeset.commit =
431 431 > # now, "changeset" should be chosen for "hg commit"
432 432 > EOF
433 433
434 434 $ HGEDITOR=cat hg commit -q
435 435 HG: this is customized commit template
436 436 HG: Leave message empty to abort commit.
437 437 HG: no bookmark is activated
438 438 abort: empty commit message
439 439 [255]
440 440
441 441 $ cat >> .hg/hgrc <<EOF
442 442 > [committemplate]
443 443 > changeset = {desc}
444 > HG: mods={file_mods}
445 > HG: adds={file_adds}
446 > HG: dels={file_dels}
444 447 > HG: files={files}
445 448 > HG:
446 449 > {splitlines(diff()) % 'HG: {line}\n'
447 450 > }HG:
451 > HG: mods={file_mods}
452 > HG: adds={file_adds}
453 > HG: dels={file_dels}
448 454 > HG: files={files}\n
449 455 > EOF
450 456 $ hg status -amr
451 457 M changed
452 458 A added
453 459 R removed
454 460 $ HGEDITOR=cat hg commit -q -e -m "foo bar" changed
455 461 foo bar
462 HG: mods=changed
463 HG: adds=
464 HG: dels=
456 465 HG: files=changed
457 466 HG:
458 467 HG: --- a/changed Thu Jan 01 00:00:00 1970 +0000
459 468 HG: +++ b/changed Thu Jan 01 00:00:00 1970 +0000
460 469 HG: @@ -1,1 +1,2 @@
461 470 HG: changed
462 471 HG: +changed
463 472 HG:
473 HG: mods=changed
474 HG: adds=
475 HG: dels=
464 476 HG: files=changed
465 477 $ hg status -amr
466 478 A added
467 479 R removed
468 480 $ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
469 481 M changed
470 482 A
471 483 R
472 484 $ hg rollback -q
473 485
474 486 $ cat >> .hg/hgrc <<EOF
475 487 > [committemplate]
476 488 > changeset = {desc}
489 > HG: mods={file_mods}
490 > HG: adds={file_adds}
491 > HG: dels={file_dels}
477 492 > HG: files={files}
478 493 > HG:
479 494 > {splitlines(diff("changed")) % 'HG: {line}\n'
480 495 > }HG:
496 > HG: mods={file_mods}
497 > HG: adds={file_adds}
498 > HG: dels={file_dels}
481 499 > HG: files={files}
482 500 > HG:
483 501 > {splitlines(diff("added")) % 'HG: {line}\n'
484 502 > }HG:
503 > HG: mods={file_mods}
504 > HG: adds={file_adds}
505 > HG: dels={file_dels}
485 506 > HG: files={files}
486 507 > HG:
487 508 > {splitlines(diff("removed")) % 'HG: {line}\n'
488 509 > }HG:
510 > HG: mods={file_mods}
511 > HG: adds={file_adds}
512 > HG: dels={file_dels}
489 513 > HG: files={files}\n
490 514 > EOF
491 515 $ HGEDITOR=cat hg commit -q -e -m "foo bar" added removed
492 516 foo bar
517 HG: mods=
518 HG: adds=added
519 HG: dels=removed
493 520 HG: files=added removed
494 521 HG:
495 522 HG:
523 HG: mods=
524 HG: adds=added
525 HG: dels=removed
496 526 HG: files=added removed
497 527 HG:
498 528 HG: --- /dev/null Thu Jan 01 00:00:00 1970 +0000
499 529 HG: +++ b/added Thu Jan 01 00:00:00 1970 +0000
500 530 HG: @@ -0,0 +1,1 @@
501 531 HG: +added
502 532 HG:
533 HG: mods=
534 HG: adds=added
535 HG: dels=removed
503 536 HG: files=added removed
504 537 HG:
505 538 HG: --- a/removed Thu Jan 01 00:00:00 1970 +0000
506 539 HG: +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
507 540 HG: @@ -1,1 +0,0 @@
508 541 HG: -removed
509 542 HG:
543 HG: mods=
544 HG: adds=added
545 HG: dels=removed
510 546 HG: files=added removed
511 547 $ hg status -amr
512 548 M changed
513 549 $ hg parents --template "M {file_mods}\nA {file_adds}\nR {file_dels}\n"
514 550 M
515 551 A added
516 552 R removed
517 553 $ hg rollback -q
518 554
519 555 $ cat >> .hg/hgrc <<EOF
520 556 > # disable customizing for subsequent tests
521 557 > [committemplate]
522 558 > changeset =
523 559 > EOF
524 560
525 561 $ cd ..
526 562
527 563
528 564 commit copy
529 565
530 566 $ hg init dir2
531 567 $ cd dir2
532 568 $ echo bleh > bar
533 569 $ hg add bar
534 570 $ hg ci -m 'add bar'
535 571
536 572 $ hg cp bar foo
537 573 $ echo >> bar
538 574 $ hg ci -m 'cp bar foo; change bar'
539 575
540 576 $ hg debugrename foo
541 577 foo renamed from bar:26d3ca0dfd18e44d796b564e38dd173c9668d3a9
542 578 $ hg debugindex bar
543 579 rev offset length ..... linkrev nodeid p1 p2 (re)
544 580 0 0 6 ..... 0 26d3ca0dfd18 000000000000 000000000000 (re)
545 581 1 6 7 ..... 1 d267bddd54f7 26d3ca0dfd18 000000000000 (re)
546 582
547 583 verify pathauditor blocks evil filepaths
548 584 $ cat > evil-commit.py <<EOF
549 585 > from mercurial import ui, hg, context, node
550 586 > notrc = u".h\u200cg".encode('utf-8') + '/hgrc'
551 587 > u = ui.ui()
552 588 > r = hg.repository(u, '.')
553 589 > def filectxfn(repo, memctx, path):
554 590 > return context.memfilectx(repo, path, '[hooks]\nupdate = echo owned')
555 591 > c = context.memctx(r, [r['tip'].node(), node.nullid],
556 592 > 'evil', [notrc], filectxfn, 0)
557 593 > r.commitctx(c)
558 594 > EOF
559 595 $ $PYTHON evil-commit.py
560 596 #if windows
561 597 $ hg co --clean tip
562 598 abort: path contains illegal component: .h\xe2\x80\x8cg\\hgrc (esc)
563 599 [255]
564 600 #else
565 601 $ hg co --clean tip
566 602 abort: path contains illegal component: .h\xe2\x80\x8cg/hgrc (esc)
567 603 [255]
568 604 #endif
569 605
570 606 $ hg rollback -f
571 607 repository tip rolled back to revision 1 (undo commit)
572 608 $ cat > evil-commit.py <<EOF
573 609 > from mercurial import ui, hg, context, node
574 610 > notrc = "HG~1/hgrc"
575 611 > u = ui.ui()
576 612 > r = hg.repository(u, '.')
577 613 > def filectxfn(repo, memctx, path):
578 614 > return context.memfilectx(repo, path, '[hooks]\nupdate = echo owned')
579 615 > c = context.memctx(r, [r['tip'].node(), node.nullid],
580 616 > 'evil', [notrc], filectxfn, 0)
581 617 > r.commitctx(c)
582 618 > EOF
583 619 $ $PYTHON evil-commit.py
584 620 $ hg co --clean tip
585 621 abort: path contains illegal component: HG~1/hgrc (glob)
586 622 [255]
587 623
588 624 $ hg rollback -f
589 625 repository tip rolled back to revision 1 (undo commit)
590 626 $ cat > evil-commit.py <<EOF
591 627 > from mercurial import ui, hg, context, node
592 628 > notrc = "HG8B6C~2/hgrc"
593 629 > u = ui.ui()
594 630 > r = hg.repository(u, '.')
595 631 > def filectxfn(repo, memctx, path):
596 632 > return context.memfilectx(repo, path, '[hooks]\nupdate = echo owned')
597 633 > c = context.memctx(r, [r['tip'].node(), node.nullid],
598 634 > 'evil', [notrc], filectxfn, 0)
599 635 > r.commitctx(c)
600 636 > EOF
601 637 $ $PYTHON evil-commit.py
602 638 $ hg co --clean tip
603 639 abort: path contains illegal component: HG8B6C~2/hgrc (glob)
604 640 [255]
General Comments 0
You need to be logged in to leave comments. Login now