Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgStatusCollector.java @ 691:72fc7774b87e
Fix file.isCopy() for blame/annotate. Refactor status and blame to use newly introduced FileHistory helper that builds file rename history
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Fri, 02 Aug 2013 23:07:23 +0200 |
| parents | b286222158be |
| children | 7efabe0cddcf |
comparison
equal
deleted
inserted
replaced
| 690:b286222158be | 691:72fc7774b87e |
|---|---|
| 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; | |
| 30 import org.tmatesoft.hg.core.Nodeid; | 29 import org.tmatesoft.hg.core.Nodeid; |
| 30 import org.tmatesoft.hg.internal.FileRenameHistory; | |
| 31 import org.tmatesoft.hg.internal.FileRenameHistory.Chunk; | |
| 31 import org.tmatesoft.hg.internal.IntMap; | 32 import org.tmatesoft.hg.internal.IntMap; |
| 32 import org.tmatesoft.hg.internal.ManifestRevision; | 33 import org.tmatesoft.hg.internal.ManifestRevision; |
| 33 import org.tmatesoft.hg.internal.Pool; | 34 import org.tmatesoft.hg.internal.Pool; |
| 34 import org.tmatesoft.hg.util.CancelSupport; | 35 import org.tmatesoft.hg.util.CancelSupport; |
| 35 import org.tmatesoft.hg.util.CancelledException; | 36 import org.tmatesoft.hg.util.CancelledException; |
| 374 throw new HgInvalidFileException(msg, null).setFileName(fname).setRevisionIndex(originalChangesetIndex); | 375 throw new HgInvalidFileException(msg, null).setFileName(fname).setRevisionIndex(originalChangesetIndex); |
| 375 } | 376 } |
| 376 assert fnameRev != null; | 377 assert fnameRev != null; |
| 377 assert !Nodeid.NULL.equals(fnameRev); | 378 assert !Nodeid.NULL.equals(fnameRev); |
| 378 int fileRevIndex = fnameRev == null ? 0 : df.getRevisionIndex(fnameRev); | 379 int fileRevIndex = fnameRev == null ? 0 : df.getRevisionIndex(fnameRev); |
| 379 Path lastOriginFound = null; | 380 FileRenameHistory frh = new FileRenameHistory(originalChangesetIndex, df.getChangesetRevisionIndex(fileRevIndex)); |
| 380 while(fileRevIndex >=0) { | 381 if (frh.isOutOfRange(df, fileRevIndex)) { |
| 381 if (!df.isCopy(fileRevIndex)) { | 382 return null; |
| 382 fileRevIndex--; | 383 } |
| 383 continue; | 384 frh.build(df, fileRevIndex); |
| 384 } | 385 Chunk c = frh.chunkAt(originalChangesetIndex); |
| 385 int csetRevIndex = df.getChangesetRevisionIndex(fileRevIndex); | 386 if (c == null) { |
| 386 if (csetRevIndex <= originalChangesetIndex) { | 387 // file rename history doesn't go deep up to changeset of interest |
| 387 // we've walked past originalChangelogRevIndex and no chances we'll find origin | 388 return null; |
| 388 // if we get here, it means either fname's origin is not from the base revision | 389 } |
| 389 // or the last found rename is still valid | 390 Path nameAtOrigin = c.file().getPath(); |
| 390 return lastOriginFound; | 391 if (originals.contains(nameAtOrigin)) { |
| 391 } | 392 return nameAtOrigin; |
| 392 HgFileRevision origin = df.getCopySource(fileRevIndex); | 393 } |
| 393 // prepare for the next step, df(copyFromFileRev) would point to copy origin and its revision | 394 return null; |
| 394 df = hgRepo.getFileNode(origin.getPath()); | |
| 395 int copyFromFileRevIndex = df.getRevisionIndex(origin.getRevision()); | |
| 396 if (originals.contains(origin.getPath())) { | |
| 397 int copyFromCsetIndex = df.getChangesetRevisionIndex(copyFromFileRevIndex); | |
| 398 if (copyFromCsetIndex <= originalChangesetIndex) { | |
| 399 // copy/rename source was known prior to rev1 | |
| 400 // (both r1Files.contains is true and original was created earlier than rev1) | |
| 401 // without r1Files.contains changelogRevision <= rev1 won't suffice as the file | |
| 402 // might get removed somewhere in between (changelogRevision < R < rev1) | |
| 403 return origin.getPath(); | |
| 404 } | |
| 405 // copy/rename happened in [copyFromCsetIndex..target], let's see if | |
| 406 // origin wasn't renamed once more in [originalChangesetIndex..copyFromCsetIndex] | |
| 407 lastOriginFound = origin.getPath(); | |
| 408 // FALL-THROUGH | |
| 409 } else { | |
| 410 // clear last known origin if the file was renamed once again to something we don't have in base | |
| 411 lastOriginFound = null; | |
| 412 } | |
| 413 // try more steps away | |
| 414 // copyFromFileRev or one of its predecessors might be copies as well | |
| 415 fileRevIndex = copyFromFileRevIndex; // df is already origin file | |
| 416 } | |
| 417 return lastOriginFound; | |
| 418 } | 395 } |
| 419 | 396 |
| 420 // XXX for r1..r2 status, only modified, added, removed (and perhaps, clean) make sense | 397 // XXX for r1..r2 status, only modified, added, removed (and perhaps, clean) make sense |
| 421 // XXX Need to specify whether copy targets are in added or not (@see Inspector#copied above) | 398 // XXX Need to specify whether copy targets are in added or not (@see Inspector#copied above) |
| 422 /** | 399 /** |
