Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 603:707b5c7c6fa4
Refactor HgBlameFacility: relevant action methods moved to proper home (HgDataFile), as facility doesn't provide anything but packaging of relevant methods/interfaces
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Mon, 06 May 2013 18:29:57 +0200 |
| parents | e3717fc7d26f |
| children | e1b29756f901 |
comparison
equal
deleted
inserted
replaced
| 602:e3717fc7d26f | 603:707b5c7c6fa4 |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2010-2012 TMate Software Ltd | 2 * Copyright (c) 2010-2013 TMate Software Ltd |
| 3 * | 3 * |
| 4 * This program is free software; you can redistribute it and/or modify | 4 * This program is free software; you can redistribute it and/or modify |
| 5 * it under the terms of the GNU General Public License as published by | 5 * it under the terms of the GNU General Public License as published by |
| 6 * the Free Software Foundation; version 2 of the License. | 6 * the Free Software Foundation; version 2 of the License. |
| 7 * | 7 * |
| 14 * the terms of a license other than GNU General Public License | 14 * the terms of a license other than GNU General Public License |
| 15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
| 16 */ | 16 */ |
| 17 package org.tmatesoft.hg.repo; | 17 package org.tmatesoft.hg.repo; |
| 18 | 18 |
| 19 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew; | |
| 19 import static org.tmatesoft.hg.repo.HgInternals.wrongRevisionIndex; | 20 import static org.tmatesoft.hg.repo.HgInternals.wrongRevisionIndex; |
| 20 import static org.tmatesoft.hg.repo.HgRepository.*; | 21 import static org.tmatesoft.hg.repo.HgRepository.*; |
| 21 import static org.tmatesoft.hg.util.LogFacility.Severity.Info; | 22 import static org.tmatesoft.hg.util.LogFacility.Severity.Info; |
| 22 import static org.tmatesoft.hg.util.LogFacility.Severity.Warn; | 23 import static org.tmatesoft.hg.util.LogFacility.Severity.Warn; |
| 23 | 24 |
| 26 import java.io.IOException; | 27 import java.io.IOException; |
| 27 import java.nio.ByteBuffer; | 28 import java.nio.ByteBuffer; |
| 28 import java.nio.channels.FileChannel; | 29 import java.nio.channels.FileChannel; |
| 29 import java.util.Arrays; | 30 import java.util.Arrays; |
| 30 | 31 |
| 32 import org.tmatesoft.hg.core.HgCallbackTargetException; | |
| 31 import org.tmatesoft.hg.core.HgChangesetFileSneaker; | 33 import org.tmatesoft.hg.core.HgChangesetFileSneaker; |
| 34 import org.tmatesoft.hg.core.HgIterateDirection; | |
| 32 import org.tmatesoft.hg.core.Nodeid; | 35 import org.tmatesoft.hg.core.Nodeid; |
| 36 import org.tmatesoft.hg.internal.BlameHelper; | |
| 33 import org.tmatesoft.hg.internal.DataAccess; | 37 import org.tmatesoft.hg.internal.DataAccess; |
| 38 import org.tmatesoft.hg.internal.FileHistory; | |
| 39 import org.tmatesoft.hg.internal.FileRevisionHistoryChunk; | |
| 34 import org.tmatesoft.hg.internal.FilterByteChannel; | 40 import org.tmatesoft.hg.internal.FilterByteChannel; |
| 35 import org.tmatesoft.hg.internal.FilterDataAccess; | 41 import org.tmatesoft.hg.internal.FilterDataAccess; |
| 36 import org.tmatesoft.hg.internal.Internals; | 42 import org.tmatesoft.hg.internal.Internals; |
| 37 import org.tmatesoft.hg.internal.Metadata; | 43 import org.tmatesoft.hg.internal.Metadata; |
| 38 import org.tmatesoft.hg.internal.RevlogStream; | 44 import org.tmatesoft.hg.internal.RevlogStream; |
| 45 import org.tmatesoft.hg.repo.HgBlameInspector; | |
| 39 import org.tmatesoft.hg.util.ByteChannel; | 46 import org.tmatesoft.hg.util.ByteChannel; |
| 40 import org.tmatesoft.hg.util.CancelSupport; | 47 import org.tmatesoft.hg.util.CancelSupport; |
| 41 import org.tmatesoft.hg.util.CancelledException; | 48 import org.tmatesoft.hg.util.CancelledException; |
| 42 import org.tmatesoft.hg.util.LogFacility; | 49 import org.tmatesoft.hg.util.LogFacility; |
| 43 import org.tmatesoft.hg.util.Pair; | 50 import org.tmatesoft.hg.util.Pair; |
| 426 public HgManifest.Flags getFlags(int fileRevisionIndex) throws HgRuntimeException { | 433 public HgManifest.Flags getFlags(int fileRevisionIndex) throws HgRuntimeException { |
| 427 int changesetRevIndex = getChangesetRevisionIndex(fileRevisionIndex); | 434 int changesetRevIndex = getChangesetRevisionIndex(fileRevisionIndex); |
| 428 return getRepo().getManifest().getFileFlags(changesetRevIndex, getPath()); | 435 return getRepo().getManifest().getFileFlags(changesetRevIndex, getPath()); |
| 429 } | 436 } |
| 430 | 437 |
| 438 /** | |
| 439 * mimic 'hg diff -r clogRevIndex1 -r clogRevIndex2' | |
| 440 */ | |
| 441 public void diff(int clogRevIndex1, int clogRevIndex2, HgBlameInspector insp) throws HgCallbackTargetException { | |
| 442 // FIXME clogRevIndex1 and clogRevIndex2 may point to different files, need to decide whether to throw an exception | |
| 443 // or to attempt to look up correct file node (tricky) | |
| 444 int fileRevIndex1 = fileRevIndex(this, clogRevIndex1); | |
| 445 int fileRevIndex2 = fileRevIndex(this, clogRevIndex2); | |
| 446 BlameHelper bh = new BlameHelper(insp, 5); | |
| 447 bh.useFileUpTo(this, clogRevIndex2); | |
| 448 bh.diff(fileRevIndex1, clogRevIndex1, fileRevIndex2, clogRevIndex2); | |
| 449 } | |
| 450 | |
| 451 /** | |
| 452 * Walk file history up/down to revision at given changeset and report changes for each revision | |
| 453 */ | |
| 454 public void annotate(int changelogRevisionIndex, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgCallbackTargetException { | |
| 455 annotate(0, changelogRevisionIndex, insp, iterateOrder); | |
| 456 } | |
| 457 | |
| 458 /** | |
| 459 * Walk file history range and report changes for each revision | |
| 460 */ | |
| 461 public void annotate(int changelogRevIndexStart, int changelogRevIndexEnd, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgCallbackTargetException { | |
| 462 if (wrongRevisionIndex(changelogRevIndexStart) || wrongRevisionIndex(changelogRevIndexEnd)) { | |
| 463 throw new IllegalArgumentException(); | |
| 464 } | |
| 465 // Note, changelogRevIndexEnd may be TIP, while the code below doesn't tolerate constants | |
| 466 // | |
| 467 int lastRevision = getRepo().getChangelog().getLastRevision(); | |
| 468 if (changelogRevIndexEnd == TIP) { | |
| 469 changelogRevIndexEnd = lastRevision; | |
| 470 } | |
| 471 HgInternals.checkRevlogRange(changelogRevIndexStart, changelogRevIndexEnd, lastRevision); | |
| 472 if (!exists()) { | |
| 473 return; | |
| 474 } | |
| 475 FileHistory fileHistory = new FileHistory(this, changelogRevIndexStart, changelogRevIndexEnd); | |
| 476 fileHistory.build(); | |
| 477 BlameHelper bh = new BlameHelper(insp, 10); | |
| 478 for (FileRevisionHistoryChunk fhc : fileHistory.iterate(OldToNew)) { | |
| 479 // iteration order is not important here | |
| 480 bh.useFileUpTo(fhc.getFile(), fhc.getEndChangeset()); | |
| 481 } | |
| 482 int[] fileClogParentRevs = new int[2]; | |
| 483 int[] fileParentRevs = new int[2]; | |
| 484 for (FileRevisionHistoryChunk fhc : fileHistory.iterate(iterateOrder)) { | |
| 485 for (int fri : fhc.fileRevisions(iterateOrder)) { | |
| 486 int clogRevIndex = fhc.changeset(fri); | |
| 487 // the way we built fileHistory ensures we won't walk past [changelogRevIndexStart..changelogRevIndexEnd] | |
| 488 assert clogRevIndex >= changelogRevIndexStart; | |
| 489 assert clogRevIndex <= changelogRevIndexEnd; | |
| 490 fhc.fillFileParents(fri, fileParentRevs); | |
| 491 fhc.fillCsetParents(fri, fileClogParentRevs); | |
| 492 bh.annotateChange(fri, clogRevIndex, fileParentRevs, fileClogParentRevs); | |
| 493 } | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 /** | |
| 498 * Annotates changes of the file against its parent(s). | |
| 499 * Unlike {@link #annotate(HgDataFile, int, Inspector, HgIterateDirection)}, doesn't | |
| 500 * walk file history, looks at the specified revision only. Handles both parents (if merge revision). | |
| 501 */ | |
| 502 public void annotateSingleRevision(int changelogRevisionIndex, HgBlameInspector insp) throws HgCallbackTargetException { | |
| 503 // TODO detect if file is text/binary (e.g. looking for chars < ' ' and not \t\r\n\f | |
| 504 int fileRevIndex = fileRevIndex(this, changelogRevisionIndex); | |
| 505 int[] fileRevParents = new int[2]; | |
| 506 parents(fileRevIndex, fileRevParents, null, null); | |
| 507 if (changelogRevisionIndex == TIP) { | |
| 508 changelogRevisionIndex = getChangesetRevisionIndex(fileRevIndex); | |
| 509 } | |
| 510 BlameHelper bh = new BlameHelper(insp, 5); | |
| 511 bh.useFileUpTo(this, changelogRevisionIndex); | |
| 512 int[] fileClogParentRevs = new int[2]; | |
| 513 fileClogParentRevs[0] = fileRevParents[0] == NO_REVISION ? NO_REVISION : getChangesetRevisionIndex(fileRevParents[0]); | |
| 514 fileClogParentRevs[1] = fileRevParents[1] == NO_REVISION ? NO_REVISION : getChangesetRevisionIndex(fileRevParents[1]); | |
| 515 bh.annotateChange(fileRevIndex, changelogRevisionIndex, fileRevParents, fileClogParentRevs); | |
| 516 } | |
| 517 | |
| 431 @Override | 518 @Override |
| 432 public String toString() { | 519 public String toString() { |
| 433 StringBuilder sb = new StringBuilder(getClass().getSimpleName()); | 520 StringBuilder sb = new StringBuilder(getClass().getSimpleName()); |
| 434 sb.append('('); | 521 sb.append('('); |
| 435 sb.append(getPath()); | 522 sb.append(getPath()); |
| 443 } | 530 } |
| 444 // use MetadataInspector without delegate to process metadata only | 531 // use MetadataInspector without delegate to process metadata only |
| 445 RevlogStream.Inspector insp = new MetadataInspector(metadata, null); | 532 RevlogStream.Inspector insp = new MetadataInspector(metadata, null); |
| 446 super.content.iterate(localRev, localRev, true, insp); | 533 super.content.iterate(localRev, localRev, true, insp); |
| 447 } | 534 } |
| 535 | |
| 536 | |
| 537 private static int fileRevIndex(HgDataFile df, int csetRevIndex) { | |
| 538 Nodeid fileRev = df.getRepo().getManifest().getFileRevision(csetRevIndex, df.getPath()); | |
| 539 return df.getRevisionIndex(fileRev); | |
| 540 } | |
| 541 | |
| 448 | 542 |
| 449 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { | 543 private static class MetadataInspector extends ErrorHandlingInspector implements RevlogStream.Inspector { |
| 450 private final Metadata metadata; | 544 private final Metadata metadata; |
| 451 private final RevlogStream.Inspector delegate; | 545 private final RevlogStream.Inspector delegate; |
| 452 | 546 |
