Mercurial > hg4j
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 |