Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 629:5f52074707b2
Diff/blame methods as command, their residence in HgDataFile was a mistake
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Wed, 22 May 2013 16:46:15 +0200 |
parents | 6526d8adbc0f |
children | 54e16ab771ec |
comparison
equal
deleted
inserted
replaced
628:6526d8adbc0f | 629:5f52074707b2 |
---|---|
25 import java.io.IOException; | 25 import java.io.IOException; |
26 import java.nio.ByteBuffer; | 26 import java.nio.ByteBuffer; |
27 import java.nio.channels.FileChannel; | 27 import java.nio.channels.FileChannel; |
28 import java.util.Arrays; | 28 import java.util.Arrays; |
29 | 29 |
30 import org.tmatesoft.hg.core.HgBlameInspector; | |
30 import org.tmatesoft.hg.core.HgCallbackTargetException; | 31 import org.tmatesoft.hg.core.HgCallbackTargetException; |
31 import org.tmatesoft.hg.core.HgChangesetFileSneaker; | 32 import org.tmatesoft.hg.core.HgChangesetFileSneaker; |
33 import org.tmatesoft.hg.core.HgDiffCommand; | |
34 import org.tmatesoft.hg.core.HgException; | |
32 import org.tmatesoft.hg.core.HgIterateDirection; | 35 import org.tmatesoft.hg.core.HgIterateDirection; |
36 import org.tmatesoft.hg.core.HgLibraryFailureException; | |
33 import org.tmatesoft.hg.core.Nodeid; | 37 import org.tmatesoft.hg.core.Nodeid; |
34 import org.tmatesoft.hg.internal.BlameHelper; | |
35 import org.tmatesoft.hg.internal.DataAccess; | 38 import org.tmatesoft.hg.internal.DataAccess; |
36 import org.tmatesoft.hg.internal.FileHistory; | |
37 import org.tmatesoft.hg.internal.FileRevisionHistoryChunk; | |
38 import org.tmatesoft.hg.internal.FileUtils; | 39 import org.tmatesoft.hg.internal.FileUtils; |
39 import org.tmatesoft.hg.internal.FilterByteChannel; | 40 import org.tmatesoft.hg.internal.FilterByteChannel; |
40 import org.tmatesoft.hg.internal.FilterDataAccess; | 41 import org.tmatesoft.hg.internal.FilterDataAccess; |
41 import org.tmatesoft.hg.internal.Internals; | 42 import org.tmatesoft.hg.internal.Internals; |
42 import org.tmatesoft.hg.internal.Metadata; | 43 import org.tmatesoft.hg.internal.Metadata; |
424 */ | 425 */ |
425 public HgManifest.Flags getFlags(int fileRevisionIndex) throws HgRuntimeException { | 426 public HgManifest.Flags getFlags(int fileRevisionIndex) throws HgRuntimeException { |
426 int changesetRevIndex = getChangesetRevisionIndex(fileRevisionIndex); | 427 int changesetRevIndex = getChangesetRevisionIndex(fileRevisionIndex); |
427 return getRepo().getManifest().getFileFlags(changesetRevIndex, getPath()); | 428 return getRepo().getManifest().getFileFlags(changesetRevIndex, getPath()); |
428 } | 429 } |
429 | 430 |
430 /** | 431 /** |
431 * mimic 'hg diff -r clogRevIndex1 -r clogRevIndex2' | 432 * @deprecated use {@link HgDiffCommand} instead |
432 */ | 433 */ |
434 @Deprecated | |
433 public void diff(int clogRevIndex1, int clogRevIndex2, HgBlameInspector insp) throws HgRuntimeException, HgCallbackTargetException { | 435 public void diff(int clogRevIndex1, int clogRevIndex2, HgBlameInspector insp) throws HgRuntimeException, HgCallbackTargetException { |
434 int fileRevIndex1 = fileRevIndex(this, clogRevIndex1); | 436 try { |
435 int fileRevIndex2 = fileRevIndex(this, clogRevIndex2); | 437 new HgDiffCommand(getRepo()).file(this).range(clogRevIndex1, clogRevIndex2).executeDiff(insp); |
436 BlameHelper bh = new BlameHelper(insp); | 438 } catch (HgLibraryFailureException ex) { |
437 bh.prepare(this, clogRevIndex1, clogRevIndex2); | 439 throw ex.getCause(); |
438 bh.diff(fileRevIndex1, clogRevIndex1, fileRevIndex2, clogRevIndex2); | 440 } catch (HgException ex) { |
439 } | 441 throw new HgInvalidStateException(ex.getMessage()); |
440 | 442 } catch (CancelledException ex) { |
441 /** | 443 throw new HgInvalidStateException("Cancellatin is not expected"); |
442 * Walk file history up/down to revision at given changeset and report changes for each revision | 444 } |
443 */ | 445 } |
444 public void annotate(int changelogRevisionIndex, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgRuntimeException, HgCallbackTargetException { | 446 |
445 annotate(0, changelogRevisionIndex, insp, iterateOrder); | 447 /** |
446 } | 448 * @deprecated use {@link HgDiffCommand} instead |
447 | 449 */ |
448 /** | 450 @Deprecated |
449 * Walk file history range and report changes for each revision | 451 public void annotate(int clogRevIndex1, int clogRevIndex2, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgRuntimeException, HgCallbackTargetException { |
450 */ | 452 try { |
451 public void annotate(int changelogRevIndexStart, int changelogRevIndexEnd, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgRuntimeException, HgCallbackTargetException { | 453 new HgDiffCommand(getRepo()).file(this).range(clogRevIndex1, clogRevIndex2).order(iterateOrder).executeAnnotate(insp); |
452 if (wrongRevisionIndex(changelogRevIndexStart) || wrongRevisionIndex(changelogRevIndexEnd)) { | 454 } catch (HgLibraryFailureException ex) { |
453 throw new IllegalArgumentException(); | 455 throw ex.getCause(); |
454 } | 456 } catch (HgException ex) { |
455 // Note, changelogRevIndexEnd may be TIP, while the code below doesn't tolerate constants | 457 throw new HgInvalidStateException(ex.getMessage()); |
456 // | 458 } catch (CancelledException ex) { |
457 int lastRevision = getRepo().getChangelog().getLastRevision(); | 459 throw new HgInvalidStateException("Cancellatin is not expected"); |
458 if (changelogRevIndexEnd == TIP) { | 460 } |
459 changelogRevIndexEnd = lastRevision; | 461 } |
460 } | 462 |
461 HgInternals.checkRevlogRange(changelogRevIndexStart, changelogRevIndexEnd, lastRevision); | 463 /** |
462 if (!exists()) { | 464 * @deprecated use {@link HgDiffCommand} instead |
463 return; | 465 */ |
464 } | 466 @Deprecated |
465 BlameHelper bh = new BlameHelper(insp); | |
466 FileHistory fileHistory = bh.prepare(this, changelogRevIndexStart, changelogRevIndexEnd); | |
467 | |
468 int[] fileClogParentRevs = new int[2]; | |
469 int[] fileParentRevs = new int[2]; | |
470 for (FileRevisionHistoryChunk fhc : fileHistory.iterate(iterateOrder)) { | |
471 for (int fri : fhc.fileRevisions(iterateOrder)) { | |
472 int clogRevIndex = fhc.changeset(fri); | |
473 // the way we built fileHistory ensures we won't walk past [changelogRevIndexStart..changelogRevIndexEnd] | |
474 assert clogRevIndex >= changelogRevIndexStart; | |
475 assert clogRevIndex <= changelogRevIndexEnd; | |
476 fhc.fillFileParents(fri, fileParentRevs); | |
477 fhc.fillCsetParents(fri, fileClogParentRevs); | |
478 bh.annotateChange(fri, clogRevIndex, fileParentRevs, fileClogParentRevs); | |
479 } | |
480 } | |
481 } | |
482 | |
483 /** | |
484 * Annotates changes of the file against its parent(s). | |
485 * Unlike {@link #annotate(HgDataFile, int, Inspector, HgIterateDirection)}, doesn't | |
486 * walk file history, looks at the specified revision only. Handles both parents (if merge revision). | |
487 */ | |
488 public void annotateSingleRevision(int changelogRevisionIndex, HgBlameInspector insp) throws HgRuntimeException, HgCallbackTargetException { | 467 public void annotateSingleRevision(int changelogRevisionIndex, HgBlameInspector insp) throws HgRuntimeException, HgCallbackTargetException { |
489 // TODO detect if file is text/binary (e.g. looking for chars < ' ' and not \t\r\n\f | 468 try { |
490 int fileRevIndex = fileRevIndex(this, changelogRevisionIndex); | 469 new HgDiffCommand(getRepo()).file(this).changeset(changelogRevisionIndex).executeAnnotateSingleRevision(insp); |
491 int[] fileRevParents = new int[2]; | 470 } catch (HgLibraryFailureException ex) { |
492 parents(fileRevIndex, fileRevParents, null, null); | 471 throw ex.getCause(); |
493 if (changelogRevisionIndex == TIP) { | 472 } catch (HgException ex) { |
494 changelogRevisionIndex = getChangesetRevisionIndex(fileRevIndex); | 473 throw new HgInvalidStateException(ex.getMessage()); |
495 } | 474 } catch (CancelledException ex) { |
496 int[] fileClogParentRevs = new int[2]; | 475 throw new HgInvalidStateException("Cancellatin is not expected"); |
497 fileClogParentRevs[0] = fileRevParents[0] == NO_REVISION ? NO_REVISION : getChangesetRevisionIndex(fileRevParents[0]); | 476 } |
498 fileClogParentRevs[1] = fileRevParents[1] == NO_REVISION ? NO_REVISION : getChangesetRevisionIndex(fileRevParents[1]); | |
499 BlameHelper bh = new BlameHelper(insp); | |
500 int clogIndexStart = fileClogParentRevs[0] == NO_REVISION ? (fileClogParentRevs[1] == NO_REVISION ? 0 : fileClogParentRevs[1]) : fileClogParentRevs[0]; | |
501 bh.prepare(this, clogIndexStart, changelogRevisionIndex); | |
502 bh.annotateChange(fileRevIndex, changelogRevisionIndex, fileRevParents, fileClogParentRevs); | |
503 } | 477 } |
504 | 478 |
505 @Override | 479 @Override |
506 public String toString() { | 480 public String toString() { |
507 StringBuilder sb = new StringBuilder(getClass().getSimpleName()); | 481 StringBuilder sb = new StringBuilder(getClass().getSimpleName()); |
517 } | 491 } |
518 // use MetadataInspector without delegate to process metadata only | 492 // use MetadataInspector without delegate to process metadata only |
519 RevlogStream.Inspector insp = new MetadataInspector(metadata, null); | 493 RevlogStream.Inspector insp = new MetadataInspector(metadata, null); |
520 super.content.iterate(localRev, localRev, true, insp); | 494 super.content.iterate(localRev, localRev, true, insp); |
521 } | 495 } |
522 | |
523 | |
524 private static int fileRevIndex(HgDataFile df, int csetRevIndex) throws HgRuntimeException { | |
525 Nodeid fileRev = df.getRepo().getManifest().getFileRevision(csetRevIndex, df.getPath()); | |
526 return df.getRevisionIndex(fileRev); | |
527 } | |
528 | |
529 | 496 |
530 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { | 497 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { |
531 private final Metadata metadata; | 498 private final Metadata metadata; |
532 private final RevlogStream.Inspector delegate; | 499 private final RevlogStream.Inspector delegate; |
533 | 500 |