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