Mercurial > jhg
diff src/org/tmatesoft/hg/repo/HgStatusCollector.java @ 689:5050ee565bd1
Issue 44: Renames/copies other than for the very first revision of a file are not recognized
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Sat, 27 Jul 2013 22:06:14 +0200 |
parents | 6526d8adbc0f |
children | b286222158be |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgStatusCollector.java Sat Jul 27 20:15:37 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgStatusCollector.java Sat Jul 27 22:06:14 2013 +0200 @@ -26,6 +26,7 @@ import java.util.Map; import java.util.TreeSet; +import org.tmatesoft.hg.core.HgFileRevision; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.IntMap; import org.tmatesoft.hg.internal.ManifestRevision; @@ -316,7 +317,7 @@ } else { try { Path copyTarget = r2fname; - Path copyOrigin = detectCopies ? getOriginIfCopy(repo, copyTarget, r1Files, rev1) : null; + Path copyOrigin = detectCopies ? getOriginIfCopy(repo, copyTarget, r2.nodeid(copyTarget), r1Files, rev1) : null; if (copyOrigin != null) { inspector.copied(getPathPool().mangle(copyOrigin) /*pipe through pool, just in case*/, copyTarget); } else { @@ -361,29 +362,50 @@ return rv; } - /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Collection<Path> originals, int originalChangelogRevision) throws HgRuntimeException { + /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Nodeid fnameRev, Collection<Path> originals, int originalChangesetIndex) throws HgRuntimeException { HgDataFile df = hgRepo.getFileNode(fname); if (!df.exists()) { String msg = String.format("Didn't find file '%s' in the repo. Perhaps, bad storage name conversion?", fname); - throw new HgInvalidFileException(msg, null).setFileName(fname).setRevisionIndex(originalChangelogRevision); + throw new HgInvalidFileException(msg, null).setFileName(fname).setRevisionIndex(originalChangesetIndex); } - while (df.isCopy()) { - Path original = df.getCopySourceName(); - if (originals.contains(original)) { - df = hgRepo.getFileNode(original); - int changelogRevision = df.getChangesetRevisionIndex(0); - if (changelogRevision <= originalChangelogRevision) { + assert fnameRev != null; + assert !Nodeid.NULL.equals(fnameRev); + int fileRevIndex = fnameRev == null ? 0 : df.getRevisionIndex(fnameRev); + Path lastOriginFound = null; + while(fileRevIndex >=0) { + if (!df.isCopy(fileRevIndex)) { + fileRevIndex--; + continue; + } + int csetRevIndex = df.getChangesetRevisionIndex(fileRevIndex); + if (csetRevIndex <= originalChangesetIndex) { + // we've walked past originalChangelogRevIndex and no chances we'll find origin + // if we get here, it means fname's origin is not from the base revision + return null; + } + HgFileRevision origin = df.getCopySource(fileRevIndex); + // prepare for the next step, df(copyFromFileRev) would point to copy origin and its revision + df = hgRepo.getFileNode(origin.getPath()); + int copyFromFileRevIndex = df.getRevisionIndex(origin.getRevision()); + if (originals.contains(origin.getPath())) { + int copyFromCsetIndex = df.getChangesetRevisionIndex(copyFromFileRevIndex); + if (copyFromCsetIndex <= originalChangesetIndex) { // copy/rename source was known prior to rev1 // (both r1Files.contains is true and original was created earlier than rev1) // without r1Files.contains changelogRevision <= rev1 won't suffice as the file // might get removed somewhere in between (changelogRevision < R < rev1) - return original; + return origin.getPath(); } - break; // copy/rename done later - } - df = hgRepo.getFileNode(original); // try more steps away + // copy/rename happened in [copyFromCsetIndex..target], let's see if + // origin wasn't renamed once more in [originalChangesetIndex..copyFromCsetIndex] + lastOriginFound = origin.getPath(); + // FALL-THROUGH + } + // try more steps away + // copyFromFileRev or one of its predecessors might be copies as well + fileRevIndex = copyFromFileRevIndex; // df is already origin file } - return null; + return lastOriginFound; } // XXX for r1..r2 status, only modified, added, removed (and perhaps, clean) make sense