Mercurial > hg4j
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 688:1499139a600a | 689:5050ee565bd1 |
|---|---|
| 24 import java.util.LinkedList; | 24 import java.util.LinkedList; |
| 25 import java.util.List; | 25 import java.util.List; |
| 26 import java.util.Map; | 26 import java.util.Map; |
| 27 import java.util.TreeSet; | 27 import java.util.TreeSet; |
| 28 | 28 |
| 29 import org.tmatesoft.hg.core.HgFileRevision; | |
| 29 import org.tmatesoft.hg.core.Nodeid; | 30 import org.tmatesoft.hg.core.Nodeid; |
| 30 import org.tmatesoft.hg.internal.IntMap; | 31 import org.tmatesoft.hg.internal.IntMap; |
| 31 import org.tmatesoft.hg.internal.ManifestRevision; | 32 import org.tmatesoft.hg.internal.ManifestRevision; |
| 32 import org.tmatesoft.hg.internal.Pool; | 33 import org.tmatesoft.hg.internal.Pool; |
| 33 import org.tmatesoft.hg.util.CancelSupport; | 34 import org.tmatesoft.hg.util.CancelSupport; |
| 314 } | 315 } |
| 315 cs.checkCancelled(); | 316 cs.checkCancelled(); |
| 316 } else { | 317 } else { |
| 317 try { | 318 try { |
| 318 Path copyTarget = r2fname; | 319 Path copyTarget = r2fname; |
| 319 Path copyOrigin = detectCopies ? getOriginIfCopy(repo, copyTarget, r1Files, rev1) : null; | 320 Path copyOrigin = detectCopies ? getOriginIfCopy(repo, copyTarget, r2.nodeid(copyTarget), r1Files, rev1) : null; |
| 320 if (copyOrigin != null) { | 321 if (copyOrigin != null) { |
| 321 inspector.copied(getPathPool().mangle(copyOrigin) /*pipe through pool, just in case*/, copyTarget); | 322 inspector.copied(getPathPool().mangle(copyOrigin) /*pipe through pool, just in case*/, copyTarget); |
| 322 } else { | 323 } else { |
| 323 inspector.added(copyTarget); | 324 inspector.added(copyTarget); |
| 324 } | 325 } |
| 359 throw t; | 360 throw t; |
| 360 } | 361 } |
| 361 return rv; | 362 return rv; |
| 362 } | 363 } |
| 363 | 364 |
| 364 /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Collection<Path> originals, int originalChangelogRevision) throws HgRuntimeException { | 365 /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Nodeid fnameRev, Collection<Path> originals, int originalChangesetIndex) throws HgRuntimeException { |
| 365 HgDataFile df = hgRepo.getFileNode(fname); | 366 HgDataFile df = hgRepo.getFileNode(fname); |
| 366 if (!df.exists()) { | 367 if (!df.exists()) { |
| 367 String msg = String.format("Didn't find file '%s' in the repo. Perhaps, bad storage name conversion?", fname); | 368 String msg = String.format("Didn't find file '%s' in the repo. Perhaps, bad storage name conversion?", fname); |
| 368 throw new HgInvalidFileException(msg, null).setFileName(fname).setRevisionIndex(originalChangelogRevision); | 369 throw new HgInvalidFileException(msg, null).setFileName(fname).setRevisionIndex(originalChangesetIndex); |
| 369 } | 370 } |
| 370 while (df.isCopy()) { | 371 assert fnameRev != null; |
| 371 Path original = df.getCopySourceName(); | 372 assert !Nodeid.NULL.equals(fnameRev); |
| 372 if (originals.contains(original)) { | 373 int fileRevIndex = fnameRev == null ? 0 : df.getRevisionIndex(fnameRev); |
| 373 df = hgRepo.getFileNode(original); | 374 Path lastOriginFound = null; |
| 374 int changelogRevision = df.getChangesetRevisionIndex(0); | 375 while(fileRevIndex >=0) { |
| 375 if (changelogRevision <= originalChangelogRevision) { | 376 if (!df.isCopy(fileRevIndex)) { |
| 377 fileRevIndex--; | |
| 378 continue; | |
| 379 } | |
| 380 int csetRevIndex = df.getChangesetRevisionIndex(fileRevIndex); | |
| 381 if (csetRevIndex <= originalChangesetIndex) { | |
| 382 // we've walked past originalChangelogRevIndex and no chances we'll find origin | |
| 383 // if we get here, it means fname's origin is not from the base revision | |
| 384 return null; | |
| 385 } | |
| 386 HgFileRevision origin = df.getCopySource(fileRevIndex); | |
| 387 // prepare for the next step, df(copyFromFileRev) would point to copy origin and its revision | |
| 388 df = hgRepo.getFileNode(origin.getPath()); | |
| 389 int copyFromFileRevIndex = df.getRevisionIndex(origin.getRevision()); | |
| 390 if (originals.contains(origin.getPath())) { | |
| 391 int copyFromCsetIndex = df.getChangesetRevisionIndex(copyFromFileRevIndex); | |
| 392 if (copyFromCsetIndex <= originalChangesetIndex) { | |
| 376 // copy/rename source was known prior to rev1 | 393 // copy/rename source was known prior to rev1 |
| 377 // (both r1Files.contains is true and original was created earlier than rev1) | 394 // (both r1Files.contains is true and original was created earlier than rev1) |
| 378 // without r1Files.contains changelogRevision <= rev1 won't suffice as the file | 395 // without r1Files.contains changelogRevision <= rev1 won't suffice as the file |
| 379 // might get removed somewhere in between (changelogRevision < R < rev1) | 396 // might get removed somewhere in between (changelogRevision < R < rev1) |
| 380 return original; | 397 return origin.getPath(); |
| 381 } | 398 } |
| 382 break; // copy/rename done later | 399 // copy/rename happened in [copyFromCsetIndex..target], let's see if |
| 383 } | 400 // origin wasn't renamed once more in [originalChangesetIndex..copyFromCsetIndex] |
| 384 df = hgRepo.getFileNode(original); // try more steps away | 401 lastOriginFound = origin.getPath(); |
| 385 } | 402 // FALL-THROUGH |
| 386 return null; | 403 } |
| 404 // try more steps away | |
| 405 // copyFromFileRev or one of its predecessors might be copies as well | |
| 406 fileRevIndex = copyFromFileRevIndex; // df is already origin file | |
| 407 } | |
| 408 return lastOriginFound; | |
| 387 } | 409 } |
| 388 | 410 |
| 389 // XXX for r1..r2 status, only modified, added, removed (and perhaps, clean) make sense | 411 // XXX for r1..r2 status, only modified, added, removed (and perhaps, clean) make sense |
| 390 // XXX Need to specify whether copy targets are in added or not (@see Inspector#copied above) | 412 // XXX Need to specify whether copy targets are in added or not (@see Inspector#copied above) |
| 391 /** | 413 /** |
