##// END OF EJS Templates
commit: pass mergestate into _filecommit() instead of re-reading it...
Pulkit Goyal -
r46014:037e88d4 default
parent child Browse files
Show More
@@ -1,438 +1,442
1 1 # commit.py - fonction to perform commit
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5
6 6 from __future__ import absolute_import
7 7
8 8 import errno
9 9
10 10 from .i18n import _
11 11 from .node import (
12 12 hex,
13 13 nullid,
14 14 nullrev,
15 15 )
16 16
17 17 from . import (
18 18 context,
19 19 mergestate,
20 20 metadata,
21 21 phases,
22 22 scmutil,
23 23 subrepoutil,
24 24 )
25 25
26 26
27 27 def _write_copy_meta(repo):
28 28 """return a (changelog, filelog) boolean tuple
29 29
30 30 changelog: copy related information should be stored in the changeset
31 31 filelof: copy related information should be written in the file revision
32 32 """
33 33 if repo.filecopiesmode == b'changeset-sidedata':
34 34 writechangesetcopy = True
35 35 writefilecopymeta = True
36 36 else:
37 37 writecopiesto = repo.ui.config(b'experimental', b'copies.write-to')
38 38 writefilecopymeta = writecopiesto != b'changeset-only'
39 39 writechangesetcopy = writecopiesto in (
40 40 b'changeset-only',
41 41 b'compatibility',
42 42 )
43 43 return writechangesetcopy, writefilecopymeta
44 44
45 45
46 46 def commitctx(repo, ctx, error=False, origctx=None):
47 47 """Add a new revision to the target repository.
48 48 Revision information is passed via the context argument.
49 49
50 50 ctx.files() should list all files involved in this commit, i.e.
51 51 modified/added/removed files. On merge, it may be wider than the
52 52 ctx.files() to be committed, since any file nodes derived directly
53 53 from p1 or p2 are excluded from the committed ctx.files().
54 54
55 55 origctx is for convert to work around the problem that bug
56 56 fixes to the files list in changesets change hashes. For
57 57 convert to be the identity, it can pass an origctx and this
58 58 function will use the same files list when it makes sense to
59 59 do so.
60 60 """
61 61 repo = repo.unfiltered()
62 62
63 63 p1, p2 = ctx.p1(), ctx.p2()
64 64 user = ctx.user()
65 65
66 66 with repo.lock(), repo.transaction(b"commit") as tr:
67 67 mn, files = _prepare_files(tr, ctx, error=error, origctx=origctx)
68 68
69 69 extra = ctx.extra().copy()
70 70
71 71 if extra is not None:
72 72 for name in (
73 73 b'p1copies',
74 74 b'p2copies',
75 75 b'filesadded',
76 76 b'filesremoved',
77 77 ):
78 78 extra.pop(name, None)
79 79 if repo.changelog._copiesstorage == b'extra':
80 80 extra = _extra_with_copies(repo, extra, files)
81 81
82 82 # update changelog
83 83 repo.ui.note(_(b"committing changelog\n"))
84 84 repo.changelog.delayupdate(tr)
85 85 n = repo.changelog.add(
86 86 mn,
87 87 files,
88 88 ctx.description(),
89 89 tr,
90 90 p1.node(),
91 91 p2.node(),
92 92 user,
93 93 ctx.date(),
94 94 extra,
95 95 )
96 96 xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
97 97 repo.hook(
98 98 b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2,
99 99 )
100 100 # set the new commit is proper phase
101 101 targetphase = subrepoutil.newcommitphase(repo.ui, ctx)
102 102 if targetphase:
103 103 # retract boundary do not alter parent changeset.
104 104 # if a parent have higher the resulting phase will
105 105 # be compliant anyway
106 106 #
107 107 # if minimal phase was 0 we don't need to retract anything
108 108 phases.registernew(repo, tr, targetphase, [n])
109 109 return n
110 110
111 111
112 112 def _prepare_files(tr, ctx, error=False, origctx=None):
113 113 repo = ctx.repo()
114 114 p1 = ctx.p1()
115 115
116 116 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
117 117
118 118 if ctx.manifestnode():
119 119 # reuse an existing manifest revision
120 120 repo.ui.debug(b'reusing known manifest\n')
121 121 mn = ctx.manifestnode()
122 122 files = metadata.ChangingFiles()
123 123 files.update_touched(ctx.files())
124 124 if writechangesetcopy:
125 125 files.update_added(ctx.filesadded())
126 126 files.update_removed(ctx.filesremoved())
127 127 elif not ctx.files():
128 128 repo.ui.debug(b'reusing manifest from p1 (no file change)\n')
129 129 mn = p1.manifestnode()
130 130 files = metadata.ChangingFiles()
131 131 else:
132 132 mn, files = _process_files(tr, ctx, error=error)
133 133
134 134 if origctx and origctx.manifestnode() == mn:
135 135 origfiles = origctx.files()
136 136 assert files.touched.issubset(origfiles)
137 137 files.update_touched(origfiles)
138 138
139 139 if writechangesetcopy:
140 140 files.update_copies_from_p1(ctx.p1copies())
141 141 files.update_copies_from_p2(ctx.p2copies())
142 142
143 143 return mn, files
144 144
145 145
146 146 def _process_files(tr, ctx, error=False):
147 147 repo = ctx.repo()
148 148 p1 = ctx.p1()
149 149 p2 = ctx.p2()
150 150
151 151 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
152 152
153 153 m1ctx = p1.manifestctx()
154 154 m2ctx = p2.manifestctx()
155 155 mctx = m1ctx.copy()
156 156
157 157 m = mctx.read()
158 158 m1 = m1ctx.read()
159 159 m2 = m2ctx.read()
160 ms = mergestate.mergestate.read(repo)
160 161
161 162 files = metadata.ChangingFiles()
162 163
163 164 # check in files
164 165 added = []
165 166 removed = list(ctx.removed())
166 167 linkrev = len(repo)
167 168 repo.ui.note(_(b"committing files:\n"))
168 169 uipathfn = scmutil.getuipathfn(repo)
169 170 for f in sorted(ctx.modified() + ctx.added()):
170 171 repo.ui.note(uipathfn(f) + b"\n")
171 172 try:
172 173 fctx = ctx[f]
173 174 if fctx is None:
174 175 removed.append(f)
175 176 else:
176 177 added.append(f)
177 178 m[f], is_touched = _filecommit(
178 repo, fctx, m1, m2, linkrev, tr, writefilecopymeta,
179 repo, fctx, m1, m2, linkrev, tr, writefilecopymeta, ms
179 180 )
180 181 if is_touched:
181 182 if is_touched == 'added':
182 183 files.mark_added(f)
183 184 else:
184 185 files.mark_touched(f)
185 186 m.setflag(f, fctx.flags())
186 187 except OSError:
187 188 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
188 189 raise
189 190 except IOError as inst:
190 191 errcode = getattr(inst, 'errno', errno.ENOENT)
191 192 if error or errcode and errcode != errno.ENOENT:
192 193 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
193 194 raise
194 195
195 196 # update manifest
196 197 removed = [f for f in removed if f in m1 or f in m2]
197 198 drop = sorted([f for f in removed if f in m])
198 199 for f in drop:
199 200 del m[f]
200 201 if p2.rev() == nullrev:
201 202 files.update_removed(removed)
202 203 else:
203 204 rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2))
204 205 for f in removed:
205 206 if not rf(f):
206 207 files.mark_removed(f)
207 208
208 209 mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files.touched, added, drop)
209 210
210 211 return mn, files
211 212
212 213
213 214 def _filecommit(
214 repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta,
215 repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta, ms,
215 216 ):
216 217 """
217 218 commit an individual file as part of a larger transaction
218 219
219 220 input:
220 221
221 222 fctx: a file context with the content we are trying to commit
222 223 manifest1: manifest of changeset first parent
223 224 manifest2: manifest of changeset second parent
224 225 linkrev: revision number of the changeset being created
225 226 tr: current transation
226 227 includecopymeta: boolean, set to False to skip storing the copy data
227 228 (only used by the Google specific feature of using
228 229 changeset extra as copy source of truth).
230 ms: mergestate object
229 231
230 232 output: (filenode, touched)
231 233
232 234 filenode: the filenode that should be used by this changeset
233 235 touched: one of: None (mean untouched), 'added' or 'modified'
234 236 """
235 237
236 238 fname = fctx.path()
237 239 fparent1 = manifest1.get(fname, nullid)
238 240 fparent2 = manifest2.get(fname, nullid)
239 241 touched = None
240 242 if fparent1 == fparent2 == nullid:
241 243 touched = 'added'
242 244
243 245 if isinstance(fctx, context.filectx):
244 246 # This block fast path most comparisons which are usually done. It
245 247 # assumes that bare filectx is used and no merge happened, hence no
246 248 # need to create a new file revision in this case.
247 249 node = fctx.filenode()
248 250 if node in [fparent1, fparent2]:
249 251 repo.ui.debug(b'reusing %s filelog entry\n' % fname)
250 252 if (
251 253 fparent1 != nullid and manifest1.flags(fname) != fctx.flags()
252 254 ) or (
253 255 fparent2 != nullid and manifest2.flags(fname) != fctx.flags()
254 256 ):
255 257 touched = 'modified'
256 258 return node, touched
257 259
258 260 flog = repo.file(fname)
259 261 meta = {}
260 262 cfname = fctx.copysource()
261 263 fnode = None
262 264
263 265 if cfname and cfname != fname:
264 266 # Mark the new revision of this file as a copy of another
265 267 # file. This copy data will effectively act as a parent
266 268 # of this new revision. If this is a merge, the first
267 269 # parent will be the nullid (meaning "look up the copy data")
268 270 # and the second one will be the other parent. For example:
269 271 #
270 272 # 0 --- 1 --- 3 rev1 changes file foo
271 273 # \ / rev2 renames foo to bar and changes it
272 274 # \- 2 -/ rev3 should have bar with all changes and
273 275 # should record that bar descends from
274 276 # bar in rev2 and foo in rev1
275 277 #
276 278 # this allows this merge to succeed:
277 279 #
278 280 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
279 281 # \ / merging rev3 and rev4 should use bar@rev2
280 282 # \- 2 --- 4 as the merge base
281 283 #
282 284
283 285 cnode = manifest1.get(cfname)
284 286 newfparent = fparent2
285 287
286 288 if manifest2: # branch merge
287 289 if fparent2 == nullid or cnode is None: # copied on remote side
288 290 if cfname in manifest2:
289 291 cnode = manifest2[cfname]
290 292 newfparent = fparent1
291 293
292 294 # Here, we used to search backwards through history to try to find
293 295 # where the file copy came from if the source of a copy was not in
294 296 # the parent directory. However, this doesn't actually make sense to
295 297 # do (what does a copy from something not in your working copy even
296 298 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
297 299 # the user that copy information was dropped, so if they didn't
298 300 # expect this outcome it can be fixed, but this is the correct
299 301 # behavior in this circumstance.
300 302
301 303 if cnode:
302 304 repo.ui.debug(b" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)))
303 305 if includecopymeta:
304 306 meta[b"copy"] = cfname
305 307 meta[b"copyrev"] = hex(cnode)
306 308 fparent1, fparent2 = nullid, newfparent
307 309 else:
308 310 repo.ui.warn(
309 311 _(
310 312 b"warning: can't find ancestor for '%s' "
311 313 b"copied from '%s'!\n"
312 314 )
313 315 % (fname, cfname)
314 316 )
315 317
316 318 elif fparent1 == nullid:
317 319 fparent1, fparent2 = fparent2, nullid
318 320 elif fparent2 != nullid:
319 321 # is one parent an ancestor of the other?
320 322 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
321 323 if fparent1 in fparentancestors:
322 324 fparent1, fparent2 = fparent2, nullid
323 325 elif fparent2 in fparentancestors:
324 326 fparent2 = nullid
325 327 elif not fparentancestors:
326 328 # TODO: this whole if-else might be simplified much more
327 ms = mergestate.mergestate.read(repo)
328 if ms.extras(fname).get(b'filenode-source') == b'other':
329 if (
330 ms.active()
331 and ms.extras(fname).get(b'filenode-source') == b'other'
332 ):
329 333 fparent1, fparent2 = fparent2, nullid
330 334
331 335 # is the file changed?
332 336 text = fctx.data()
333 337 if fparent2 != nullid or meta or flog.cmp(fparent1, text):
334 338 if touched is None: # do not overwrite added
335 339 touched = 'modified'
336 340 fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2)
337 341 # are just the flags changed during merge?
338 342 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
339 343 touched = 'modified'
340 344 fnode = fparent1
341 345 else:
342 346 fnode = fparent1
343 347 return fnode, touched
344 348
345 349
346 350 def _commit_manifest(tr, linkrev, ctx, mctx, manifest, files, added, drop):
347 351 """make a new manifest entry (or reuse a new one)
348 352
349 353 given an initialised manifest context and precomputed list of
350 354 - files: files affected by the commit
351 355 - added: new entries in the manifest
352 356 - drop: entries present in parents but absent of this one
353 357
354 358 Create a new manifest revision, reuse existing ones if possible.
355 359
356 360 Return the nodeid of the manifest revision.
357 361 """
358 362 repo = ctx.repo()
359 363
360 364 md = None
361 365
362 366 # all this is cached, so it is find to get them all from the ctx.
363 367 p1 = ctx.p1()
364 368 p2 = ctx.p2()
365 369 m1ctx = p1.manifestctx()
366 370
367 371 m1 = m1ctx.read()
368 372
369 373 if not files:
370 374 # if no "files" actually changed in terms of the changelog,
371 375 # try hard to detect unmodified manifest entry so that the
372 376 # exact same commit can be reproduced later on convert.
373 377 md = m1.diff(manifest, scmutil.matchfiles(repo, ctx.files()))
374 378 if not files and md:
375 379 repo.ui.debug(
376 380 b'not reusing manifest (no file change in '
377 381 b'changelog, but manifest differs)\n'
378 382 )
379 383 if files or md:
380 384 repo.ui.note(_(b"committing manifest\n"))
381 385 # we're using narrowmatch here since it's already applied at
382 386 # other stages (such as dirstate.walk), so we're already
383 387 # ignoring things outside of narrowspec in most cases. The
384 388 # one case where we might have files outside the narrowspec
385 389 # at this point is merges, and we already error out in the
386 390 # case where the merge has files outside of the narrowspec,
387 391 # so this is safe.
388 392 mn = mctx.write(
389 393 tr,
390 394 linkrev,
391 395 p1.manifestnode(),
392 396 p2.manifestnode(),
393 397 added,
394 398 drop,
395 399 match=repo.narrowmatch(),
396 400 )
397 401 else:
398 402 repo.ui.debug(
399 403 b'reusing manifest from p1 (listed files ' b'actually unchanged)\n'
400 404 )
401 405 mn = p1.manifestnode()
402 406
403 407 return mn
404 408
405 409
406 410 def _extra_with_copies(repo, extra, files):
407 411 """encode copy information into a `extra` dictionnary"""
408 412 p1copies = files.copied_from_p1
409 413 p2copies = files.copied_from_p2
410 414 filesadded = files.added
411 415 filesremoved = files.removed
412 416 files = sorted(files.touched)
413 417 if not _write_copy_meta(repo)[1]:
414 418 # If writing only to changeset extras, use None to indicate that
415 419 # no entry should be written. If writing to both, write an empty
416 420 # entry to prevent the reader from falling back to reading
417 421 # filelogs.
418 422 p1copies = p1copies or None
419 423 p2copies = p2copies or None
420 424 filesadded = filesadded or None
421 425 filesremoved = filesremoved or None
422 426
423 427 extrasentries = p1copies, p2copies, filesadded, filesremoved
424 428 if extra is None and any(x is not None for x in extrasentries):
425 429 extra = {}
426 430 if p1copies is not None:
427 431 p1copies = metadata.encodecopies(files, p1copies)
428 432 extra[b'p1copies'] = p1copies
429 433 if p2copies is not None:
430 434 p2copies = metadata.encodecopies(files, p2copies)
431 435 extra[b'p2copies'] = p2copies
432 436 if filesadded is not None:
433 437 filesadded = metadata.encodefileindices(files, filesadded)
434 438 extra[b'filesadded'] = filesadded
435 439 if filesremoved is not None:
436 440 filesremoved = metadata.encodefileindices(files, filesremoved)
437 441 extra[b'filesremoved'] = filesremoved
438 442 return extra
@@ -1,1202 +1,1202
1 1 $ cat >> "$HGRCPATH" << EOF
2 2 > [ui]
3 3 > merge = :merge3
4 4 > EOF
5 5
6 6 init
7 7
8 8 $ hg init repo
9 9 $ cd repo
10 10
11 11 commit
12 12
13 13 $ echo 'a' > a
14 14 $ hg ci -A -m test -u nobody -d '1 0'
15 15 adding a
16 16
17 17 annotate -c
18 18
19 19 $ hg annotate -c a
20 20 8435f90966e4: a
21 21
22 22 annotate -cl
23 23
24 24 $ hg annotate -cl a
25 25 8435f90966e4:1: a
26 26
27 27 annotate -d
28 28
29 29 $ hg annotate -d a
30 30 Thu Jan 01 00:00:01 1970 +0000: a
31 31
32 32 annotate -n
33 33
34 34 $ hg annotate -n a
35 35 0: a
36 36
37 37 annotate -nl
38 38
39 39 $ hg annotate -nl a
40 40 0:1: a
41 41
42 42 annotate -u
43 43
44 44 $ hg annotate -u a
45 45 nobody: a
46 46
47 47 annotate -cdnu
48 48
49 49 $ hg annotate -cdnu a
50 50 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000: a
51 51
52 52 annotate -cdnul
53 53
54 54 $ hg annotate -cdnul a
55 55 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000:1: a
56 56
57 57 annotate (JSON)
58 58
59 59 $ hg annotate -Tjson a
60 60 [
61 61 {
62 62 "lines": [{"line": "a\n", "rev": 0}],
63 63 "path": "a"
64 64 }
65 65 ]
66 66
67 67 $ hg annotate -Tjson -cdfnul a
68 68 [
69 69 {
70 70 "lines": [{"date": [1.0, 0], "line": "a\n", "lineno": 1, "node": "8435f90966e442695d2ded29fdade2bac5ad8065", "path": "a", "rev": 0, "user": "nobody"}],
71 71 "path": "a"
72 72 }
73 73 ]
74 74
75 75 log-like templating
76 76
77 77 $ hg annotate -T'{lines % "{rev} {node|shortest}: {line}"}' a
78 78 0 8435: a
79 79
80 80 '{lineno}' field should be populated as necessary
81 81
82 82 $ hg annotate -T'{lines % "{rev}:{lineno}: {line}"}' a
83 83 0:1: a
84 84 $ hg annotate -Ta a \
85 85 > --config templates.a='"{lines % "{rev}:{lineno}: {line}"}"'
86 86 0:1: a
87 87
88 88 $ cat <<EOF >>a
89 89 > a
90 90 > a
91 91 > EOF
92 92 $ hg ci -ma1 -d '1 0'
93 93 $ hg cp a b
94 94 $ hg ci -mb -d '1 0'
95 95 $ cat <<EOF >> b
96 96 > b4
97 97 > b5
98 98 > b6
99 99 > EOF
100 100 $ hg ci -mb2 -d '2 0'
101 101
102 102 default output of '{lines}' should be readable
103 103
104 104 $ hg annotate -T'{lines}' a
105 105 0: a
106 106 1: a
107 107 1: a
108 108 $ hg annotate -T'{join(lines, "\n")}' a
109 109 0: a
110 110
111 111 1: a
112 112
113 113 1: a
114 114
115 115 several filters can be applied to '{lines}'
116 116
117 117 $ hg annotate -T'{lines|json}\n' a
118 118 [{"line": "a\n", "rev": 0}, {"line": "a\n", "rev": 1}, {"line": "a\n", "rev": 1}]
119 119 $ hg annotate -T'{lines|stringify}' a
120 120 0: a
121 121 1: a
122 122 1: a
123 123 $ hg annotate -T'{lines|count}\n' a
124 124 3
125 125
126 126 annotate multiple files (JSON)
127 127
128 128 $ hg annotate -Tjson a b
129 129 [
130 130 {
131 131 "lines": [{"line": "a\n", "rev": 0}, {"line": "a\n", "rev": 1}, {"line": "a\n", "rev": 1}],
132 132 "path": "a"
133 133 },
134 134 {
135 135 "lines": [{"line": "a\n", "rev": 0}, {"line": "a\n", "rev": 1}, {"line": "a\n", "rev": 1}, {"line": "b4\n", "rev": 3}, {"line": "b5\n", "rev": 3}, {"line": "b6\n", "rev": 3}],
136 136 "path": "b"
137 137 }
138 138 ]
139 139
140 140 annotate multiple files (template)
141 141
142 142 $ hg annotate -T'== {path} ==\n{lines % "{rev}: {line}"}' a b
143 143 == a ==
144 144 0: a
145 145 1: a
146 146 1: a
147 147 == b ==
148 148 0: a
149 149 1: a
150 150 1: a
151 151 3: b4
152 152 3: b5
153 153 3: b6
154 154
155 155 annotate -n b
156 156
157 157 $ hg annotate -n b
158 158 0: a
159 159 1: a
160 160 1: a
161 161 3: b4
162 162 3: b5
163 163 3: b6
164 164
165 165 annotate --no-follow b
166 166
167 167 $ hg annotate --no-follow b
168 168 2: a
169 169 2: a
170 170 2: a
171 171 3: b4
172 172 3: b5
173 173 3: b6
174 174
175 175 annotate -nl b
176 176
177 177 $ hg annotate -nl b
178 178 0:1: a
179 179 1:2: a
180 180 1:3: a
181 181 3:4: b4
182 182 3:5: b5
183 183 3:6: b6
184 184
185 185 annotate -nf b
186 186
187 187 $ hg annotate -nf b
188 188 0 a: a
189 189 1 a: a
190 190 1 a: a
191 191 3 b: b4
192 192 3 b: b5
193 193 3 b: b6
194 194
195 195 annotate -nlf b
196 196
197 197 $ hg annotate -nlf b
198 198 0 a:1: a
199 199 1 a:2: a
200 200 1 a:3: a
201 201 3 b:4: b4
202 202 3 b:5: b5
203 203 3 b:6: b6
204 204
205 205 $ hg up -C 2
206 206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 207 $ cat <<EOF >> b
208 208 > b4
209 209 > c
210 210 > b5
211 211 > EOF
212 212 $ hg ci -mb2.1 -d '2 0'
213 213 created new head
214 214 $ hg merge
215 215 merging b
216 216 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
217 217 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
218 218 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
219 219 [1]
220 220 $ cat b
221 221 a
222 222 a
223 223 a
224 224 <<<<<<< working copy: 5fbdc1152d97 - test: b2.1
225 225 b4
226 226 c
227 227 b5
228 228 ||||||| base
229 229 =======
230 230 b4
231 231 b5
232 232 b6
233 233 >>>>>>> merge rev: 37ec9f5c3d1f - test: b2
234 234 $ cat <<EOF > b
235 235 > a
236 236 > a
237 237 > a
238 238 > b4
239 239 > c
240 240 > b5
241 241 > EOF
242 242 $ hg resolve --mark -q
243 243 $ rm b.orig
244 244 $ hg ci -mmergeb -d '3 0'
245 245
246 246 annotate after merge
247 247
248 248 $ hg annotate -nf b
249 249 0 a: a
250 250 1 a: a
251 251 1 a: a
252 252 3 b: b4
253 253 4 b: c
254 254 3 b: b5
255 255
256 256 annotate after merge with -l
257 257
258 258 $ hg annotate -nlf b
259 259 0 a:1: a
260 260 1 a:2: a
261 261 1 a:3: a
262 262 3 b:4: b4
263 263 4 b:5: c
264 264 3 b:5: b5
265 265
266 266 $ hg up -C 1
267 267 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
268 268 $ hg cp a b
269 269 $ cat <<EOF > b
270 270 > a
271 271 > z
272 272 > a
273 273 > EOF
274 274 $ hg ci -mc -d '3 0'
275 275 created new head
276 276 Work around the pure version not resolving the conflict like native code
277 277 #if pure
278 278 $ hg merge
279 279 merging b
280 280 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
281 281 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
282 282 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
283 283 [1]
284 284 $ cat <<EOF > b
285 285 > a
286 286 > z
287 287 > a
288 288 > b4
289 289 > c
290 290 > b5
291 291 > EOF
292 292 $ hg resolve -m b
293 293 (no more unresolved files)
294 294 $ rm b.orig
295 295 #else
296 296 $ hg merge
297 297 merging b
298 298 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
299 299 (branch merge, don't forget to commit)
300 300 #endif
301 301 $ echo d >> b
302 302 $ hg ci -mmerge2 -d '4 0'
303 303
304 304 annotate after rename merge
305 305
306 306 $ hg annotate -nf b
307 307 0 a: a
308 308 6 b: z
309 309 1 a: a
310 310 3 b: b4
311 311 4 b: c
312 312 3 b: b5
313 313 7 b: d
314 314
315 315 annotate after rename merge with -l
316 316
317 317 $ hg annotate -nlf b
318 318 0 a:1: a
319 319 6 b:2: z
320 320 1 a:3: a
321 321 3 b:4: b4
322 322 4 b:5: c
323 323 3 b:5: b5
324 324 7 b:7: d
325 325
326 326 --skip nothing (should be the same as no --skip at all)
327 327
328 328 $ hg annotate -nlf b --skip '1::0'
329 329 0 a:1: a
330 330 6 b:2: z
331 331 1 a:3: a
332 332 3 b:4: b4
333 333 4 b:5: c
334 334 3 b:5: b5
335 335 7 b:7: d
336 336
337 337 --skip a modified line. Note a slight behavior difference in pure - this is
338 338 because the pure code comes up with slightly different deltas internally.
339 339
340 340 $ hg annotate -nlf b --skip 6
341 341 0 a:1: a
342 342 1 a:2* z (no-pure !)
343 343 0 a:1* z (pure !)
344 344 1 a:3: a
345 345 3 b:4: b4
346 346 4 b:5: c
347 347 3 b:5: b5
348 348 7 b:7: d
349 349
350 350 --skip added lines (and test multiple skip)
351 351
352 352 $ hg annotate -nlf b --skip 3
353 353 0 a:1: a
354 354 6 b:2: z
355 355 1 a:3: a
356 356 1 a:3* b4
357 357 4 b:5: c
358 358 1 a:3* b5
359 359 7 b:7: d
360 360
361 361 $ hg annotate -nlf b --skip 4
362 362 0 a:1: a
363 363 6 b:2: z
364 364 1 a:3: a
365 365 3 b:4: b4
366 366 1 a:3* c
367 367 3 b:5: b5
368 368 7 b:7: d
369 369
370 370 $ hg annotate -nlf b --skip 3 --skip 4
371 371 0 a:1: a
372 372 6 b:2: z
373 373 1 a:3: a
374 374 1 a:3* b4
375 375 1 a:3* c
376 376 1 a:3* b5
377 377 7 b:7: d
378 378
379 379 $ hg annotate -nlf b --skip 'merge()'
380 380 0 a:1: a
381 381 6 b:2: z
382 382 1 a:3: a
383 383 3 b:4: b4
384 384 4 b:5: c
385 385 3 b:5: b5
386 386 3 b:5* d
387 387
388 388 --skip everything -- use the revision the file was introduced in
389 389
390 390 $ hg annotate -nlf b --skip 'all()'
391 391 0 a:1: a
392 392 0 a:1* z
393 393 0 a:1* a
394 394 0 a:1* b4
395 395 0 a:1* c
396 396 0 a:1* b5
397 397 0 a:1* d
398 398
399 399 Issue2807: alignment of line numbers with -l
400 400
401 401 $ echo more >> b
402 402 $ hg ci -mmore -d '5 0'
403 403 $ echo more >> b
404 404 $ hg ci -mmore -d '6 0'
405 405 $ echo more >> b
406 406 $ hg ci -mmore -d '7 0'
407 407 $ hg annotate -nlf b
408 408 0 a: 1: a
409 409 6 b: 2: z
410 410 1 a: 3: a
411 411 3 b: 4: b4
412 412 4 b: 5: c
413 413 3 b: 5: b5
414 414 7 b: 7: d
415 415 8 b: 8: more
416 416 9 b: 9: more
417 417 10 b:10: more
418 418
419 419 linkrev vs rev
420 420
421 421 $ hg annotate -r tip -n a
422 422 0: a
423 423 1: a
424 424 1: a
425 425
426 426 linkrev vs rev with -l
427 427
428 428 $ hg annotate -r tip -nl a
429 429 0:1: a
430 430 1:2: a
431 431 1:3: a
432 432
433 433 Issue589: "undelete" sequence leads to crash
434 434
435 435 annotate was crashing when trying to --follow something
436 436
437 437 like A -> B -> A
438 438
439 439 generate ABA rename configuration
440 440
441 441 $ echo foo > foo
442 442 $ hg add foo
443 443 $ hg ci -m addfoo
444 444 $ hg rename foo bar
445 445 $ hg ci -m renamefoo
446 446 $ hg rename bar foo
447 447 $ hg ci -m renamebar
448 448
449 449 annotate after ABA with follow
450 450
451 451 $ hg annotate --follow foo
452 452 foo: foo
453 453
454 454 missing file
455 455
456 456 $ hg ann nosuchfile
457 457 abort: nosuchfile: no such file in rev e9e6b4fa872f
458 458 [255]
459 459
460 460 annotate file without '\n' on last line
461 461
462 462 $ printf "" > c
463 463 $ hg ci -A -m test -u nobody -d '1 0'
464 464 adding c
465 465 $ hg annotate c
466 466 $ printf "a\nb" > c
467 467 $ hg ci -m test
468 468 $ hg annotate c
469 469 [0-9]+: a (re)
470 470 [0-9]+: b (re)
471 471
472 472 Issue3841: check annotation of the file of which filelog includes
473 473 merging between the revision and its ancestor
474 474
475 475 to reproduce the situation with recent Mercurial, this script uses (1)
476 476 "hg debugsetparents" to merge without ancestor check by "hg merge",
477 477 and (2) the extension to allow filelog merging between the revision
478 478 and its ancestor by overriding "repo._filecommit".
479 479
480 480 $ cat > ../legacyrepo.py <<EOF
481 481 > from __future__ import absolute_import
482 482 > from mercurial import commit, error, extensions, node
483 483 > def _filecommit(orig, repo, fctx, manifest1, manifest2,
484 > linkrev, tr, includecopymeta):
484 > linkrev, tr, includecopymeta, ms):
485 485 > fname = fctx.path()
486 486 > text = fctx.data()
487 487 > flog = repo.file(fname)
488 488 > fparent1 = manifest1.get(fname, node.nullid)
489 489 > fparent2 = manifest2.get(fname, node.nullid)
490 490 > meta = {}
491 491 > copy = fctx.copysource()
492 492 > if copy and copy != fname:
493 493 > raise error.Abort('copying is not supported')
494 494 > if fparent2 != node.nullid:
495 495 > return flog.add(text, meta, tr, linkrev,
496 496 > fparent1, fparent2), 'modified'
497 497 > raise error.Abort('only merging is supported')
498 498 > def uisetup(ui):
499 499 > extensions.wrapfunction(commit, '_filecommit', _filecommit)
500 500 > EOF
501 501
502 502 $ cat > baz <<EOF
503 503 > 1
504 504 > 2
505 505 > 3
506 506 > 4
507 507 > 5
508 508 > EOF
509 509 $ hg add baz
510 510 $ hg commit -m "baz:0"
511 511
512 512 $ cat > baz <<EOF
513 513 > 1 baz:1
514 514 > 2
515 515 > 3
516 516 > 4
517 517 > 5
518 518 > EOF
519 519 $ hg commit -m "baz:1"
520 520
521 521 $ cat > baz <<EOF
522 522 > 1 baz:1
523 523 > 2 baz:2
524 524 > 3
525 525 > 4
526 526 > 5
527 527 > EOF
528 528 $ hg debugsetparents 17 17
529 529 $ hg --config extensions.legacyrepo=../legacyrepo.py commit -m "baz:2"
530 530 $ hg debugindexdot baz
531 531 digraph G {
532 532 -1 -> 0
533 533 0 -> 1
534 534 1 -> 2
535 535 1 -> 2
536 536 }
537 537 $ hg annotate baz
538 538 17: 1 baz:1
539 539 18: 2 baz:2
540 540 16: 3
541 541 16: 4
542 542 16: 5
543 543
544 544 $ cat > baz <<EOF
545 545 > 1 baz:1
546 546 > 2 baz:2
547 547 > 3 baz:3
548 548 > 4
549 549 > 5
550 550 > EOF
551 551 $ hg commit -m "baz:3"
552 552
553 553 $ cat > baz <<EOF
554 554 > 1 baz:1
555 555 > 2 baz:2
556 556 > 3 baz:3
557 557 > 4 baz:4
558 558 > 5
559 559 > EOF
560 560 $ hg debugsetparents 19 18
561 561 $ hg --config extensions.legacyrepo=../legacyrepo.py commit -m "baz:4"
562 562 $ hg debugindexdot baz
563 563 digraph G {
564 564 -1 -> 0
565 565 0 -> 1
566 566 1 -> 2
567 567 1 -> 2
568 568 2 -> 3
569 569 3 -> 4
570 570 2 -> 4
571 571 }
572 572 $ hg annotate baz
573 573 17: 1 baz:1
574 574 18: 2 baz:2
575 575 19: 3 baz:3
576 576 20: 4 baz:4
577 577 16: 5
578 578
579 579 annotate clean file
580 580
581 581 $ hg annotate -ncr "wdir()" foo
582 582 11 472b18db256d : foo
583 583
584 584 annotate modified file
585 585
586 586 $ echo foofoo >> foo
587 587 $ hg annotate -r "wdir()" foo
588 588 11 : foo
589 589 20+: foofoo
590 590
591 591 $ hg annotate -cr "wdir()" foo
592 592 472b18db256d : foo
593 593 b6bedd5477e7+: foofoo
594 594
595 595 $ hg annotate -ncr "wdir()" foo
596 596 11 472b18db256d : foo
597 597 20 b6bedd5477e7+: foofoo
598 598
599 599 $ hg annotate --debug -ncr "wdir()" foo
600 600 11 472b18db256d1e8282064eab4bfdaf48cbfe83cd : foo
601 601 20 b6bedd5477e797f25e568a6402d4697f3f895a72+: foofoo
602 602
603 603 $ hg annotate -udr "wdir()" foo
604 604 test Thu Jan 01 00:00:00 1970 +0000: foo
605 605 test [A-Za-z0-9:+ ]+: foofoo (re)
606 606
607 607 $ hg annotate -ncr "wdir()" -Tjson foo
608 608 [
609 609 {
610 610 "lines": [{"line": "foo\n", "node": "472b18db256d1e8282064eab4bfdaf48cbfe83cd", "rev": 11}, {"line": "foofoo\n", "node": "ffffffffffffffffffffffffffffffffffffffff", "rev": 2147483647}],
611 611 "path": "foo"
612 612 }
613 613 ]
614 614
615 615 annotate added file
616 616
617 617 $ echo bar > bar
618 618 $ hg add bar
619 619 $ hg annotate -ncr "wdir()" bar
620 620 20 b6bedd5477e7+: bar
621 621
622 622 annotate renamed file
623 623
624 624 $ hg rename foo renamefoo2
625 625 $ hg annotate -ncr "wdir()" renamefoo2
626 626 11 472b18db256d : foo
627 627 20 b6bedd5477e7+: foofoo
628 628
629 629 annotate missing file
630 630
631 631 $ rm baz
632 632
633 633 $ hg annotate -ncr "wdir()" baz
634 634 abort: $TESTTMP\repo\baz: $ENOENT$ (windows !)
635 635 abort: $ENOENT$: '$TESTTMP/repo/baz' (no-windows !)
636 636 [255]
637 637
638 638 annotate removed file
639 639
640 640 $ hg rm baz
641 641
642 642 $ hg annotate -ncr "wdir()" baz
643 643 abort: $TESTTMP\repo\baz: $ENOENT$ (windows !)
644 644 abort: $ENOENT$: '$TESTTMP/repo/baz' (no-windows !)
645 645 [255]
646 646
647 647 $ hg revert --all --no-backup --quiet
648 648 $ hg id -n
649 649 20
650 650
651 651 Test followlines() revset; we usually check both followlines(pat, range) and
652 652 followlines(pat, range, descend=True) to make sure both give the same result
653 653 when they should.
654 654
655 655 $ echo a >> foo
656 656 $ hg ci -m 'foo: add a'
657 657 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5)'
658 658 16: baz:0
659 659 19: baz:3
660 660 20: baz:4
661 661 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, startrev=20)'
662 662 16: baz:0
663 663 19: baz:3
664 664 20: baz:4
665 665 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, startrev=19)'
666 666 16: baz:0
667 667 19: baz:3
668 668 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, startrev=19, descend=True)'
669 669 19: baz:3
670 670 20: baz:4
671 671 $ printf "0\n0\n" | cat - baz > baz1
672 672 $ mv baz1 baz
673 673 $ hg ci -m 'added two lines with 0'
674 674 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7)'
675 675 16: baz:0
676 676 19: baz:3
677 677 20: baz:4
678 678 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, descend=true, startrev=19)'
679 679 19: baz:3
680 680 20: baz:4
681 681 $ echo 6 >> baz
682 682 $ hg ci -m 'added line 8'
683 683 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7)'
684 684 16: baz:0
685 685 19: baz:3
686 686 20: baz:4
687 687 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, startrev=19, descend=1)'
688 688 19: baz:3
689 689 20: baz:4
690 690 $ sed 's/3/3+/' baz > baz.new
691 691 $ mv baz.new baz
692 692 $ hg ci -m 'baz:3->3+'
693 693 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7, descend=0)'
694 694 16: baz:0
695 695 19: baz:3
696 696 20: baz:4
697 697 24: baz:3->3+
698 698 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:5, startrev=17, descend=True)'
699 699 19: baz:3
700 700 20: baz:4
701 701 24: baz:3->3+
702 702 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 1:2, descend=false)'
703 703 22: added two lines with 0
704 704
705 705 file patterns are okay
706 706 $ hg log -T '{rev}: {desc}\n' -r 'followlines("path:baz", 1:2)'
707 707 22: added two lines with 0
708 708
709 709 renames are followed
710 710 $ hg mv baz qux
711 711 $ sed 's/4/4+/' qux > qux.new
712 712 $ mv qux.new qux
713 713 $ hg ci -m 'qux:4->4+'
714 714 $ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5:7)'
715 715 16: baz:0
716 716 19: baz:3
717 717 20: baz:4
718 718 24: baz:3->3+
719 719 25: qux:4->4+
720 720
721 721 but are missed when following children
722 722 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7, startrev=22, descend=True)'
723 723 24: baz:3->3+
724 724
725 725 merge
726 726 $ hg up 24 --quiet
727 727 $ echo 7 >> baz
728 728 $ hg ci -m 'one more line, out of line range'
729 729 created new head
730 730 $ sed 's/3+/3-/' baz > baz.new
731 731 $ mv baz.new baz
732 732 $ hg ci -m 'baz:3+->3-'
733 733 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7)'
734 734 16: baz:0
735 735 19: baz:3
736 736 20: baz:4
737 737 24: baz:3->3+
738 738 27: baz:3+->3-
739 739 $ hg merge 25
740 740 merging baz and qux to qux
741 741 warning: conflicts while merging qux! (edit, then use 'hg resolve --mark')
742 742 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
743 743 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
744 744 [1]
745 745 $ cat qux
746 746 0
747 747 0
748 748 1 baz:1
749 749 2 baz:2
750 750 <<<<<<< working copy: 863de62655ef - test: baz:3+->3-
751 751 3- baz:3
752 752 4 baz:4
753 753 ||||||| base
754 754 3+ baz:3
755 755 4 baz:4
756 756 =======
757 757 3+ baz:3
758 758 4+ baz:4
759 759 >>>>>>> merge rev: cb8df70ae185 - test: qux:4->4+
760 760 5
761 761 6
762 762 7
763 763 $ cat > qux <<EOF
764 764 > 0
765 765 > 0
766 766 > 1 baz:1
767 767 > 2 baz:2
768 768 > 3- baz:3
769 769 > 4 baz:4
770 770 > 5
771 771 > 6
772 772 > 7
773 773 > EOF
774 774 $ hg resolve --mark -q
775 775 $ rm qux.orig
776 776 $ hg ci -m merge
777 777 $ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5:7)'
778 778 16: baz:0
779 779 19: baz:3
780 780 20: baz:4
781 781 24: baz:3->3+
782 782 25: qux:4->4+
783 783 27: baz:3+->3-
784 784 28: merge
785 785 $ hg up 25 --quiet
786 786 $ hg merge 27
787 787 merging qux and baz to qux
788 788 warning: conflicts while merging qux! (edit, then use 'hg resolve --mark')
789 789 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
790 790 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
791 791 [1]
792 792 $ cat qux
793 793 0
794 794 0
795 795 1 baz:1
796 796 2 baz:2
797 797 <<<<<<< working copy: cb8df70ae185 - test: qux:4->4+
798 798 3+ baz:3
799 799 4+ baz:4
800 800 ||||||| base
801 801 3+ baz:3
802 802 4 baz:4
803 803 =======
804 804 3- baz:3
805 805 4 baz:4
806 806 >>>>>>> merge rev: 863de62655ef - test: baz:3+->3-
807 807 5
808 808 6
809 809 7
810 810 $ cat > qux <<EOF
811 811 > 0
812 812 > 0
813 813 > 1 baz:1
814 814 > 2 baz:2
815 815 > 3+ baz:3
816 816 > 4+ baz:4
817 817 > 5
818 818 > 6
819 819 > EOF
820 820 $ hg resolve --mark -q
821 821 $ rm qux.orig
822 822 $ hg ci -m 'merge from other side'
823 823 created new head
824 824 $ hg log -T '{rev}: {desc}\n' -r 'followlines(qux, 5:7)'
825 825 16: baz:0
826 826 19: baz:3
827 827 20: baz:4
828 828 24: baz:3->3+
829 829 25: qux:4->4+
830 830 27: baz:3+->3-
831 831 29: merge from other side
832 832 $ hg up 24 --quiet
833 833
834 834 we are missing the branch with rename when following children
835 835 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 5:7, startrev=26, descend=True)'
836 836 27: baz:3+->3-
837 837
838 838 we follow all branches in descending direction
839 839 $ hg up 23 --quiet
840 840 $ sed 's/3/+3/' baz > baz.new
841 841 $ mv baz.new baz
842 842 $ hg ci -m 'baz:3->+3'
843 843 created new head
844 844 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 2:5, startrev=16, descend=True)' --graph
845 845 @ 30: baz:3->+3
846 846 :
847 847 : o 27: baz:3+->3-
848 848 : :
849 849 : o 24: baz:3->3+
850 850 :/
851 851 o 20: baz:4
852 852 |\
853 853 | o 19: baz:3
854 854 |/
855 855 o 18: baz:2
856 856 :
857 857 o 16: baz:0
858 858 |
859 859 ~
860 860
861 861 Issue5595: on a merge changeset with different line ranges depending on
862 862 parent, be conservative and use the surrounding interval to avoid loosing
863 863 track of possible further descendants in specified range.
864 864
865 865 $ hg up 23 --quiet
866 866 $ hg cat baz -r 24
867 867 0
868 868 0
869 869 1 baz:1
870 870 2 baz:2
871 871 3+ baz:3
872 872 4 baz:4
873 873 5
874 874 6
875 875 $ cat > baz << EOF
876 876 > 0
877 877 > 0
878 878 > a
879 879 > b
880 880 > 3+ baz:3
881 881 > 4 baz:4
882 882 > y
883 883 > z
884 884 > EOF
885 885 $ hg ci -m 'baz: mostly rewrite with some content from 24'
886 886 created new head
887 887 $ hg merge --tool :merge-other 24
888 888 merging baz
889 889 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
890 890 (branch merge, don't forget to commit)
891 891 $ hg ci -m 'merge forgetting about baz rewrite'
892 892 $ cat > baz << EOF
893 893 > 0
894 894 > 0
895 895 > 1 baz:1
896 896 > 2+ baz:2
897 897 > 3+ baz:3
898 898 > 4 baz:4
899 899 > 5
900 900 > 6
901 901 > EOF
902 902 $ hg ci -m 'baz: narrow change (2->2+)'
903 903 $ hg log -T '{rev}: {desc}\n' -r 'followlines(baz, 3:4, startrev=20, descend=True)' --graph
904 904 @ 33: baz: narrow change (2->2+)
905 905 |
906 906 o 32: merge forgetting about baz rewrite
907 907 |\
908 908 | o 31: baz: mostly rewrite with some content from 24
909 909 | :
910 910 | : o 30: baz:3->+3
911 911 | :/
912 912 +---o 27: baz:3+->3-
913 913 | :
914 914 o : 24: baz:3->3+
915 915 :/
916 916 o 20: baz:4
917 917 |\
918 918 ~ ~
919 919
920 920 An integer as a line range, which is parsed as '1:1'
921 921
922 922 $ hg log -r 'followlines(baz, 1)'
923 923 changeset: 22:2174d0bf352a
924 924 user: test
925 925 date: Thu Jan 01 00:00:00 1970 +0000
926 926 summary: added two lines with 0
927 927
928 928
929 929 check error cases
930 930 $ hg up 24 --quiet
931 931 $ hg log -r 'followlines()'
932 932 hg: parse error: followlines takes at least 1 positional arguments
933 933 [255]
934 934 $ hg log -r 'followlines(baz)'
935 935 hg: parse error: followlines requires a line range
936 936 [255]
937 937 $ hg log -r 'followlines(baz, x)'
938 938 hg: parse error: followlines expects a line number or a range
939 939 [255]
940 940 $ hg log -r 'followlines(baz, 1:2, startrev=desc("b"))'
941 941 hg: parse error: followlines expects exactly one revision
942 942 [255]
943 943 $ hg log -r 'followlines("glob:*", 1:2)'
944 944 hg: parse error: followlines expects exactly one file
945 945 [255]
946 946 $ hg log -r 'followlines(baz, 1:)'
947 947 hg: parse error: line range bounds must be integers
948 948 [255]
949 949 $ hg log -r 'followlines(baz, :1)'
950 950 hg: parse error: line range bounds must be integers
951 951 [255]
952 952 $ hg log -r 'followlines(baz, x:4)'
953 953 hg: parse error: line range bounds must be integers
954 954 [255]
955 955 $ hg log -r 'followlines(baz, 5:4)'
956 956 hg: parse error: line range must be positive
957 957 [255]
958 958 $ hg log -r 'followlines(baz, 0:4)'
959 959 hg: parse error: fromline must be strictly positive
960 960 [255]
961 961 $ hg log -r 'followlines(baz, 2:40)'
962 962 abort: line range exceeds file size
963 963 [255]
964 964 $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=[1])'
965 965 hg: parse error at 43: not a prefix: [
966 966 (followlines(baz, 2:4, startrev=20, descend=[1])
967 967 ^ here)
968 968 [255]
969 969 $ hg log -r 'followlines(baz, 2:4, startrev=20, descend=a)'
970 970 hg: parse error: descend argument must be a boolean
971 971 [255]
972 972
973 973 Test empty annotate output
974 974
975 975 $ printf '\0' > binary
976 976 $ touch empty
977 977 $ hg ci -qAm 'add binary and empty files'
978 978
979 979 $ hg annotate binary empty
980 980 binary: binary file
981 981
982 982 $ hg annotate -Tjson binary empty
983 983 [
984 984 {
985 985 "path": "binary"
986 986 },
987 987 {
988 988 "lines": [],
989 989 "path": "empty"
990 990 }
991 991 ]
992 992
993 993 Test annotate with whitespace options
994 994
995 995 $ cd ..
996 996 $ hg init repo-ws
997 997 $ cd repo-ws
998 998 $ cat > a <<EOF
999 999 > aa
1000 1000 >
1001 1001 > b b
1002 1002 > EOF
1003 1003 $ hg ci -Am "adda"
1004 1004 adding a
1005 1005 $ sed 's/EOL$//g' > a <<EOF
1006 1006 > a a
1007 1007 >
1008 1008 > EOL
1009 1009 > b b
1010 1010 > EOF
1011 1011 $ hg ci -m "changea"
1012 1012
1013 1013 Annotate with no option
1014 1014
1015 1015 $ hg annotate a
1016 1016 1: a a
1017 1017 0:
1018 1018 1:
1019 1019 1: b b
1020 1020
1021 1021 Annotate with --ignore-space-change
1022 1022
1023 1023 $ hg annotate --ignore-space-change a
1024 1024 1: a a
1025 1025 1:
1026 1026 0:
1027 1027 0: b b
1028 1028
1029 1029 Annotate with --ignore-all-space
1030 1030
1031 1031 $ hg annotate --ignore-all-space a
1032 1032 0: a a
1033 1033 0:
1034 1034 1:
1035 1035 0: b b
1036 1036
1037 1037 Annotate with --ignore-blank-lines (similar to no options case)
1038 1038
1039 1039 $ hg annotate --ignore-blank-lines a
1040 1040 1: a a
1041 1041 0:
1042 1042 1:
1043 1043 1: b b
1044 1044
1045 1045 $ cd ..
1046 1046
1047 1047 Annotate with orphaned CR (issue5798)
1048 1048 -------------------------------------
1049 1049
1050 1050 $ hg init repo-cr
1051 1051 $ cd repo-cr
1052 1052
1053 1053 $ cat <<'EOF' >> "$TESTTMP/substcr.py"
1054 1054 > import sys
1055 1055 > from mercurial.utils import procutil
1056 1056 > procutil.setbinary(sys.stdin)
1057 1057 > procutil.setbinary(sys.stdout)
1058 1058 > stdin = getattr(sys.stdin, 'buffer', sys.stdin)
1059 1059 > stdout = getattr(sys.stdout, 'buffer', sys.stdout)
1060 1060 > stdout.write(stdin.read().replace(b'\r', b'[CR]'))
1061 1061 > EOF
1062 1062
1063 1063 >>> with open('a', 'wb') as f:
1064 1064 ... f.write(b'0a\r0b\r\n0c\r0d\r\n0e\n0f\n0g') and None
1065 1065 $ hg ci -qAm0
1066 1066 >>> with open('a', 'wb') as f:
1067 1067 ... f.write(b'0a\r0b\r\n1c\r1d\r\n0e\n1f\n0g') and None
1068 1068 $ hg ci -m1
1069 1069
1070 1070 $ hg annotate -r0 a | "$PYTHON" "$TESTTMP/substcr.py"
1071 1071 0: 0a[CR]0b[CR]
1072 1072 0: 0c[CR]0d[CR]
1073 1073 0: 0e
1074 1074 0: 0f
1075 1075 0: 0g
1076 1076 $ hg annotate -r1 a | "$PYTHON" "$TESTTMP/substcr.py"
1077 1077 0: 0a[CR]0b[CR]
1078 1078 1: 1c[CR]1d[CR]
1079 1079 0: 0e
1080 1080 1: 1f
1081 1081 0: 0g
1082 1082
1083 1083 $ cd ..
1084 1084
1085 1085 Annotate with linkrev pointing to another branch
1086 1086 ------------------------------------------------
1087 1087
1088 1088 create history with a filerev whose linkrev points to another branch
1089 1089
1090 1090 $ hg init branchedlinkrev
1091 1091 $ cd branchedlinkrev
1092 1092 $ echo A > a
1093 1093 $ hg commit -Am 'contentA'
1094 1094 adding a
1095 1095 $ echo B >> a
1096 1096 $ hg commit -m 'contentB'
1097 1097 $ hg up --rev 'desc(contentA)'
1098 1098 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1099 1099 $ echo unrelated > unrelated
1100 1100 $ hg commit -Am 'unrelated'
1101 1101 adding unrelated
1102 1102 created new head
1103 1103 $ hg graft -r 'desc(contentB)'
1104 1104 grafting 1:fd27c222e3e6 "contentB"
1105 1105 $ echo C >> a
1106 1106 $ hg commit -m 'contentC'
1107 1107 $ echo W >> a
1108 1108 $ hg log -G
1109 1109 @ changeset: 4:072f1e8df249
1110 1110 | tag: tip
1111 1111 | user: test
1112 1112 | date: Thu Jan 01 00:00:00 1970 +0000
1113 1113 | summary: contentC
1114 1114 |
1115 1115 o changeset: 3:ff38df03cc4b
1116 1116 | user: test
1117 1117 | date: Thu Jan 01 00:00:00 1970 +0000
1118 1118 | summary: contentB
1119 1119 |
1120 1120 o changeset: 2:62aaf3f6fc06
1121 1121 | parent: 0:f0932f74827e
1122 1122 | user: test
1123 1123 | date: Thu Jan 01 00:00:00 1970 +0000
1124 1124 | summary: unrelated
1125 1125 |
1126 1126 | o changeset: 1:fd27c222e3e6
1127 1127 |/ user: test
1128 1128 | date: Thu Jan 01 00:00:00 1970 +0000
1129 1129 | summary: contentB
1130 1130 |
1131 1131 o changeset: 0:f0932f74827e
1132 1132 user: test
1133 1133 date: Thu Jan 01 00:00:00 1970 +0000
1134 1134 summary: contentA
1135 1135
1136 1136
1137 1137 Annotate should list ancestor of starting revision only
1138 1138
1139 1139 $ hg annotate a
1140 1140 0: A
1141 1141 3: B
1142 1142 4: C
1143 1143
1144 1144 $ hg annotate a -r 'wdir()'
1145 1145 0 : A
1146 1146 3 : B
1147 1147 4 : C
1148 1148 4+: W
1149 1149
1150 1150 Even when the starting revision is the linkrev-shadowed one:
1151 1151
1152 1152 $ hg annotate a -r 3
1153 1153 0: A
1154 1154 3: B
1155 1155
1156 1156 $ cd ..
1157 1157
1158 1158 Issue5360: Deleted chunk in p1 of a merge changeset
1159 1159
1160 1160 $ hg init repo-5360
1161 1161 $ cd repo-5360
1162 1162 $ echo 1 > a
1163 1163 $ hg commit -A a -m 1
1164 1164 $ echo 2 >> a
1165 1165 $ hg commit -m 2
1166 1166 $ echo a > a
1167 1167 $ hg commit -m a
1168 1168 $ hg update '.^' -q
1169 1169 $ echo 3 >> a
1170 1170 $ hg commit -m 3 -q
1171 1171 $ hg merge 2 -q
1172 1172 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
1173 1173 [1]
1174 1174 $ cat a
1175 1175 <<<<<<< working copy: 0a068f0261cf - test: 3
1176 1176 1
1177 1177 2
1178 1178 3
1179 1179 ||||||| base
1180 1180 1
1181 1181 2
1182 1182 =======
1183 1183 a
1184 1184 >>>>>>> merge rev: 9409851bc20a - test: a
1185 1185 $ cat > a << EOF
1186 1186 > b
1187 1187 > 1
1188 1188 > 2
1189 1189 > 3
1190 1190 > a
1191 1191 > EOF
1192 1192 $ hg resolve --mark -q
1193 1193 $ rm a.orig
1194 1194 $ hg commit -m m
1195 1195 $ hg annotate a
1196 1196 4: b
1197 1197 0: 1
1198 1198 1: 2
1199 1199 3: 3
1200 1200 2: a
1201 1201
1202 1202 $ cd ..
@@ -1,819 +1,819
1 1 (this file is backported from core hg tests/test-annotate.t)
2 2
3 3 $ cat >> $HGRCPATH << EOF
4 4 > [ui]
5 5 > merge = :merge3
6 6 > [diff]
7 7 > git=1
8 8 > [extensions]
9 9 > fastannotate=
10 10 > [fastannotate]
11 11 > modes=fctx
12 12 > forcefollow=False
13 13 > mainbranch=.
14 14 > EOF
15 15
16 16 init
17 17
18 18 $ hg init repo
19 19 $ cd repo
20 20
21 21 commit
22 22
23 23 $ echo 'a' > a
24 24 $ hg ci -A -m test -u nobody -d '1 0'
25 25 adding a
26 26
27 27 annotate -c
28 28
29 29 $ hg annotate -c a
30 30 8435f90966e4: a
31 31
32 32 annotate -cl
33 33
34 34 $ hg annotate -cl a
35 35 8435f90966e4:1: a
36 36
37 37 annotate -d
38 38
39 39 $ hg annotate -d a
40 40 Thu Jan 01 00:00:01 1970 +0000: a
41 41
42 42 annotate -n
43 43
44 44 $ hg annotate -n a
45 45 0: a
46 46
47 47 annotate -nl
48 48
49 49 $ hg annotate -nl a
50 50 0:1: a
51 51
52 52 annotate -u
53 53
54 54 $ hg annotate -u a
55 55 nobody: a
56 56
57 57 annotate -cdnu
58 58
59 59 $ hg annotate -cdnu a
60 60 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000: a
61 61
62 62 annotate -cdnul
63 63
64 64 $ hg annotate -cdnul a
65 65 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000:1: a
66 66
67 67 annotate (JSON)
68 68
69 69 $ hg annotate -Tjson a
70 70 [
71 71 {
72 72 "lines": [{"line": "a\n", "rev": 0}],
73 73 "path": "a"
74 74 }
75 75 ]
76 76
77 77 $ hg annotate -Tjson -cdfnul a
78 78 [
79 79 {
80 80 "lines": [{"date": [1.0, 0], "line": "a\n", "lineno": 1, "node": "8435f90966e442695d2ded29fdade2bac5ad8065", "path": "a", "rev": 0, "user": "nobody"}],
81 81 "path": "a"
82 82 }
83 83 ]
84 84
85 85 $ cat <<EOF >>a
86 86 > a
87 87 > a
88 88 > EOF
89 89 $ hg ci -ma1 -d '1 0'
90 90 $ hg cp a b
91 91 $ hg ci -mb -d '1 0'
92 92 $ cat <<EOF >> b
93 93 > b4
94 94 > b5
95 95 > b6
96 96 > EOF
97 97 $ hg ci -mb2 -d '2 0'
98 98
99 99 annotate -n b
100 100
101 101 $ hg annotate -n b
102 102 0: a
103 103 1: a
104 104 1: a
105 105 3: b4
106 106 3: b5
107 107 3: b6
108 108
109 109 annotate --no-follow b
110 110
111 111 $ hg annotate --no-follow b
112 112 2: a
113 113 2: a
114 114 2: a
115 115 3: b4
116 116 3: b5
117 117 3: b6
118 118
119 119 annotate -nl b
120 120
121 121 $ hg annotate -nl b
122 122 0:1: a
123 123 1:2: a
124 124 1:3: a
125 125 3:4: b4
126 126 3:5: b5
127 127 3:6: b6
128 128
129 129 annotate -nf b
130 130
131 131 $ hg annotate -nf b
132 132 0 a: a
133 133 1 a: a
134 134 1 a: a
135 135 3 b: b4
136 136 3 b: b5
137 137 3 b: b6
138 138
139 139 annotate -nlf b
140 140
141 141 $ hg annotate -nlf b
142 142 0 a:1: a
143 143 1 a:2: a
144 144 1 a:3: a
145 145 3 b:4: b4
146 146 3 b:5: b5
147 147 3 b:6: b6
148 148
149 149 $ hg up -C 2
150 150 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 151 $ cat <<EOF >> b
152 152 > b4
153 153 > c
154 154 > b5
155 155 > EOF
156 156 $ hg ci -mb2.1 -d '2 0'
157 157 created new head
158 158 $ hg merge
159 159 merging b
160 160 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
161 161 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
162 162 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
163 163 [1]
164 164 $ cat b
165 165 a
166 166 a
167 167 a
168 168 <<<<<<< working copy: 5fbdc1152d97 - test: b2.1
169 169 b4
170 170 c
171 171 b5
172 172 ||||||| base
173 173 =======
174 174 b4
175 175 b5
176 176 b6
177 177 >>>>>>> merge rev: 37ec9f5c3d1f - test: b2
178 178 $ cat <<EOF > b
179 179 > a
180 180 > a
181 181 > a
182 182 > b4
183 183 > c
184 184 > b5
185 185 > EOF
186 186 $ hg resolve --mark -q
187 187 $ rm b.orig
188 188 $ hg ci -mmergeb -d '3 0'
189 189
190 190 annotate after merge
191 191 (note: the first one falls back to the vanilla annotate which does not use linelog)
192 192
193 193 $ hg annotate -nf b --debug
194 194 fastannotate: b: rebuilding broken cache
195 195 fastannotate: b: 5 new changesets in the main branch
196 196 0 a: a
197 197 1 a: a
198 198 1 a: a
199 199 3 b: b4
200 200 4 b: c
201 201 3 b: b5
202 202
203 203 (difference explained below)
204 204
205 205 $ hg annotate -nf b --debug
206 206 fastannotate: b: using fast path (resolved fctx: False)
207 207 0 a: a
208 208 1 a: a
209 209 1 a: a
210 210 4 b: b4
211 211 4 b: c
212 212 4 b: b5
213 213
214 214 annotate after merge with -l
215 215 (fastannotate differs from annotate)
216 216
217 217 $ hg log -Gp -T '{rev}:{node}' -r '2..5'
218 218 @ 5:64afcdf8e29e063c635be123d8d2fb160af00f7e
219 219 |\
220 220 | o 4:5fbdc1152d97597717021ad9e063061b200f146bdiff --git a/b b/b
221 221 | | --- a/b
222 222 | | +++ b/b
223 223 | | @@ -1,3 +1,6 @@
224 224 | | a
225 225 | | a
226 226 | | a
227 227 | | +b4
228 228 | | +c
229 229 | | +b5
230 230 | |
231 231 o | 3:37ec9f5c3d1f99572d7075971cb4876e2139b52fdiff --git a/b b/b
232 232 |/ --- a/b
233 233 | +++ b/b
234 234 | @@ -1,3 +1,6 @@
235 235 | a
236 236 | a
237 237 | a
238 238 | +b4
239 239 | +b5
240 240 | +b6
241 241 |
242 242 o 2:3086dbafde1ce745abfc8d2d367847280aabae9ddiff --git a/a b/b
243 243 | copy from a
244 244 ~ copy to b
245 245
246 246
247 247 (in this case, "b4", "b5" could be considered introduced by either rev 3, or rev 4.
248 248 and that causes the rev number difference)
249 249
250 250 $ hg annotate -nlf b --config fastannotate.modes=
251 251 0 a:1: a
252 252 1 a:2: a
253 253 1 a:3: a
254 254 3 b:4: b4
255 255 4 b:5: c
256 256 3 b:5: b5
257 257
258 258 $ hg annotate -nlf b
259 259 0 a:1: a
260 260 1 a:2: a
261 261 1 a:3: a
262 262 4 b:4: b4
263 263 4 b:5: c
264 264 4 b:6: b5
265 265
266 266 $ hg up -C 1
267 267 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
268 268 $ hg cp a b
269 269 $ cat <<EOF > b
270 270 > a
271 271 > z
272 272 > a
273 273 > EOF
274 274 $ hg ci -mc -d '3 0'
275 275 created new head
276 276 Work around the pure version not resolving the conflict like native code
277 277 #if pure
278 278 $ hg merge
279 279 merging b
280 280 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
281 281 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
282 282 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
283 283 [1]
284 284 $ cat <<EOF > b
285 285 > a
286 286 > z
287 287 > a
288 288 > b4
289 289 > c
290 290 > b5
291 291 > EOF
292 292 $ hg resolve -m b
293 293 (no more unresolved files)
294 294 $ rm b.orig
295 295 #else
296 296 $ hg merge
297 297 merging b
298 298 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
299 299 (branch merge, don't forget to commit)
300 300 #endif
301 301 $ echo d >> b
302 302 $ hg ci -mmerge2 -d '4 0'
303 303
304 304 annotate after rename merge
305 305
306 306 $ hg annotate -nf b
307 307 0 a: a
308 308 6 b: z
309 309 1 a: a
310 310 3 b: b4
311 311 4 b: c
312 312 3 b: b5
313 313 7 b: d
314 314
315 315 annotate after rename merge with -l
316 316 (fastannotate differs from annotate)
317 317
318 318 $ hg log -Gp -T '{rev}:{node}' -r '0+1+6+7'
319 319 @ 7:6284bb6c38fef984a929862a53bbc71ce9eafa81diff --git a/b b/b
320 320 |\ --- a/b
321 321 | : +++ b/b
322 322 | : @@ -1,3 +1,7 @@
323 323 | : a
324 324 | : z
325 325 | : a
326 326 | : +b4
327 327 | : +c
328 328 | : +b5
329 329 | : +d
330 330 | :
331 331 o : 6:b80e3e32f75a6a67cd4ac85496a11511e9112816diff --git a/a b/b
332 332 :/ copy from a
333 333 : copy to b
334 334 : --- a/a
335 335 : +++ b/b
336 336 : @@ -1,3 +1,3 @@
337 337 : -a (?)
338 338 : a
339 339 : +z
340 340 : a
341 341 : -a (?)
342 342 :
343 343 o 1:762f04898e6684ff713415f7b8a8d53d33f96c92diff --git a/a b/a
344 344 | --- a/a
345 345 | +++ b/a
346 346 | @@ -1,1 +1,3 @@
347 347 | a
348 348 | +a
349 349 | +a
350 350 |
351 351 o 0:8435f90966e442695d2ded29fdade2bac5ad8065diff --git a/a b/a
352 352 new file mode 100644
353 353 --- /dev/null
354 354 +++ b/a
355 355 @@ -0,0 +1,1 @@
356 356 +a
357 357
358 358
359 359 (note on question marks:
360 360 the upstream bdiff change (96f2f50d923f+3633403888ae+8c0c75aa3ff4+5c4e2636c1a9
361 361 +38ed54888617) alters the output so deletion is not always at the end of the
362 362 output. for example:
363 363 | a | b | old | new | # old: e1d6aa0e4c3a, new: 8836f13e3c5b
364 364 |-------------------|
365 365 | a | a | a | -a |
366 366 | a | z | +z | a |
367 367 | a | a | a | +z |
368 368 | | | -a | a |
369 369 |-------------------|
370 370 | a | a | a |
371 371 | a | a | a |
372 372 | a | | -a |
373 373 this leads to more question marks below)
374 374
375 375 (rev 1 adds two "a"s and rev 6 deletes one "a".
376 376 the "a" that rev 6 deletes could be either the first or the second "a" of those two "a"s added by rev 1.
377 377 and that causes the line number difference)
378 378
379 379 $ hg annotate -nlf b --config fastannotate.modes=
380 380 0 a:1: a
381 381 6 b:2: z
382 382 1 a:3: a
383 383 3 b:4: b4
384 384 4 b:5: c
385 385 3 b:5: b5
386 386 7 b:7: d
387 387
388 388 $ hg annotate -nlf b
389 389 0 a:1: a (?)
390 390 1 a:2: a (?)
391 391 6 b:2: z
392 392 1 a:2: a (?)
393 393 1 a:3: a (?)
394 394 3 b:4: b4
395 395 4 b:5: c
396 396 3 b:5: b5
397 397 7 b:7: d
398 398
399 399 Issue2807: alignment of line numbers with -l
400 400 (fastannotate differs from annotate, same reason as above)
401 401
402 402 $ echo more >> b
403 403 $ hg ci -mmore -d '5 0'
404 404 $ echo more >> b
405 405 $ hg ci -mmore -d '6 0'
406 406 $ echo more >> b
407 407 $ hg ci -mmore -d '7 0'
408 408 $ hg annotate -nlf b
409 409 0 a: 1: a (?)
410 410 1 a: 2: a (?)
411 411 6 b: 2: z
412 412 1 a: 2: a (?)
413 413 1 a: 3: a (?)
414 414 3 b: 4: b4
415 415 4 b: 5: c
416 416 3 b: 5: b5
417 417 7 b: 7: d
418 418 8 b: 8: more
419 419 9 b: 9: more
420 420 10 b:10: more
421 421
422 422 linkrev vs rev
423 423
424 424 $ hg annotate -r tip -n a
425 425 0: a
426 426 1: a
427 427 1: a
428 428
429 429 linkrev vs rev with -l
430 430
431 431 $ hg annotate -r tip -nl a
432 432 0:1: a
433 433 1:2: a
434 434 1:3: a
435 435
436 436 Issue589: "undelete" sequence leads to crash
437 437
438 438 annotate was crashing when trying to --follow something
439 439
440 440 like A -> B -> A
441 441
442 442 generate ABA rename configuration
443 443
444 444 $ echo foo > foo
445 445 $ hg add foo
446 446 $ hg ci -m addfoo
447 447 $ hg rename foo bar
448 448 $ hg ci -m renamefoo
449 449 $ hg rename bar foo
450 450 $ hg ci -m renamebar
451 451
452 452 annotate after ABA with follow
453 453
454 454 $ hg annotate --follow foo
455 455 foo: foo
456 456
457 457 missing file
458 458
459 459 $ hg ann nosuchfile
460 460 abort: nosuchfile: no such file in rev e9e6b4fa872f
461 461 [255]
462 462
463 463 annotate file without '\n' on last line
464 464
465 465 $ printf "" > c
466 466 $ hg ci -A -m test -u nobody -d '1 0'
467 467 adding c
468 468 $ hg annotate c
469 469 $ printf "a\nb" > c
470 470 $ hg ci -m test
471 471 $ hg annotate c
472 472 [0-9]+: a (re)
473 473 [0-9]+: b (re)
474 474
475 475 Issue3841: check annotation of the file of which filelog includes
476 476 merging between the revision and its ancestor
477 477
478 478 to reproduce the situation with recent Mercurial, this script uses (1)
479 479 "hg debugsetparents" to merge without ancestor check by "hg merge",
480 480 and (2) the extension to allow filelog merging between the revision
481 481 and its ancestor by overriding "repo._filecommit".
482 482
483 483 $ cat > ../legacyrepo.py <<EOF
484 484 > from __future__ import absolute_import
485 485 > from mercurial import commit, error, extensions, node
486 486 > def _filecommit(orig, repo, fctx, manifest1, manifest2,
487 > linkrev, tr, includecopymeta):
487 > linkrev, tr, includecopymeta, ms):
488 488 > fname = fctx.path()
489 489 > text = fctx.data()
490 490 > flog = repo.file(fname)
491 491 > fparent1 = manifest1.get(fname, node.nullid)
492 492 > fparent2 = manifest2.get(fname, node.nullid)
493 493 > meta = {}
494 494 > copy = fctx.copysource()
495 495 > if copy and copy != fname:
496 496 > raise error.Abort('copying is not supported')
497 497 > if fparent2 != node.nullid:
498 498 > return flog.add(text, meta, tr, linkrev,
499 499 > fparent1, fparent2), 'modified'
500 500 > raise error.Abort('only merging is supported')
501 501 > def uisetup(ui):
502 502 > extensions.wrapfunction(commit, '_filecommit', _filecommit)
503 503 > EOF
504 504
505 505 $ cat > baz <<EOF
506 506 > 1
507 507 > 2
508 508 > 3
509 509 > 4
510 510 > 5
511 511 > EOF
512 512 $ hg add baz
513 513 $ hg commit -m "baz:0"
514 514
515 515 $ cat > baz <<EOF
516 516 > 1 baz:1
517 517 > 2
518 518 > 3
519 519 > 4
520 520 > 5
521 521 > EOF
522 522 $ hg commit -m "baz:1"
523 523
524 524 $ cat > baz <<EOF
525 525 > 1 baz:1
526 526 > 2 baz:2
527 527 > 3
528 528 > 4
529 529 > 5
530 530 > EOF
531 531 $ hg debugsetparents 17 17
532 532 $ hg --config extensions.legacyrepo=../legacyrepo.py commit -m "baz:2"
533 533 $ hg debugindexdot baz
534 534 digraph G {
535 535 -1 -> 0
536 536 0 -> 1
537 537 1 -> 2
538 538 1 -> 2
539 539 }
540 540 $ hg annotate baz
541 541 17: 1 baz:1
542 542 18: 2 baz:2
543 543 16: 3
544 544 16: 4
545 545 16: 5
546 546
547 547 $ cat > baz <<EOF
548 548 > 1 baz:1
549 549 > 2 baz:2
550 550 > 3 baz:3
551 551 > 4
552 552 > 5
553 553 > EOF
554 554 $ hg commit -m "baz:3"
555 555
556 556 $ cat > baz <<EOF
557 557 > 1 baz:1
558 558 > 2 baz:2
559 559 > 3 baz:3
560 560 > 4 baz:4
561 561 > 5
562 562 > EOF
563 563 $ hg debugsetparents 19 18
564 564 $ hg --config extensions.legacyrepo=../legacyrepo.py commit -m "baz:4"
565 565 $ hg debugindexdot baz
566 566 digraph G {
567 567 -1 -> 0
568 568 0 -> 1
569 569 1 -> 2
570 570 1 -> 2
571 571 2 -> 3
572 572 3 -> 4
573 573 2 -> 4
574 574 }
575 575 $ hg annotate baz
576 576 17: 1 baz:1
577 577 18: 2 baz:2
578 578 19: 3 baz:3
579 579 20: 4 baz:4
580 580 16: 5
581 581
582 582 annotate clean file
583 583
584 584 $ hg annotate -ncr "wdir()" foo
585 585 11 472b18db256d : foo
586 586
587 587 annotate modified file
588 588
589 589 $ echo foofoo >> foo
590 590 $ hg annotate -r "wdir()" foo
591 591 11 : foo
592 592 20+: foofoo
593 593
594 594 $ hg annotate -cr "wdir()" foo
595 595 472b18db256d : foo
596 596 b6bedd5477e7+: foofoo
597 597
598 598 $ hg annotate -ncr "wdir()" foo
599 599 11 472b18db256d : foo
600 600 20 b6bedd5477e7+: foofoo
601 601
602 602 $ hg annotate --debug -ncr "wdir()" foo
603 603 11 472b18db256d1e8282064eab4bfdaf48cbfe83cd : foo
604 604 20 b6bedd5477e797f25e568a6402d4697f3f895a72+: foofoo
605 605
606 606 $ hg annotate -udr "wdir()" foo
607 607 test Thu Jan 01 00:00:00 1970 +0000: foo
608 608 test [A-Za-z0-9:+ ]+: foofoo (re)
609 609
610 610 $ hg annotate -ncr "wdir()" -Tjson foo
611 611 [
612 612 {
613 613 "lines": [{"line": "foo\n", "node": "472b18db256d1e8282064eab4bfdaf48cbfe83cd", "rev": 11}, {"line": "foofoo\n", "node": "ffffffffffffffffffffffffffffffffffffffff", "rev": 2147483647}],
614 614 "path": "foo"
615 615 }
616 616 ]
617 617
618 618 annotate added file
619 619
620 620 $ echo bar > bar
621 621 $ hg add bar
622 622 $ hg annotate -ncr "wdir()" bar
623 623 20 b6bedd5477e7+: bar
624 624
625 625 annotate renamed file
626 626
627 627 $ hg rename foo renamefoo2
628 628 $ hg annotate -ncr "wdir()" renamefoo2
629 629 11 472b18db256d : foo
630 630 20 b6bedd5477e7+: foofoo
631 631
632 632 annotate missing file
633 633
634 634 $ rm baz
635 635 $ hg annotate -ncr "wdir()" baz
636 636 abort: $TESTTMP/repo/baz: $ENOENT$ (windows !)
637 637 abort: $ENOENT$: '$TESTTMP/repo/baz' (no-windows !)
638 638 [255]
639 639
640 640 annotate removed file
641 641
642 642 $ hg rm baz
643 643 $ hg annotate -ncr "wdir()" baz
644 644 abort: $TESTTMP/repo/baz: $ENOENT$ (windows !)
645 645 abort: $ENOENT$: '$TESTTMP/repo/baz' (no-windows !)
646 646 [255]
647 647
648 648 Test annotate with whitespace options
649 649
650 650 $ cd ..
651 651 $ hg init repo-ws
652 652 $ cd repo-ws
653 653 $ cat > a <<EOF
654 654 > aa
655 655 >
656 656 > b b
657 657 > EOF
658 658 $ hg ci -Am "adda"
659 659 adding a
660 660 $ sed 's/EOL$//g' > a <<EOF
661 661 > a a
662 662 >
663 663 > EOL
664 664 > b b
665 665 > EOF
666 666 $ hg ci -m "changea"
667 667
668 668 Annotate with no option
669 669
670 670 $ hg annotate a
671 671 1: a a
672 672 0:
673 673 1:
674 674 1: b b
675 675
676 676 Annotate with --ignore-space-change
677 677
678 678 $ hg annotate --ignore-space-change a
679 679 1: a a
680 680 1:
681 681 0:
682 682 0: b b
683 683
684 684 Annotate with --ignore-all-space
685 685
686 686 $ hg annotate --ignore-all-space a
687 687 0: a a
688 688 0:
689 689 1:
690 690 0: b b
691 691
692 692 Annotate with --ignore-blank-lines (similar to no options case)
693 693
694 694 $ hg annotate --ignore-blank-lines a
695 695 1: a a
696 696 0:
697 697 1:
698 698 1: b b
699 699
700 700 $ cd ..
701 701
702 702 Annotate with linkrev pointing to another branch
703 703 ------------------------------------------------
704 704
705 705 create history with a filerev whose linkrev points to another branch
706 706
707 707 $ hg init branchedlinkrev
708 708 $ cd branchedlinkrev
709 709 $ echo A > a
710 710 $ hg commit -Am 'contentA'
711 711 adding a
712 712 $ echo B >> a
713 713 $ hg commit -m 'contentB'
714 714 $ hg up --rev 'desc(contentA)'
715 715 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
716 716 $ echo unrelated > unrelated
717 717 $ hg commit -Am 'unrelated'
718 718 adding unrelated
719 719 created new head
720 720 $ hg graft -r 'desc(contentB)'
721 721 grafting 1:fd27c222e3e6 "contentB"
722 722 $ echo C >> a
723 723 $ hg commit -m 'contentC'
724 724 $ echo W >> a
725 725 $ hg log -G
726 726 @ changeset: 4:072f1e8df249
727 727 | tag: tip
728 728 | user: test
729 729 | date: Thu Jan 01 00:00:00 1970 +0000
730 730 | summary: contentC
731 731 |
732 732 o changeset: 3:ff38df03cc4b
733 733 | user: test
734 734 | date: Thu Jan 01 00:00:00 1970 +0000
735 735 | summary: contentB
736 736 |
737 737 o changeset: 2:62aaf3f6fc06
738 738 | parent: 0:f0932f74827e
739 739 | user: test
740 740 | date: Thu Jan 01 00:00:00 1970 +0000
741 741 | summary: unrelated
742 742 |
743 743 | o changeset: 1:fd27c222e3e6
744 744 |/ user: test
745 745 | date: Thu Jan 01 00:00:00 1970 +0000
746 746 | summary: contentB
747 747 |
748 748 o changeset: 0:f0932f74827e
749 749 user: test
750 750 date: Thu Jan 01 00:00:00 1970 +0000
751 751 summary: contentA
752 752
753 753
754 754 Annotate should list ancestor of starting revision only
755 755
756 756 $ hg annotate a
757 757 0: A
758 758 3: B
759 759 4: C
760 760
761 761 $ hg annotate a -r 'wdir()'
762 762 0 : A
763 763 3 : B
764 764 4 : C
765 765 4+: W
766 766
767 767 Even when the starting revision is the linkrev-shadowed one:
768 768
769 769 $ hg annotate a -r 3
770 770 0: A
771 771 3: B
772 772
773 773 $ cd ..
774 774
775 775 Issue5360: Deleted chunk in p1 of a merge changeset
776 776
777 777 $ hg init repo-5360
778 778 $ cd repo-5360
779 779 $ echo 1 > a
780 780 $ hg commit -A a -m 1
781 781 $ echo 2 >> a
782 782 $ hg commit -m 2
783 783 $ echo a > a
784 784 $ hg commit -m a
785 785 $ hg update '.^' -q
786 786 $ echo 3 >> a
787 787 $ hg commit -m 3 -q
788 788 $ hg merge 2 -q
789 789 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
790 790 [1]
791 791 $ cat a
792 792 <<<<<<< working copy: 0a068f0261cf - test: 3
793 793 1
794 794 2
795 795 3
796 796 ||||||| base
797 797 1
798 798 2
799 799 =======
800 800 a
801 801 >>>>>>> merge rev: 9409851bc20a - test: a
802 802 $ cat > a << EOF
803 803 > b
804 804 > 1
805 805 > 2
806 806 > 3
807 807 > a
808 808 > EOF
809 809 $ hg resolve --mark -q
810 810 $ rm a.orig
811 811 $ hg commit -m m
812 812 $ hg annotate a
813 813 4: b
814 814 0: 1
815 815 1: 2
816 816 3: 3
817 817 2: a
818 818
819 819 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now