copies: follow copies across merge base without source file (issue6163)
As in the previous patch, consider these two histories:
@ 4 'rename x to y'
|
o 3 'add x again'
|
o 2 'remove x'
|
| o 1 'modify x'
|/
o 0 'add x'
@ 4 'rename x to y'
|
o 3 'add x again'
|
| o 2 'modify x'
| |
| o 1 'add x'
|/
o 0 'base'
We trace copies from the 'modify x' commit to commit 4 by going via
the merge base (commit 0). When tracing file 'y' (_tracefile()) in the
first case, we immediately find the rename from 'x'. We check to see
if 'x' exists in the merge base, which it does, so we consider it a
valid copy. In the second case, 'x' does not exist in the merge base,
so it's not considered a valid copy. As a workaround, this patch makes
it so we also attempt the check in mergecopies's base commit (commit 1
in the second case). That feels pretty ugly to me, but I don't have
any better ideas.
Note that we actually also check not only that the filename matches,
but also that the file's nodeid matches. I don't know why we do that,
but it was like that already before I rewrote mergecopies(). That
means that the rebase will still fail in cases like this (again, it
already failed before my rewrite):
@ 4 'rename x to y'
|
o 3 'add x again with content X2'
|
o 2 'remove x'
|
| o 1 'modify x to content X2'
|/
o 1 'modify x to content X1'
|
o 0 'add x with content X0'
Differential Revision: https://phab.mercurial-scm.org/D6604
#!/usr/bin/env python
from __future__ import absolute_import
__doc__ = """Same as `echo a >> b`, but ensures a changed mtime of b.
Without this svn will not detect workspace changes."""
import os
import stat
import sys
if sys.version_info[0] >= 3:
text = os.fsencode(sys.argv[1])
fname = os.fsencode(sys.argv[2])
else:
text = sys.argv[1]
fname = sys.argv[2]
f = open(fname, "ab")
try:
before = os.fstat(f.fileno())[stat.ST_MTIME]
f.write(text)
f.write(b"\n")
finally:
f.close()
inc = 1
now = os.stat(fname)[stat.ST_MTIME]
while now == before:
t = now + inc
inc += 1
os.utime(fname, (t, t))
now = os.stat(fname)[stat.ST_MTIME]