# HG changeset patch # User Artem Tikhomirov # Date 1369230751 -7200 # Node ID 6526d8adbc0fb11575bf87b6641e28a24ec4dca5 # Parent 5153eb73b18d68fdba1d7ba7d32039e37d91dc83 Explicit HgRuntimeException to facilitate easy switch from runtime to checked exceptions diff -r 5153eb73b18d -r 6526d8adbc0f cmdline/org/tmatesoft/hg/console/Bundle.java --- a/cmdline/org/tmatesoft/hg/console/Bundle.java Tue May 21 20:17:33 2013 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Bundle.java Wed May 22 15:52:31 2013 +0200 @@ -29,6 +29,7 @@ import org.tmatesoft.hg.repo.HgBundle.GroupElement; import org.tmatesoft.hg.repo.HgBundle.Inspector; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; +import org.tmatesoft.hg.repo.HgRuntimeException; /** @@ -60,7 +61,7 @@ hgBundle.changes(hgRepo, new HgChangelog.Inspector() { private final HgChangelog changelog = hgRepo.getChangelog(); - public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { + public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) throws HgRuntimeException { if (changelog.isKnown(nodeid)) { System.out.print("+"); } else { @@ -99,7 +100,7 @@ */ - public static void dump(HgBundle hgBundle) throws HgException { + public static void dump(HgBundle hgBundle) throws HgException, HgRuntimeException { Dump dump = new Dump(); hgBundle.inspectAll(dump); System.out.println("Total files:" + dump.names.size()); diff -r 5153eb73b18d -r 6526d8adbc0f cmdline/org/tmatesoft/hg/console/ChangesetDumpHandler.java --- a/cmdline/org/tmatesoft/hg/console/ChangesetDumpHandler.java Tue May 21 20:17:33 2013 +0200 +++ b/cmdline/org/tmatesoft/hg/console/ChangesetDumpHandler.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ import org.tmatesoft.hg.core.HgFileRevision; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Path; /** @@ -43,7 +44,7 @@ private final HgRepository repo; private final int tip; - public ChangesetDumpHandler(HgRepository hgRepo) { + public ChangesetDumpHandler(HgRepository hgRepo) throws HgRuntimeException { repo = hgRepo; tip = hgRepo.getChangelog().getLastRevision(); } @@ -63,7 +64,7 @@ return this; } - public void cset(HgChangeset changeset) { + public void cset(HgChangeset changeset) throws HgRuntimeException { try { final String s = print(changeset); if (reverseOrder) { @@ -89,7 +90,7 @@ l.clear(); } - private String print(HgChangeset cset) throws HgException { + private String print(HgChangeset cset) throws HgException, HgRuntimeException { StringBuilder sb = new StringBuilder(); Formatter f = new Formatter(sb); final Nodeid csetNodeid = cset.getNodeid(); diff -r 5153eb73b18d -r 6526d8adbc0f cmdline/org/tmatesoft/hg/console/Log.java --- a/cmdline/org/tmatesoft/hg/console/Log.java Tue May 21 20:17:33 2013 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Log.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 TMate Software Ltd + * Copyright (c) 2010-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ import org.tmatesoft.hg.core.HgLogCommand; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.CancelSupport; import org.tmatesoft.hg.util.ProgressSupport; @@ -124,7 +125,7 @@ private static final class Dump extends ChangesetDumpHandler implements HgChangesetHandler.WithCopyHistory { private final RenameDumpHandler renameHandlerDelegate; - public Dump(HgRepository hgRepo) { + public Dump(HgRepository hgRepo) throws HgRuntimeException { super(hgRepo); renameHandlerDelegate = new RenameDumpHandler(); } diff -r 5153eb73b18d -r 6526d8adbc0f cmdline/org/tmatesoft/hg/console/Main.java --- a/cmdline/org/tmatesoft/hg/console/Main.java Tue May 21 20:17:33 2013 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Main.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,6 +57,7 @@ import org.tmatesoft.hg.repo.HgDirstate.Record; import org.tmatesoft.hg.repo.HgIgnore; import org.tmatesoft.hg.repo.HgInternals; +import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgManifest; import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.repo.HgMergeState; @@ -219,7 +220,7 @@ cmd.file("a2.txt", true, false); final int[] count = new int[] { 0 }; class MyHandler implements HgChangesetTreeHandler, Adaptable { - public void treeElement(HgChangesetTreeHandler.TreeElement entry) { + public void treeElement(HgChangesetTreeHandler.TreeElement entry) throws HgRuntimeException { StringBuilder sb = new StringBuilder(); HashSet test = new HashSet(entry.childRevisions()); for (HgChangeset cc : entry.children()) { @@ -519,7 +520,7 @@ System.out.println(bac.toArray().length); } - private void dumpIgnored() { + private void dumpIgnored() throws HgInvalidControlFileException { String[] toCheck = new String[] {"design.txt", "src/com/tmate/hgkit/ll/Changelog.java", "src/Extras.java", "bin/com/tmate/hgkit/ll/Changelog.class"}; HgIgnore ignore = hgRepo.getIgnore(); for (int i = 0; i < toCheck.length; i++) { @@ -609,7 +610,7 @@ public void dir(Path p) { System.out.println(p); } - public void file(HgFileRevision fileRevision) { + public void file(HgFileRevision fileRevision) throws HgRuntimeException { System.out.print(fileRevision.getRevision());; System.out.print(" "); System.out.printf("%s %s", fileRevision.getParents().first().shortNotation(), fileRevision.getParents().second().shortNotation()); @@ -672,7 +673,7 @@ } - private void testStatusInternals() throws HgException { + private void testStatusInternals() throws HgException, HgRuntimeException { HgDataFile n = hgRepo.getFileNode(Path.create("design.txt")); for (String s : new String[] {"011dfd44417c72bd9e54cf89b82828f661b700ed", "e5529faa06d53e06a816e56d218115b42782f1ba", "c18e7111f1fc89a80a00f6a39d51288289a382fc"}) { // expected: 359, 2123, 3079 diff -r 5153eb73b18d -r 6526d8adbc0f cmdline/org/tmatesoft/hg/console/Manifest.java --- a/cmdline/org/tmatesoft/hg/console/Manifest.java Tue May 21 20:17:33 2013 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Manifest.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 TMate Software Ltd + * Copyright (c) 2010-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ import org.tmatesoft.hg.repo.HgInvalidRevisionException; import org.tmatesoft.hg.repo.HgManifest; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Path; @@ -52,7 +53,7 @@ } public void dir(Path p) { } - public void file(HgFileRevision fileRevision) { + public void file(HgFileRevision fileRevision) throws HgRuntimeException { try { if (debug) { System.out.print(fileRevision.getRevision());; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/ChangesetTransformer.java --- a/src/org/tmatesoft/hg/core/ChangesetTransformer.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/ChangesetTransformer.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.repo.HgStatusCollector; import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.util.Adaptable; @@ -63,7 +64,7 @@ lifecycleBridge = new LifecycleBridge(ps, cs); } - public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { + public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) throws HgRuntimeException { if (branches != null && !branches.contains(cset.branch())) { return; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgAnnotateCommand.java --- a/src/org/tmatesoft/hg/core/HgAnnotateCommand.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgAnnotateCommand.java Wed May 22 15:52:31 2013 +0200 @@ -28,6 +28,7 @@ import org.tmatesoft.hg.repo.HgBlameInspector.BlockData; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.CancelSupport; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.Path; @@ -107,27 +108,31 @@ final CancelSupport cancellation = getCancelSupport(inspector, true); cancellation.checkCancelled(); progress.start(2); - HgDataFile df = repo.getFileNode(file); - if (!df.exists()) { - return; + try { + HgDataFile df = repo.getFileNode(file); + if (!df.exists()) { + return; + } + final int changesetStart = followRename ? 0 : df.getChangesetRevisionIndex(0); + Collector c = new Collector(cancellation); + FileAnnotation fa = new FileAnnotation(c); + df.annotate(changesetStart, annotateRevision.get(), fa, HgIterateDirection.NewToOld); + progress.worked(1); + c.throwIfCancelled(); + cancellation.checkCancelled(); + ProgressSupport.Sub subProgress = new ProgressSupport.Sub(progress, 1); + subProgress.start(c.lineRevisions.length); + LineImpl li = new LineImpl(); + for (int i = 0; i < c.lineRevisions.length; i++) { + li.init(i+1, c.lineRevisions[i], c.line(i)); + inspector.next(li); + subProgress.worked(1); + cancellation.checkCancelled(); + } + subProgress.done(); + } catch (HgRuntimeException ex) { + throw new HgLibraryFailureException(ex); } - final int changesetStart = followRename ? 0 : df.getChangesetRevisionIndex(0); - Collector c = new Collector(cancellation); - FileAnnotation fa = new FileAnnotation(c); - df.annotate(changesetStart, annotateRevision.get(), fa, HgIterateDirection.NewToOld); - progress.worked(1); - c.throwIfCancelled(); - cancellation.checkCancelled(); - ProgressSupport.Sub subProgress = new ProgressSupport.Sub(progress, 1); - subProgress.start(c.lineRevisions.length); - LineImpl li = new LineImpl(); - for (int i = 0; i < c.lineRevisions.length; i++) { - li.init(i+1, c.lineRevisions[i], c.line(i)); - inspector.next(li); - subProgress.worked(1); - cancellation.checkCancelled(); - } - subProgress.done(); progress.done(); } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgChangesetHandler.java --- a/src/org/tmatesoft/hg/core/HgChangesetHandler.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgChangesetHandler.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ package org.tmatesoft.hg.core; import org.tmatesoft.hg.internal.Callback; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Adaptable; import org.tmatesoft.hg.util.Path; @@ -32,8 +33,9 @@ /** * @param changeset descriptor of a change, not necessarily a distinct instance each time, {@link HgChangeset#clone() clone()} if need a copy. * @throws HgCallbackTargetException wrapper for any exception user code may produce + * @throws HgRuntimeException propagates library issues. Runtime exception */ - void cset(HgChangeset changeset) throws HgCallbackTargetException; + void cset(HgChangeset changeset) throws HgCallbackTargetException, HgRuntimeException; /** diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgChangesetTreeHandler.java --- a/src/org/tmatesoft/hg/core/HgChangesetTreeHandler.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgChangesetTreeHandler.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ import org.tmatesoft.hg.internal.Callback; import org.tmatesoft.hg.repo.HgDataFile; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Pair; /** @@ -36,16 +37,18 @@ * @param entry access to various pieces of information about current tree node. Instances might be * reused across calls and shall not be kept by client's code * @throws HgCallbackTargetException wrapper for any exception user code may produce + * @throws HgRuntimeException propagates library issues. Runtime exception */ - public void treeElement(HgChangesetTreeHandler.TreeElement entry) throws HgCallbackTargetException; + public void treeElement(HgChangesetTreeHandler.TreeElement entry) throws HgCallbackTargetException, HgRuntimeException; interface TreeElement { /** * Revision of the revlog being iterated. For example, when walking file history, return value represents file revisions. * * @return revision of the revlog being iterated. + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public Nodeid fileRevision(); + public Nodeid fileRevision() throws HgRuntimeException; /** * File node, provided revlog being iterated is a {@link HgDataFile}; {@link #fileRevision()} @@ -55,19 +58,22 @@ * file name for particular revision in the history. * * @return instance of the file being walked, or null if it's not a file but other revlog. + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public HgDataFile file(); + public HgDataFile file() throws HgRuntimeException; /** * @return changeset associated with the current file revision + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public HgChangeset changeset(); + public HgChangeset changeset() throws HgRuntimeException; /** * Lightweight alternative to {@link #changeset()}, identifies changeset in which current file node has been modified * @return changeset {@link Nodeid revision} + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public Nodeid changesetRevision(); + public Nodeid changesetRevision() throws HgRuntimeException; /** * Identifies parent changes, changesets where file/revlog in question was modified prior to change being visited. @@ -91,25 +97,29 @@ * then this {@link #parents()} call would return pair with single element only, pointing to D * * @return changesets that correspond to parents of the current file node, either pair element may be null. + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public Pair parents(); + public Pair parents() throws HgRuntimeException; /** * Lightweight alternative to {@link #parents()}, give {@link Nodeid nodeids} only * @return two values, neither is null, use {@link Nodeid#isNull()} to identify parent not set + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public Pair parentRevisions(); + public Pair parentRevisions() throws HgRuntimeException; /** * Changes that originate from the given change and bear it as their parent. * @return collection (possibly empty) of immediate children of the change + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public Collection children(); + public Collection children() throws HgRuntimeException; /** * Lightweight alternative to {@link #children()}. * @return never null + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public Collection childRevisions(); + public Collection childRevisions() throws HgRuntimeException; } } \ No newline at end of file diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgCloneCommand.java --- a/src/org/tmatesoft/hg/core/HgCloneCommand.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgCloneCommand.java Wed May 22 15:52:31 2013 +0200 @@ -90,7 +90,6 @@ * @throws HgRepositoryNotFoundException * @throws HgException * @throws CancelledException - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ public HgRepository execute() throws HgException, CancelledException { if (destination == null) { @@ -114,23 +113,27 @@ // if cloning remote repo, which can stream and no revision is specified - // can use 'stream_out' wireproto // - // pull all changes from the very beginning - // XXX consult getContext() if by any chance has a bundle ready, if not, then read and register - HgBundle completeChanges = srcRepo.getChanges(Collections.singletonList(NULL)); - cancel.checkCancelled(); - WriteDownMate mate = new WriteDownMate(srcRepo.getSessionContext(), destination, progress, cancel); try { - // instantiate new repo in the destdir - mate.initEmptyRepository(); - // pull changes - completeChanges.inspectAll(mate); - mate.checkFailure(); - mate.complete(); - } catch (IOException ex) { - throw new HgInvalidFileException(getClass().getName(), ex); - } finally { - completeChanges.unlink(); - progress.done(); + // pull all changes from the very beginning + // XXX consult getContext() if by any chance has a bundle ready, if not, then read and register + HgBundle completeChanges = srcRepo.getChanges(Collections.singletonList(NULL)); + cancel.checkCancelled(); + WriteDownMate mate = new WriteDownMate(srcRepo.getSessionContext(), destination, progress, cancel); + try { + // instantiate new repo in the destdir + mate.initEmptyRepository(); + // pull changes + completeChanges.inspectAll(mate); + mate.checkFailure(); + mate.complete(); + } catch (IOException ex) { + throw new HgInvalidFileException(getClass().getName(), ex); + } finally { + completeChanges.unlink(); + progress.done(); + } + } catch (HgRuntimeException ex) { + throw new HgLibraryFailureException(ex); } return new HgLookup().detect(destination); } @@ -190,7 +193,7 @@ fncacheFile.write(); } - public void changelogStart() { + public void changelogStart() throws HgInvalidControlFileException { try { revlogHeader.offset(0).baseRevision(-1); revisionSequence.clear(); @@ -202,7 +205,7 @@ stopIfCancelled(); } - public void changelogEnd() { + public void changelogEnd() throws HgInvalidControlFileException { try { clearPreviousContent(); collectChangelogIndexes = false; @@ -214,7 +217,7 @@ stopIfCancelled(); } - public void manifestStart() { + public void manifestStart() throws HgInvalidControlFileException { try { revlogHeader.offset(0).baseRevision(-1); revisionSequence.clear(); @@ -225,7 +228,7 @@ stopIfCancelled(); } - public void manifestEnd() { + public void manifestEnd() throws HgInvalidControlFileException { try { clearPreviousContent(); closeIndexFile(); @@ -236,7 +239,7 @@ stopIfCancelled(); } - public void fileStart(String name) { + public void fileStart(String name) throws HgInvalidControlFileException { try { revlogHeader.offset(0).baseRevision(-1); revisionSequence.clear(); @@ -250,7 +253,7 @@ stopIfCancelled(); } - public void fileEnd(String name) { + public void fileEnd(String name) throws HgInvalidControlFileException { try { fncacheFile.addIndex(pathFactory.path(name)); clearPreviousContent(); @@ -277,7 +280,7 @@ currentFile = null; } - private int knownRevision(Nodeid p) { + private int knownRevision(Nodeid p) throws HgInvalidControlFileException { if (p.isNull()) { return -1; } else { @@ -291,7 +294,7 @@ throw new HgInvalidControlFileException(m, null, new File(hgDir, filename)).setRevision(p); } - public boolean element(GroupElement ge) { + public boolean element(GroupElement ge) throws HgRuntimeException { try { assert indexFile != null; boolean writeComplete = false; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgCommitCommand.java --- a/src/org/tmatesoft/hg/core/HgCommitCommand.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgCommitCommand.java Wed May 22 15:52:31 2013 +0200 @@ -30,6 +30,7 @@ import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgInternals; +import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.repo.HgStatusCollector.Record; @@ -74,12 +75,17 @@ * Tell if changes in the working directory constitute merge commit. May be invoked prior to (and independently from) {@link #execute()} * * @return true if working directory changes are result of a merge - * @throws HgException subclass thereof to indicate specific issue with the repository + * @throws HgLibraryFailureException to indicate unexpected issue with the repository + * @throws HgException subclass thereof to indicate other specific issue with repository state */ public boolean isMergeCommit() throws HgException { - int[] parents = new int[2]; - detectParentFromDirstate(parents); - return parents[0] != NO_REVISION && parents[1] != NO_REVISION; + try { + int[] parents = new int[2]; + detectParentFromDirstate(parents); + return parents[0] != NO_REVISION && parents[1] != NO_REVISION; + } catch (HgRuntimeException ex) { + throw new HgLibraryFailureException(ex); + } } /** @@ -152,7 +158,7 @@ return newRevision; } - private String detectBranch() { + private String detectBranch() throws HgInvalidControlFileException { return repo.getWorkingCopyBranchName(); } @@ -164,7 +170,7 @@ return new HgInternals(repo).getNextCommitUsername(); } - private void detectParentFromDirstate(int[] parents) { + private void detectParentFromDirstate(int[] parents) throws HgRuntimeException { Pair pn = repo.getWorkingCopyParents(); HgChangelog clog = repo.getChangelog(); parents[0] = pn.first().isNull() ? NO_REVISION : clog.getRevisionIndex(pn.first()); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgFileRenameHandlerMixin.java --- a/src/org/tmatesoft/hg/core/HgFileRenameHandlerMixin.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgFileRenameHandlerMixin.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 TMate Software Ltd + * Copyright (c) 2012-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,7 @@ */ package org.tmatesoft.hg.core; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Adaptable; /** @@ -34,6 +35,7 @@ /** * @throws HgCallbackTargetException wrapper object for any exception user code may produce + * @throws HgRuntimeException propagates library issues. Runtime exception */ - void copy(HgFileRevision from, HgFileRevision to) throws HgCallbackTargetException; + void copy(HgFileRevision from, HgFileRevision to) throws HgCallbackTargetException, HgRuntimeException; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgFileRevision.java --- a/src/org/tmatesoft/hg/core/HgFileRevision.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgFileRevision.java Wed May 22 15:52:31 2013 +0200 @@ -107,7 +107,11 @@ return flags; } - public boolean wasCopied() throws HgException { + /** + * @return true if this file revision was created as a result of a copy/rename + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + */ + public boolean wasCopied() throws HgRuntimeException { if (isCopy == null) { checkCopy(); } @@ -115,8 +119,9 @@ } /** * @return null if {@link #wasCopied()} is false, name of the copy source otherwise. + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public Path getOriginIfCopy() throws HgException { + public Path getOriginIfCopy() throws HgRuntimeException { if (wasCopied()) { return origin; } @@ -145,7 +150,13 @@ return parents; } - public void putContentTo(ByteChannel sink) throws HgException, CancelledException { + /** + * Pipe content of this file revision into the sink + * @param sink accepts file revision content + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws CancelledException if execution of the operation was cancelled + */ + public void putContentTo(ByteChannel sink) throws HgRuntimeException, CancelledException { HgDataFile fn = repo.getFileNode(path); int revisionIndex = fn.getRevisionIndex(revision); fn.contentWithFilters(revisionIndex, sink); @@ -156,7 +167,7 @@ return String.format("HgFileRevision(%s, %s)", getPath().toString(), revision.shortNotation()); } - private void checkCopy() throws HgException { + private void checkCopy() throws HgRuntimeException { HgDataFile fn = repo.getFileNode(path); if (fn.isCopy()) { if (fn.getRevision(0).equals(revision)) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgIOException.java --- a/src/org/tmatesoft/hg/core/HgIOException.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgIOException.java Wed May 22 15:52:31 2013 +0200 @@ -40,7 +40,7 @@ * @param cause root cause for the error, likely {@link IOException} or its subclass, but not necessarily, and may be omitted. * @param troubleFile file we tried to deal with, never null */ - public HgIOException(String message, Exception cause, File troubleFile) { + public HgIOException(String message, Throwable cause, File troubleFile) { super(message, cause); file = troubleFile; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgIncomingCommand.java --- a/src/org/tmatesoft/hg/core/HgIncomingCommand.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgIncomingCommand.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,12 +31,11 @@ import org.tmatesoft.hg.repo.HgBundle; import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; -import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgInvalidStateException; +import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgRemoteRepository; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.repo.HgRuntimeException; -import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.ProgressSupport; @@ -138,10 +137,10 @@ if (handler == null) { throw new IllegalArgumentException("Delegate can't be null"); } - final List common = getCommon(); - HgBundle changegroup = remoteRepo.getChanges(common); final ProgressSupport ps = getProgressSupport(handler); try { + final List common = getCommon(); + HgBundle changegroup = remoteRepo.getChanges(common); final ChangesetTransformer transformer = new ChangesetTransformer(localRepo, handler, getParentHelper(), ps, getCancelSupport(handler, true)); transformer.limitBranches(branches); changegroup.changes(localRepo, new HgChangelog.Inspector() { @@ -154,7 +153,7 @@ localIndex = localRepo.getChangelog().getRevisionCount(); } - public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { + public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) throws HgRuntimeException { if (parentHelper.knownNode(nodeid)) { if (!common.contains(nodeid)) { throw new HgInvalidStateException("Bundle shall not report known nodes other than roots we've supplied"); @@ -172,7 +171,7 @@ } } - private RepositoryComparator getComparator() throws HgInvalidControlFileException, CancelledException { + private RepositoryComparator getComparator() throws CancelledException, HgRuntimeException { if (remoteRepo == null) { throw new IllegalArgumentException("Shall specify remote repository to compare against", null); } @@ -183,7 +182,7 @@ return comparator; } - private HgParentChildMap getParentHelper() throws HgInvalidControlFileException { + private HgParentChildMap getParentHelper() throws HgRuntimeException { if (parentHelper == null) { parentHelper = new HgParentChildMap(localRepo.getChangelog()); parentHelper.init(); @@ -191,14 +190,14 @@ return parentHelper; } - private List getMissingBranches() throws HgRemoteConnectionException, HgInvalidControlFileException, CancelledException { + private List getMissingBranches() throws HgRemoteConnectionException, CancelledException, HgRuntimeException { if (missingBranches == null) { missingBranches = getComparator().calculateMissingBranches(); } return missingBranches; } - private List getCommon() throws HgRemoteConnectionException, HgInvalidControlFileException, CancelledException { + private List getCommon() throws HgRemoteConnectionException, CancelledException, HgRuntimeException { // return getComparator(context).getCommon(); final LinkedHashSet common = new LinkedHashSet(); // XXX common can be obtained from repoCompare, but at the moment it would almost duplicate work of calculateMissingBranches diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgLogCommand.java --- a/src/org/tmatesoft/hg/core/HgLogCommand.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgLogCommand.java Wed May 22 15:52:31 2013 +0200 @@ -45,7 +45,6 @@ import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.repo.HgDataFile; -import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgInvalidStateException; import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgRepository; @@ -297,20 +296,20 @@ if (csetTransform != null) { throw new ConcurrentModificationException(); } - if (repo.getChangelog().getRevisionCount() == 0) { - return; - } - final int lastCset = endRev == TIP ? repo.getChangelog().getLastRevision() : endRev; - // XXX pretty much like HgInternals.checkRevlogRange - if (lastCset < 0 || lastCset > repo.getChangelog().getLastRevision()) { - throw new HgBadArgumentException(String.format("Bad value %d for end revision", lastCset), null); - } - if (startRev < 0 || startRev > lastCset) { - throw new HgBadArgumentException(String.format("Bad value %d for start revision for range [%1$d..%d]", startRev, lastCset), null); - } final ProgressSupport progressHelper = getProgressSupport(handler); - final int BATCH_SIZE = 100; try { + if (repo.getChangelog().getRevisionCount() == 0) { + return; + } + final int lastCset = endRev == TIP ? repo.getChangelog().getLastRevision() : endRev; + // XXX pretty much like HgInternals.checkRevlogRange + if (lastCset < 0 || lastCset > repo.getChangelog().getLastRevision()) { + throw new HgBadArgumentException(String.format("Bad value %d for end revision", lastCset), null); + } + if (startRev < 0 || startRev > lastCset) { + throw new HgBadArgumentException(String.format("Bad value %d for start revision for range [%1$d..%d]", startRev, lastCset), null); + } + final int BATCH_SIZE = 100; count = 0; HgParentChildMap pw = getParentHelper(file == null); // leave it uninitialized unless we iterate whole repo // ChangesetTransfrom creates a blank PathPool, and #file(String, boolean) above @@ -517,44 +516,48 @@ final CancelSupport cancelHelper = getCancelSupport(handler, true); final HgFileRenameHandlerMixin renameHandler = Adaptable.Factory.getAdapter(handler, HgFileRenameHandlerMixin.class, null); - - // XXX rename. dispatcher is not a proper name (most of the job done - managing history chunk interconnection) - final HandlerDispatcher dispatcher = new HandlerDispatcher() { - - @Override - protected void once(HistoryNode n) throws HgCallbackTargetException, CancelledException { - handler.treeElement(ei.init(n, currentFileNode)); - cancelHelper.checkCancelled(); - } - }; + try { - // renamed files in the queue are placed with respect to #iterateDirection - // i.e. if we iterate from new to old, recent filenames come first - FileRenameQueueBuilder frqBuilder = new FileRenameQueueBuilder(); - List> fileRenamesQueue = frqBuilder.buildFileRenamesQueue(); - // XXX perhaps, makes sense to look at selected file's revision when followAncestry is true - // to ensure file we attempt to trace is in the WC's parent. Native hg aborts if not. - progressHelper.start(4 * fileRenamesQueue.size()); - for (int namesIndex = 0, renamesQueueSize = fileRenamesQueue.size(); namesIndex < renamesQueueSize; namesIndex++) { - - final Pair renameInfo = fileRenamesQueue.get(namesIndex); - dispatcher.prepare(progressHelper, renameInfo); - cancelHelper.checkCancelled(); - if (namesIndex > 0) { - dispatcher.connectWithLastJunctionPoint(renameInfo, fileRenamesQueue.get(namesIndex - 1)); - } - if (namesIndex + 1 < renamesQueueSize) { - // there's at least one more name we are going to look at - dispatcher.updateJunctionPoint(renameInfo, fileRenamesQueue.get(namesIndex+1), renameHandler != null); - } else { - dispatcher.clearJunctionPoint(); - } - dispatcher.dispatchAllChanges(); - if (renameHandler != null && namesIndex + 1 < renamesQueueSize) { - dispatcher.reportRenames(renameHandler); - } - } // for fileRenamesQueue; - frqBuilder.reportRenameIfNotInQueue(fileRenamesQueue, renameHandler); + // XXX rename. dispatcher is not a proper name (most of the job done - managing history chunk interconnection) + final HandlerDispatcher dispatcher = new HandlerDispatcher() { + + @Override + protected void once(HistoryNode n) throws HgCallbackTargetException, CancelledException, HgRuntimeException { + handler.treeElement(ei.init(n, currentFileNode)); + cancelHelper.checkCancelled(); + } + }; + + // renamed files in the queue are placed with respect to #iterateDirection + // i.e. if we iterate from new to old, recent filenames come first + FileRenameQueueBuilder frqBuilder = new FileRenameQueueBuilder(); + List> fileRenamesQueue = frqBuilder.buildFileRenamesQueue(); + // XXX perhaps, makes sense to look at selected file's revision when followAncestry is true + // to ensure file we attempt to trace is in the WC's parent. Native hg aborts if not. + progressHelper.start(4 * fileRenamesQueue.size()); + for (int namesIndex = 0, renamesQueueSize = fileRenamesQueue.size(); namesIndex < renamesQueueSize; namesIndex++) { + + final Pair renameInfo = fileRenamesQueue.get(namesIndex); + dispatcher.prepare(progressHelper, renameInfo); + cancelHelper.checkCancelled(); + if (namesIndex > 0) { + dispatcher.connectWithLastJunctionPoint(renameInfo, fileRenamesQueue.get(namesIndex - 1)); + } + if (namesIndex + 1 < renamesQueueSize) { + // there's at least one more name we are going to look at + dispatcher.updateJunctionPoint(renameInfo, fileRenamesQueue.get(namesIndex+1), renameHandler != null); + } else { + dispatcher.clearJunctionPoint(); + } + dispatcher.dispatchAllChanges(); + if (renameHandler != null && namesIndex + 1 < renamesQueueSize) { + dispatcher.reportRenames(renameHandler); + } + } // for fileRenamesQueue; + frqBuilder.reportRenameIfNotInQueue(fileRenamesQueue, renameHandler); + } catch (HgRuntimeException ex) { + throw new HgLibraryFailureException(ex); + } progressHelper.done(); } @@ -578,8 +581,9 @@ * and possibly reuse this functionality * * @return list of file renames, ordered with respect to {@link #iterateDirection} + * @throws HgRuntimeException */ - public List> buildFileRenamesQueue() throws HgPathNotFoundException { + public List> buildFileRenamesQueue() throws HgPathNotFoundException, HgRuntimeException { LinkedList> rv = new LinkedList>(); Nodeid startRev = null; HgDataFile fileNode = repo.getFileNode(file); @@ -613,11 +617,11 @@ return rv; } - public boolean hasOrigin(Pair p) { + public boolean hasOrigin(Pair p) throws HgRuntimeException { return p.first().isCopy(); } - public Pair origin(Pair p) { + public Pair origin(Pair p) throws HgRuntimeException { HgDataFile fileNode = p.first(); assert fileNode.isCopy(); Path fp = fileNode.getCopySourceName(); @@ -633,7 +637,7 @@ * @param queue value from {@link #buildFileRenamesQueue()} * @param renameHandler may be null */ - public void reportRenameIfNotInQueue(List> queue, HgFileRenameHandlerMixin renameHandler) throws HgCallbackTargetException { + public void reportRenameIfNotInQueue(List> queue, HgFileRenameHandlerMixin renameHandler) throws HgCallbackTargetException, HgRuntimeException { if (renameHandler != null && !followRenames) { // If followRenames is true, all the historical names were in the queue and are processed already. // Hence, shall process origin explicitly only when renameHandler is present but followRenames is not requested. @@ -677,12 +681,12 @@ completeHistory[revisionNumber] = new HistoryNode(commitRevisions[revisionNumber], revision, p1, p2); } - HistoryNode one(HgDataFile fileNode, Nodeid fileRevision) throws HgInvalidControlFileException { + HistoryNode one(HgDataFile fileNode, Nodeid fileRevision) throws HgRuntimeException { int fileRevIndexToVisit = fileNode.getRevisionIndex(fileRevision); return one(fileNode, fileRevIndexToVisit); } - HistoryNode one(HgDataFile fileNode, int fileRevIndexToVisit) throws HgInvalidControlFileException { + HistoryNode one(HgDataFile fileNode, int fileRevIndexToVisit) throws HgRuntimeException { resultHistory = null; if (fileRevIndexToVisit == HgRepository.TIP) { fileRevIndexToVisit = fileNode.getLastRevision(); @@ -708,7 +712,7 @@ * @return list of history elements, from oldest to newest. In case {@link #followAncestry} is true, the list * is modifiable (to further augment with last/first elements of renamed file histories) */ - List go(HgDataFile fileNode, Nodeid fileLastRevisionToVisit) throws HgInvalidControlFileException { + List go(HgDataFile fileNode, Nodeid fileLastRevisionToVisit) throws HgRuntimeException { resultHistory = null; int fileLastRevIndexToVisit = fileLastRevisionToVisit == null ? fileNode.getLastRevision() : fileNode.getRevisionIndex(fileLastRevisionToVisit); completeHistory = new HistoryNode[fileLastRevIndexToVisit+1]; @@ -805,7 +809,7 @@ private HgFileRevision copiedFrom, copiedTo; // parentProgress shall be initialized with 4 XXX refactor all this stuff with parentProgress - public void prepare(ProgressSupport parentProgress, Pair renameInfo) { + public void prepare(ProgressSupport parentProgress, Pair renameInfo) throws HgRuntimeException { // if we don't followAncestry, take complete history // XXX treeBuildInspector knows followAncestry, perhaps the logic // whether to take specific revision or the last one shall be there? @@ -834,7 +838,7 @@ switchTo(renameInfo.first()); } - public void updateJunctionPoint(Pair curRename, Pair nextRename, boolean needCopyFromTo) { + public void updateJunctionPoint(Pair curRename, Pair nextRename, boolean needCopyFromTo) throws HgRuntimeException { copiedFrom = copiedTo = null; // // A (old) renamed to B(new). A(0..k..n) -> B(0..m). If followAncestry, k == n @@ -876,7 +880,7 @@ } } - public void reportRenames(HgFileRenameHandlerMixin renameHandler) throws HgCallbackTargetException { + public void reportRenames(HgFileRenameHandlerMixin renameHandler) throws HgCallbackTargetException, HgRuntimeException { if (renameHandler != null) { // shall report renames assert copiedFrom != null; assert copiedTo != null; @@ -931,9 +935,9 @@ throw new HgInvalidStateException(String.format("For change history (cset[%d..%d]) could not find node for file change %s", csetStart, csetEnd, fileRevision.shortNotation())); } - protected abstract void once(HistoryNode n) throws HgCallbackTargetException, CancelledException; + protected abstract void once(HistoryNode n) throws HgCallbackTargetException, CancelledException, HgRuntimeException; - public void dispatchAllChanges() throws HgCallbackTargetException, CancelledException { + public void dispatchAllChanges() throws HgCallbackTargetException, CancelledException, HgRuntimeException { // XXX shall sort changeHistory according to changeset numbers? Iterator it; if (iterateDirection == HgIterateDirection.OldToNew) { @@ -983,7 +987,7 @@ } } - public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { + public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) throws HgRuntimeException { if (limit > 0 && count >= limit) { return; } @@ -1022,7 +1026,7 @@ } } - private HgParentChildMap getParentHelper(boolean create) throws HgInvalidControlFileException { + private HgParentChildMap getParentHelper(boolean create) throws HgRuntimeException { if (parentHelper == null && create) { parentHelper = new HgParentChildMap(repo.getChangelog()); parentHelper.init(); @@ -1120,11 +1124,11 @@ return fileNode; } - public HgChangeset changeset() { + public HgChangeset changeset() throws HgRuntimeException { return get(historyNode.changeset)[0]; } - public Pair parents() { + public Pair parents() throws HgRuntimeException { if (parents != null) { return parents; } @@ -1144,7 +1148,7 @@ return parents = new Pair(r[0], r[1]); } - public Collection children() { + public Collection children() throws HgRuntimeException { if (children != null) { return children; } @@ -1165,7 +1169,7 @@ cachedChangesets.put(cs.getRevisionIndex(), cs); } - private HgChangeset[] get(int... changelogRevisionIndex) { + private HgChangeset[] get(int... changelogRevisionIndex) throws HgRuntimeException { HgChangeset[] rv = new HgChangeset[changelogRevisionIndex.length]; IntVector misses = new IntVector(changelogRevisionIndex.length, -1); for (int i = 0; i < changelogRevisionIndex.length; i++) { @@ -1187,8 +1191,7 @@ for (int changeset2read : changesets2read) { HgChangeset cs = cachedChangesets.get(changeset2read); if (cs == null) { - HgInvalidStateException t = new HgInvalidStateException(String.format("Can't get changeset for revision %d", changeset2read)); - throw t.setRevisionIndex(changeset2read); + throw new HgInvalidStateException(String.format("Can't get changeset for revision %d", changeset2read)); } // HgChangelog.range may reorder changesets according to their order in the changelog // thus need to find original index @@ -1221,14 +1224,14 @@ populate(cs.clone()); } - public Nodeid changesetRevision() { + public Nodeid changesetRevision() throws HgRuntimeException { if (changesetRevision == null) { changesetRevision = getRevision(historyNode.changeset); } return changesetRevision; } - public Pair parentRevisions() { + public Pair parentRevisions() throws HgRuntimeException { if (parentRevisions == null) { HistoryNode p; final Nodeid p1, p2; @@ -1247,7 +1250,7 @@ return parentRevisions; } - public Collection childRevisions() { + public Collection childRevisions() throws HgRuntimeException { if (childRevisions != null) { return childRevisions; } @@ -1264,7 +1267,7 @@ } // reading nodeid involves reading index only, guess, can afford not to optimize multiple reads - private Nodeid getRevision(int changelogRevisionNumber) { + private Nodeid getRevision(int changelogRevisionNumber) throws HgRuntimeException { // TODO post-1.0 pipe through pool HgChangeset cs = cachedChangesets.get(changelogRevisionNumber); if (cs != null) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgManifestCommand.java --- a/src/org/tmatesoft/hg/core/HgManifestCommand.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgManifestCommand.java Wed May 22 15:52:31 2013 +0200 @@ -190,7 +190,7 @@ } } - public boolean begin(int manifestRevision, Nodeid nid, int changelogRevision) { + public boolean begin(int manifestRevision, Nodeid nid, int changelogRevision) throws HgRuntimeException { if (needDirs && manifestContent == null) { manifestContent = new LinkedList(); } @@ -206,7 +206,7 @@ return false; } } - public boolean end(int revision) { + public boolean end(int revision) throws HgRuntimeException { try { if (needDirs) { LinkedHashMap> breakDown = new LinkedHashMap>(); @@ -243,7 +243,7 @@ } } - public boolean next(Nodeid nid, Path fname, Flags flags) { + public boolean next(Nodeid nid, Path fname, Flags flags) throws HgRuntimeException { if (matcher != null && !matcher.accept(fname)) { return true; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgManifestHandler.java --- a/src/org/tmatesoft/hg/core/HgManifestHandler.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgManifestHandler.java Wed May 22 15:52:31 2013 +0200 @@ -17,6 +17,7 @@ package org.tmatesoft.hg.core; import org.tmatesoft.hg.internal.Callback; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Path; /** @@ -33,8 +34,9 @@ * * @param manifestRevision unique identifier of the manifest revision * @throws HgCallbackTargetException wrapper for any exception user code may produce + * @throws HgRuntimeException propagates library issues. Runtime exception */ - void begin(Nodeid manifestRevision) throws HgCallbackTargetException; + void begin(Nodeid manifestRevision) throws HgCallbackTargetException, HgRuntimeException; /** * If walker is configured to spit out directories, indicates files from specified directories are about to be reported. @@ -42,16 +44,18 @@ * * @param path directory known in the manifest * @throws HgCallbackTargetException wrapper for any exception user code may produce + * @throws HgRuntimeException propagates library issues. Runtime exception */ - void dir(Path path) throws HgCallbackTargetException; + void dir(Path path) throws HgCallbackTargetException, HgRuntimeException; /** * Reports a file revision entry in the manifest * * @param fileRevision description of the file revision * @throws HgCallbackTargetException wrapper for any exception user code may produce + * @throws HgRuntimeException propagates library issues. Runtime exception */ - void file(HgFileRevision fileRevision) throws HgCallbackTargetException; + void file(HgFileRevision fileRevision) throws HgCallbackTargetException, HgRuntimeException; /** * Indicates all files from the manifest revision have been reported. @@ -59,6 +63,7 @@ * * @param manifestRevision unique identifier of the manifest revision * @throws HgCallbackTargetException wrapper for any exception user code may produce + * @throws HgRuntimeException propagates library issues. Runtime exception */ - void end(Nodeid manifestRevision) throws HgCallbackTargetException; + void end(Nodeid manifestRevision) throws HgCallbackTargetException, HgRuntimeException; } \ No newline at end of file diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgOutgoingCommand.java --- a/src/org/tmatesoft/hg/core/HgOutgoingCommand.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgOutgoingCommand.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,11 +23,10 @@ import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.RepositoryComparator; import org.tmatesoft.hg.repo.HgChangelog; -import org.tmatesoft.hg.repo.HgInvalidControlFileException; +import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgRemoteRepository; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.repo.HgRuntimeException; -import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.util.CancelSupport; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.ProgressSupport; @@ -141,7 +140,7 @@ } } - private RepositoryComparator getComparator(ProgressSupport ps, CancelSupport cs) throws HgRemoteConnectionException, HgInvalidControlFileException, CancelledException { + private RepositoryComparator getComparator(ProgressSupport ps, CancelSupport cs) throws HgRemoteConnectionException, CancelledException, HgRuntimeException { if (remoteRepo == null) { throw new IllegalArgumentException("Shall specify remote repository to compare against"); } @@ -152,7 +151,7 @@ return comparator; } - private HgParentChildMap getParentHelper() throws HgInvalidControlFileException { + private HgParentChildMap getParentHelper() throws HgRuntimeException { if (parentHelper == null) { parentHelper = new HgParentChildMap(localRepo.getChangelog()); parentHelper.init(); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/core/HgStatus.java --- a/src/org/tmatesoft/hg/core/HgStatus.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgStatus.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ import org.tmatesoft.hg.internal.ChangelogHelper; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Path; /** @@ -70,8 +71,9 @@ /** * @return null if author for the change can't be deduced (e.g. for clean files it's senseless) + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public String getModificationAuthor() { + public String getModificationAuthor() throws HgRuntimeException { RawChangeset cset = logHelper.findLatestChangeWith(path); if (cset == null) { if (kind == Kind.Modified || kind == Kind.Added || kind == Kind.Removed /*&& RightBoundary is TIP*/) { @@ -84,15 +86,20 @@ return null; } - public Date getModificationDate() { + /** + * @return date when the file was last modified, never null. Either date of changeset the file was modified at + * or timestamp of local file, if present + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + */ + public Date getModificationDate() throws HgRuntimeException { RawChangeset cset = logHelper.findLatestChangeWith(path); if (cset == null) { File localFile = new File(logHelper.getRepo().getWorkingDir(), path.toString()); if (localFile.canRead()) { return new Date(localFile.lastModified()); } - // TODO post-1.0 find out what to do in this case, perhaps, throw an exception? - // perhaps check dirstate and/or local file for tstamp + // TODO post-1.1 find out what to do in this case, perhaps, throw an exception? + // perhaps check dirstate and for timestamp return new Date(); // what's correct? } else { return cset.date(); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/BlameHelper.java --- a/src/org/tmatesoft/hg/internal/BlameHelper.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/BlameHelper.java Wed May 22 15:52:31 2013 +0200 @@ -34,6 +34,7 @@ import org.tmatesoft.hg.repo.HgBlameInspector; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgInvalidStateException; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Adaptable; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.Pair; @@ -62,7 +63,7 @@ *

NOTE, clogRevIndexEnd has to list name of the supplied file in the corresponding manifest, * as it's not possible to trace rename history otherwise. */ - public FileHistory prepare(HgDataFile df, int clogRevIndexStart, int clogRevIndexEnd) { + public FileHistory prepare(HgDataFile df, int clogRevIndexStart, int clogRevIndexEnd) throws HgRuntimeException { assert clogRevIndexStart <= clogRevIndexEnd; FileHistory fileHistory = new FileHistory(df, clogRevIndexStart, clogRevIndexEnd); fileHistory.build(); @@ -84,7 +85,7 @@ } // NO_REVISION is not allowed as any argument - public void diff(int fileRevIndex1, int clogRevIndex1, int fileRevIndex2, int clogRevIndex2) throws HgCallbackTargetException { + public void diff(int fileRevIndex1, int clogRevIndex1, int fileRevIndex2, int clogRevIndex2) throws HgCallbackTargetException, HgRuntimeException { HgDataFile targetFile = linesCache.getFile(clogRevIndex2); LineSequence c1 = linesCache.lines(clogRevIndex1, fileRevIndex1); LineSequence c2 = linesCache.lines(clogRevIndex2, fileRevIndex2); @@ -95,7 +96,7 @@ bbi.checkErrors(); } - public void annotateChange(int fileRevIndex, int csetRevIndex, int[] fileParentRevs, int[] fileParentClogRevs) throws HgCallbackTargetException { + public void annotateChange(int fileRevIndex, int csetRevIndex, int[] fileParentRevs, int[] fileParentClogRevs) throws HgCallbackTargetException, HgRuntimeException { HgDataFile targetFile = linesCache.getFile(csetRevIndex); final LineSequence fileRevLines = linesCache.lines(csetRevIndex, fileRevIndex); if (fileParentClogRevs[0] != NO_REVISION && fileParentClogRevs[1] != NO_REVISION) { @@ -176,7 +177,7 @@ throw new HgInvalidStateException(String.format("Got %d file-changelog mappings, but no luck for revision %d.", files.size(), clogRevIndex)); } - public LineSequence lines(int clogRevIndex, int fileRevIndex) { + public LineSequence lines(int clogRevIndex, int fileRevIndex) throws HgRuntimeException { Pair cached = checkCache(clogRevIndex); if (cached != null) { return cached.second(); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/ChangelogHelper.java --- a/src/org/tmatesoft/hg/internal/ChangelogHelper.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/ChangelogHelper.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,8 +19,8 @@ import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgInternals; -import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Path; /** @@ -56,7 +56,7 @@ * @param file * @return changeset where specified file is mentioned among affected files, or null if none found up to leftBoundary */ - public RawChangeset findLatestChangeWith(Path file) throws HgInvalidControlFileException { + public RawChangeset findLatestChangeWith(Path file) throws HgRuntimeException { HgDataFile df = repo.getFileNode(file); if (!df.exists()) { return null; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/ChangelogMonitor.java --- a/src/org/tmatesoft/hg/internal/ChangelogMonitor.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/ChangelogMonitor.java Wed May 22 15:52:31 2013 +0200 @@ -19,6 +19,7 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.core.SessionContext; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Track changes to a repository based on recent changelog revision. @@ -38,13 +39,13 @@ } // memorize the state of the repository's changelog - public void touch() { + public void touch() throws HgRuntimeException { changelogRevCount = repo.getChangelog().getRevisionCount(); changelogLastRev = safeGetRevision(changelogRevCount-1); } // if present state doesn't match the one we remember - public boolean isChanged() { + public boolean isChanged() throws HgRuntimeException { int rc = repo.getChangelog().getRevisionCount(); if (rc != changelogRevCount) { return true; @@ -54,7 +55,7 @@ } // handles empty repository case - private Nodeid safeGetRevision(int revIndex) { + private Nodeid safeGetRevision(int revIndex) throws HgRuntimeException { if (revIndex >= 0) { return repo.getChangelog().getRevision(revIndex); } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/CommitFacility.java --- a/src/org/tmatesoft/hg/internal/CommitFacility.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/CommitFacility.java Wed May 22 15:52:31 2013 +0200 @@ -40,6 +40,7 @@ import org.tmatesoft.hg.internal.DataSerializer.DataSource; import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgDataFile; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Pair; import org.tmatesoft.hg.util.Path; @@ -97,7 +98,7 @@ // this method doesn't roll transaction back in case of failure, caller's responsibility // this method expects repository to be locked, if needed - public Nodeid commit(String message, Transaction transaction) throws HgIOException, HgRepositoryLockException { + public Nodeid commit(String message, Transaction transaction) throws HgIOException, HgRepositoryLockException, HgRuntimeException { final HgChangelog clog = repo.getRepo().getChangelog(); final int clogRevisionIndex = clog.getRevisionCount(); ManifestRevision c1Manifest = new ManifestRevision(null, null); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/ConfigFile.java --- a/src/org/tmatesoft/hg/internal/ConfigFile.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/ConfigFile.java Wed May 22 15:52:31 2013 +0200 @@ -31,8 +31,8 @@ import java.util.List; import java.util.Map; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.core.SessionContext; -import org.tmatesoft.hg.repo.HgInvalidFileException; import org.tmatesoft.hg.util.LogFacility; /** @@ -50,7 +50,7 @@ sessionContext = ctx; } - public void addLocation(File path) throws HgInvalidFileException { + public void addLocation(File path) throws HgIOException { read(path); } @@ -125,7 +125,7 @@ } } - private void read(File f) throws HgInvalidFileException { + private void read(File f) throws HgIOException { if (f == null || !f.canRead()) { return; } @@ -227,7 +227,7 @@ return true; } - public void go(File f, ConfigFile cfg) throws HgInvalidFileException { + public void go(File f, ConfigFile cfg) throws HgIOException { contextFile = f; LineReader lr = new LineReader(f, cfg.sessionContext.getLog()); lr.ignoreLineComments("#"); @@ -250,7 +250,7 @@ LogFacility lf = cfg.sessionContext.getLog(); lf.dump(ConfigFile.class, LogFacility.Severity.Debug, "Can't read file to include: %s", f); } - } catch (HgInvalidFileException ex) { + } catch (HgIOException ex) { LogFacility lf = cfg.sessionContext.getLog(); lf.dump(ConfigFile.class, LogFacility.Severity.Warn, "Can't include %s (%s)", f, includeValue); } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/CsetParamKeeper.java --- a/src/org/tmatesoft/hg/internal/CsetParamKeeper.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/CsetParamKeeper.java Wed May 22 15:52:31 2013 +0200 @@ -23,6 +23,7 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgInvalidRevisionException; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Common code to keep changelog revision and to perform boundary check. @@ -43,19 +44,25 @@ set(repo.getChangelog().getRevisionIndex(changeset)); } catch (HgInvalidRevisionException ex) { throw new HgBadArgumentException("Can't find revision", ex).setRevision(changeset); + } catch (HgRuntimeException ex) { + throw new HgBadArgumentException(String.format("Can't initialize with revision %s", changeset.shortNotation()), ex); } return this; } public CsetParamKeeper set(int changelogRevIndex) throws HgBadArgumentException { - int lastCsetIndex = repo.getChangelog().getLastRevision(); - if (changelogRevIndex == HgRepository.TIP) { - changelogRevIndex = lastCsetIndex; + try { + int lastCsetIndex = repo.getChangelog().getLastRevision(); + if (changelogRevIndex == HgRepository.TIP) { + changelogRevIndex = lastCsetIndex; + } + if (changelogRevIndex < 0 || changelogRevIndex > lastCsetIndex) { + throw new HgBadArgumentException(String.format("Bad revision index %d, value from [0..%d] expected", changelogRevIndex, lastCsetIndex), null).setRevisionIndex(changelogRevIndex); + } + doSet(changelogRevIndex); + } catch (HgRuntimeException ex) { + throw new HgBadArgumentException(String.format("Can't initialize with revision index %d", changelogRevIndex), ex); } - if (changelogRevIndex < 0 || changelogRevIndex > lastCsetIndex) { - throw new HgBadArgumentException(String.format("Bad revision index %d, value from [0..%d] expected", changelogRevIndex, lastCsetIndex), null).setRevisionIndex(changelogRevIndex); - } - doSet(changelogRevIndex); return this; } @@ -74,7 +81,7 @@ * @param defaultRevisionIndex value to return when no revision was set, may be {@link HgRepository#TIP} which gets translated to real index if used * @return changelog revision index if set, or defaultRevisionIndex value otherwise */ - public int get(int defaultRevisionIndex) { + public int get(int defaultRevisionIndex) throws HgRuntimeException { // XXX perhaps, shall translate other predefined constants (like WORKING COPY) here, too (e.g. for HgRevertCommand) if (changelogRevisionIndex != BAD_REVISION || changelogRevisionIndex != TIP) { return changelogRevisionIndex; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/DataSerializer.java --- a/src/org/tmatesoft/hg/internal/DataSerializer.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/DataSerializer.java Wed May 22 15:52:31 2013 +0200 @@ -19,6 +19,7 @@ import java.io.ByteArrayOutputStream; import org.tmatesoft.hg.core.HgIOException; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Serialization friend of {@link DataAccess} @@ -78,13 +79,13 @@ * Invoked once for a single write operation, * although the source itself may get serialized several times */ - public void serialize(DataSerializer out) throws HgIOException; + public void serialize(DataSerializer out) throws HgIOException, HgRuntimeException; /** * Hint of data length it would like to writes * @return -1 if can't answer */ - public int serializeLength(); + public int serializeLength() throws HgRuntimeException; } public static class ByteArrayDataSource implements DataSource { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/DirstateBuilder.java --- a/src/org/tmatesoft/hg/internal/DirstateBuilder.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/DirstateBuilder.java Wed May 22 15:52:31 2013 +0200 @@ -33,6 +33,7 @@ import org.tmatesoft.hg.repo.HgDirstate; import org.tmatesoft.hg.repo.HgDirstate.EntryKind; import org.tmatesoft.hg.repo.HgDirstate.Record; +import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgInvalidStateException; import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.util.Path; @@ -164,7 +165,7 @@ } } - public void fillFrom(DirstateReader dirstate) { + public void fillFrom(DirstateReader dirstate) throws HgInvalidControlFileException { // TODO preserve order, if reasonable and possible dirstate.readInto(new HgDirstate.Inspector() { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/FileAnnotation.java --- a/src/org/tmatesoft/hg/internal/FileAnnotation.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/FileAnnotation.java Wed May 22 15:52:31 2013 +0200 @@ -23,6 +23,7 @@ import org.tmatesoft.hg.repo.HgBlameInspector.RevisionDescriptor; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgInvalidStateException; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Produce output like 'hg annotate' does @@ -48,7 +49,7 @@ /** * Annotate file revision, line by line. */ - public static void annotate(HgDataFile df, int changelogRevisionIndex, LineInspector insp) throws HgCallbackTargetException { + public static void annotate(HgDataFile df, int changelogRevisionIndex, LineInspector insp) throws HgCallbackTargetException, HgRuntimeException { if (!df.exists()) { return; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/FileHistory.java --- a/src/org/tmatesoft/hg/internal/FileHistory.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/FileHistory.java Wed May 22 15:52:31 2013 +0200 @@ -25,6 +25,7 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * History of a file, with copy/renames, and corresponding revision information. @@ -56,7 +57,7 @@ return csetTo; } - public void build() { + public void build() throws HgRuntimeException { assert fileCompleteHistory.isEmpty(); HgDataFile currentFile = df; final int changelogRevIndexEnd = csetTo; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/FileRevisionHistoryChunk.java --- a/src/org/tmatesoft/hg/internal/FileRevisionHistoryChunk.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/FileRevisionHistoryChunk.java Wed May 22 15:52:31 2013 +0200 @@ -28,6 +28,7 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Piece of file history, identified by path, limited to file revisions from range [chop..init] of changesets, @@ -73,7 +74,7 @@ return csetRangeEnd; } - public void init(int changelogRevisionIndex) { + public void init(int changelogRevisionIndex) throws HgRuntimeException { csetRangeEnd = changelogRevisionIndex; // XXX df.indexWalk(0, fileRevIndex, ) might be more effective Nodeid fileRev = df.getRepo().getManifest().getFileRevision(changelogRevisionIndex, df.getPath()); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/Internals.java --- a/src/org/tmatesoft/hg/internal/Internals.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/Internals.java Wed May 22 15:52:31 2013 +0200 @@ -19,7 +19,6 @@ import static org.tmatesoft.hg.util.LogFacility.Severity.Error; import java.io.File; -import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; @@ -29,6 +28,7 @@ import java.util.List; import java.util.StringTokenizer; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.core.SessionContext; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgInternals; @@ -337,10 +337,9 @@ /** * User-specific configuration, from system-wide and user home locations, without any repository-specific data. - * * @see http://www.selenic.com/mercurial/hgrc.5.html */ - public static ConfigFile readConfiguration(SessionContext sessionCtx) throws IOException { + public static ConfigFile readConfiguration(SessionContext sessionCtx) throws HgIOException { ConfigFile configFile = new ConfigFile(sessionCtx); File hgInstallRoot = findHgInstallRoot(sessionCtx); // may be null // @@ -386,7 +385,7 @@ * Repository-specific configuration * @see http://www.selenic.com/mercurial/hgrc.5.html */ - public ConfigFile readConfiguration() throws IOException { + public ConfigFile readConfiguration() throws HgIOException { ConfigFile configFile = readConfiguration(repo.getSessionContext()); // last one, overrides anything else // /.hg/hgrc diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/LineReader.java --- a/src/org/tmatesoft/hg/internal/LineReader.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/LineReader.java Wed May 22 15:52:31 2013 +0200 @@ -26,7 +26,7 @@ import java.nio.charset.Charset; import java.util.Collection; -import org.tmatesoft.hg.repo.HgInvalidFileException; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.util.LogFacility; /** @@ -95,7 +95,7 @@ return this; } - public void read(LineConsumer consumer, T paramObj) throws HgInvalidFileException { + public void read(LineConsumer consumer, T paramObj) throws HgIOException { BufferedReader statusFileReader = null; try { // consumer.begin(file, paramObj); @@ -120,7 +120,7 @@ } } } catch (IOException ex) { - throw new HgInvalidFileException(ex.getMessage(), ex, file); + throw new HgIOException(ex.getMessage(), ex, file); } finally { new FileUtils(log).closeQuietly(statusFileReader); // try { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/NewlineFilter.java --- a/src/org/tmatesoft/hg/internal/NewlineFilter.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/NewlineFilter.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ import java.util.ArrayList; import java.util.Map; -import org.tmatesoft.hg.repo.HgInvalidFileException; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.repo.HgInvalidStateException; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.util.Adaptable; @@ -314,7 +314,7 @@ ConfigFile hgeol = new ConfigFile(hgRepo.getSessionContext()); try { hgeol.addLocation(cfgFile); - } catch (HgInvalidFileException ex) { + } catch (HgIOException ex) { hgRepo.getSessionContext().getLog().dump(getClass(), Warn, ex, null); } nativeRepoFormat = hgeol.getSection("repository").get("native"); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/PhasesHelper.java --- a/src/org/tmatesoft/hg/internal/PhasesHelper.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/PhasesHelper.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 TMate Software Ltd + * Copyright (c) 2012-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgPhase; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Support to deal with Mercurial phases feature (as of Mercurial version 2.1) @@ -69,7 +70,7 @@ return repo.getRepo(); } - public boolean isCapableOfPhases() throws HgInvalidControlFileException { + public boolean isCapableOfPhases() throws HgRuntimeException { if (null == repoSupporsPhases) { repoSupporsPhases = readRoots(); } @@ -77,13 +78,26 @@ } - public HgPhase getPhase(HgChangeset cset) throws HgInvalidControlFileException { + /** + * @param cset revision to query + * @return phase of the changeset, never null + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception + */ + public HgPhase getPhase(HgChangeset cset) throws HgRuntimeException { final Nodeid csetRev = cset.getNodeid(); final int csetRevIndex = cset.getRevisionIndex(); return getPhase(csetRevIndex, csetRev); } - public HgPhase getPhase(final int csetRevIndex, Nodeid csetRev) throws HgInvalidControlFileException { + /** + * @param csetRevIndex revision index to query + * @param csetRev revision nodeid, optional + * @return phase of the changeset, never null + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception + */ + public HgPhase getPhase(final int csetRevIndex, Nodeid csetRev) throws HgRuntimeException { if (!isCapableOfPhases()) { return HgPhase.Undefined; } @@ -119,8 +133,8 @@ } - private Boolean readRoots() throws HgInvalidControlFileException { - File phaseroots = repo.getFileFromStoreDir("phaseroots"); + private Boolean readRoots() throws HgRuntimeException { + File phaseroots = repo.getFileFromStoreDir("phaseroots"); // TODO into HgRepositoryFiles BufferedReader br = null; try { if (!phaseroots.exists()) { @@ -177,7 +191,7 @@ } - private RevisionDescendants[] getPhaseDescendants(HgPhase phase) throws HgInvalidControlFileException { + private RevisionDescendants[] getPhaseDescendants(HgPhase phase) throws HgRuntimeException { int ordinal = phase.ordinal(); if (phaseDescendants[ordinal] == null) { phaseDescendants[ordinal] = buildPhaseDescendants(phase); @@ -185,7 +199,7 @@ return phaseDescendants[ordinal]; } - private RevisionDescendants[] buildPhaseDescendants(HgPhase phase) throws HgInvalidControlFileException { + private RevisionDescendants[] buildPhaseDescendants(HgPhase phase) throws HgRuntimeException { int[] roots = toIndexes(getPhaseRoots(phase)); RevisionDescendants[] rv = new RevisionDescendants[roots.length]; for (int i = 0; i < roots.length; i++) { @@ -195,7 +209,7 @@ return rv; } - private int[] toIndexes(List roots) throws HgInvalidControlFileException { + private int[] toIndexes(List roots) throws HgRuntimeException { int[] rv = new int[roots.size()]; for (int i = 0; i < rv.length; i++) { rv[i] = getRepo().getChangelog().getRevisionIndex(roots.get(i)); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/RepositoryComparator.java --- a/src/org/tmatesoft/hg/internal/RepositoryComparator.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RepositoryComparator.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,12 +33,12 @@ import org.tmatesoft.hg.core.HgRemoteConnectionException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgChangelog; -import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgInvalidStateException; +import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgRemoteRepository; import org.tmatesoft.hg.repo.HgRemoteRepository.Range; import org.tmatesoft.hg.repo.HgRemoteRepository.RemoteBranch; -import org.tmatesoft.hg.repo.HgParentChildMap; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.CancelSupport; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.ProgressSupport; @@ -93,7 +93,7 @@ * only its revision number. * @param inspector delegate to analyze changesets, shall not be null */ - public void visitLocalOnlyRevisions(HgChangelog.Inspector inspector) throws HgInvalidControlFileException { + public void visitLocalOnlyRevisions(HgChangelog.Inspector inspector) throws HgRuntimeException { if (inspector == null) { throw new IllegalArgumentException(); } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/RevisionDescendants.java --- a/src/org/tmatesoft/hg/internal/RevisionDescendants.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevisionDescendants.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 TMate Software Ltd + * Copyright (c) 2012-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,9 +20,9 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgChangelog; -import org.tmatesoft.hg.repo.HgInvalidControlFileException; import org.tmatesoft.hg.repo.HgInvalidStateException; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Represent indicators which revisions are descendants of the supplied root revision @@ -39,7 +39,7 @@ private final BitSet descendants; // in fact, may be refactored to deal not only with changelog, but any revlog (not sure what would be the usecase, though) - public RevisionDescendants(HgRepository hgRepo, int revisionIndex) { + public RevisionDescendants(HgRepository hgRepo, int revisionIndex) throws HgRuntimeException { repo = hgRepo; rootRevIndex = revisionIndex; // even if tip moves, we still answer correctly for those isCandidate() @@ -51,7 +51,7 @@ descendants = new BitSet(tipRevIndex - rootRevIndex + 1); } - public void build() throws HgInvalidControlFileException { + public void build() throws HgRuntimeException { final BitSet result = descendants; result.set(0); if (rootRevIndex == tipRevIndex) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/RevisionLookup.java --- a/src/org/tmatesoft/hg/internal/RevisionLookup.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevisionLookup.java Wed May 22 15:52:31 2013 +0200 @@ -21,7 +21,10 @@ import java.util.Arrays; import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.repo.HgInvalidControlFileException; +import org.tmatesoft.hg.repo.HgInvalidRevisionException; import org.tmatesoft.hg.repo.HgRevisionMap; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * Lite alternative to {@link HgRevisionMap}, to speed up nodeid to index conversion without consuming too much memory. @@ -42,7 +45,7 @@ content = stream; } - public static RevisionLookup createFor(RevlogStream stream) { + public static RevisionLookup createFor(RevlogStream stream) throws HgRuntimeException { RevisionLookup rv = new RevisionLookup(stream); int revCount = stream.revisionCount(); rv.prepare(revCount); @@ -62,7 +65,7 @@ public void next(int index, Nodeid nodeid) { nodeidHashes[index] = nodeid.hashCode(); } - public int findIndex(Nodeid nodeid) { + public int findIndex(Nodeid nodeid) throws HgInvalidControlFileException, HgInvalidRevisionException { final int hash = nodeid.hashCode(); for (int i = 0; i < nodeidHashes.length; i++) { if (nodeidHashes[i] == hash) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/RevlogCompressor.java --- a/src/org/tmatesoft/hg/internal/RevlogCompressor.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevlogCompressor.java Wed May 22 15:52:31 2013 +0200 @@ -20,6 +20,7 @@ import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.core.SessionContext; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.LogFacility.Severity; /** @@ -44,7 +45,7 @@ } // out stream is not closed! - public int writeCompressedData(DataSerializer out) throws HgIOException { + public int writeCompressedData(DataSerializer out) throws HgIOException, HgRuntimeException { zip.reset(); DeflaterDataSerializer dds = new DeflaterDataSerializer(out, zip, sourceData.serializeLength()); sourceData.serialize(dds); @@ -52,7 +53,7 @@ return zip.getTotalOut(); } - public int getCompressedLength() { + public int getCompressedLength() throws HgRuntimeException { if (compressedLen != -1) { return compressedLen; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/RevlogStream.java --- a/src/org/tmatesoft/hg/internal/RevlogStream.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevlogStream.java Wed May 22 15:52:31 2013 +0200 @@ -36,6 +36,7 @@ import org.tmatesoft.hg.repo.HgInvalidRevisionException; import org.tmatesoft.hg.repo.HgInvalidStateException; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Adaptable; @@ -150,12 +151,12 @@ return inline ? indexFile.getPath() : getDataFile().getPath(); } - public boolean isInlineData() { + public boolean isInlineData() throws HgInvalidControlFileException { initOutline(); return inline; } - public int revisionCount() { + public int revisionCount() throws HgInvalidControlFileException { initOutline(); return baseRevisions.length; } @@ -271,7 +272,7 @@ * @return value suitable for the corresponding field in the new revision's header, not physical offset in the file * (which is different in case of inline revlogs) */ - public long newEntryOffset() { + public long newEntryOffset() throws HgInvalidControlFileException { if (revisionCount() == 0) { return 0; } @@ -291,9 +292,12 @@ } } - // should be possible to use TIP, ALL, or -1, -2, -n notation of Hg - // ? boolean needsNodeid - public void iterate(int start, int end, boolean needData, Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { + /** + * should be possible to use TIP, ALL, or -1, -2, -n notation of Hg + * ? boolean needsNodeid + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + */ + public void iterate(int start, int end, boolean needData, Inspector inspector) throws HgRuntimeException { initOutline(); final int indexSize = revisionCount(); if (indexSize == 0) { @@ -326,8 +330,9 @@ * @param sortedRevisions revisions to walk, in ascending order. * @param needData whether inspector needs access to header only * @param inspector callback to process entries + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public void iterate(int[] sortedRevisions, boolean needData, Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException /*REVISIT - too general exception*/ { + public void iterate(int[] sortedRevisions, boolean needData, Inspector inspector) throws HgRuntimeException { final int indexSize = revisionCount(); if (indexSize == 0 || sortedRevisions.length == 0) { return; @@ -442,7 +447,7 @@ return inline ? indexRecordOffset[revisionIndex] : revisionIndex * REVLOGV1_RECORD_SIZE; } - private int checkRevisionIndex(int revisionIndex) throws HgInvalidRevisionException { + private int checkRevisionIndex(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { final int last = revisionCount() - 1; if (revisionIndex == TIP) { revisionIndex = last; @@ -722,7 +727,7 @@ } // may be invoked few times per instance life - public boolean range(int start, int end) throws IOException { + public boolean range(int start, int end) throws IOException, HgRuntimeException { int i; // it (i.e. replace with i >= start) if (needData && (i = getBaseRevision(start)) < start) { @@ -850,7 +855,7 @@ * @param data access to revision content of actualLen size, or null if no data has been requested with * {@link RevlogStream#iterate(int[], boolean, Inspector)} */ - void next(int revisionIndex, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[/*20*/] nodeid, DataAccess data); + void next(int revisionIndex, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[/*20*/] nodeid, DataAccess data) throws HgRuntimeException; } public interface Observer { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/RevlogStreamWriter.java --- a/src/org/tmatesoft/hg/internal/RevlogStreamWriter.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevlogStreamWriter.java Wed May 22 15:52:31 2013 +0200 @@ -29,7 +29,9 @@ import org.tmatesoft.hg.internal.DataSerializer.ByteArrayDataSource; import org.tmatesoft.hg.internal.DataSerializer.DataSource; import org.tmatesoft.hg.repo.HgInvalidControlFileException; +import org.tmatesoft.hg.repo.HgInvalidRevisionException; import org.tmatesoft.hg.repo.HgInvalidStateException; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * @@ -61,8 +63,9 @@ /** * @return nodeid of added revision + * @throws HgRuntimeException */ - public Nodeid addRevision(DataSource content, int linkRevision, int p1, int p2) throws HgIOException { + public Nodeid addRevision(DataSource content, int linkRevision, int p1, int p2) throws HgIOException, HgRuntimeException { lastEntryRevision = Nodeid.NULL; int revCount = revlogStream.revisionCount(); lastEntryIndex = revCount == 0 ? NO_REVISION : revCount - 1; @@ -138,13 +141,13 @@ return lastEntryRevision; } - private byte[] toByteArray(DataSource content) throws HgIOException { + private byte[] toByteArray(DataSource content) throws HgIOException, HgRuntimeException { ByteArrayDataSerializer ba = new ByteArrayDataSerializer(); content.serialize(ba); return ba.toByteArray(); } - private Nodeid revision(int revisionIndex) { + private Nodeid revision(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { if (revisionIndex == NO_REVISION) { return Nodeid.NULL; } @@ -156,7 +159,7 @@ return n; } - private void populateLastEntry() throws HgInvalidControlFileException { + private void populateLastEntry() throws HgRuntimeException { if (lastEntryContent != null) { return; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/WorkingCopyContent.java --- a/src/org/tmatesoft/hg/internal/WorkingCopyContent.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/WorkingCopyContent.java Wed May 22 15:52:31 2013 +0200 @@ -26,6 +26,7 @@ import org.tmatesoft.hg.repo.HgInvalidFileException; import org.tmatesoft.hg.repo.HgInvalidStateException; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.ByteChannel; import org.tmatesoft.hg.util.CancelledException; @@ -47,7 +48,7 @@ } } - public void serialize(final DataSerializer out) throws HgIOException { + public void serialize(final DataSerializer out) throws HgIOException, HgRuntimeException { final HgIOException failure[] = new HgIOException[1]; try { // TODO #workingCopy API is very limiting, CancelledException is inconvenient, @@ -80,7 +81,7 @@ } } - public int serializeLength() { + public int serializeLength() throws HgRuntimeException { return file.getLength(HgRepository.WORKING_COPY); } } \ No newline at end of file diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/internal/WorkingDirFileWriter.java --- a/src/org/tmatesoft/hg/internal/WorkingDirFileWriter.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/WorkingDirFileWriter.java Wed May 22 15:52:31 2013 +0200 @@ -26,6 +26,7 @@ import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgManifest; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.ByteChannel; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.LogFacility.Severity; @@ -62,8 +63,9 @@ /** * Writes content of specified file revision into local filesystem, or create a symlink according to flags. * Executable bit is set if specified and filesystem supports it. + * @throws HgRuntimeException */ - public void processFile(HgDataFile df, int fileRevIndex, HgManifest.Flags flags) throws IOException { + public void processFile(HgDataFile df, int fileRevIndex, HgManifest.Flags flags) throws IOException, HgRuntimeException { try { prepare(df.getPath()); if (flags != HgManifest.Flags.Link) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgBookmarks.java --- a/src/org/tmatesoft/hg/repo/HgBookmarks.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgBookmarks.java Wed May 22 15:52:31 2013 +0200 @@ -52,66 +52,78 @@ repo = internals; } - /*package-local*/ void read() throws HgInvalidControlFileException { + /*package-local*/ void read() throws HgRuntimeException { readBookmarks(); readActiveBookmark(); } - private void readBookmarks() throws HgInvalidControlFileException { + private void readBookmarks() throws HgRuntimeException { final LogFacility log = repo.getLog(); File all = repo.getRepositoryFile(HgRepositoryFiles.Bookmarks); - LinkedHashMap bm = new LinkedHashMap(); - if (all.canRead() && all.isFile()) { - LineReader lr1 = new LineReader(all, log); - ArrayList c = new ArrayList(); - lr1.read(new LineReader.SimpleLineCollector(), c); - for (String s : c) { - int x = s.indexOf(' '); - try { - if (x > 0) { - Nodeid nid = Nodeid.fromAscii(s.substring(0, x)); - String name = new String(s.substring(x+1)); - if (repo.getRepo().getChangelog().isKnown(nid)) { - // copy name part not to drag complete line - bm.put(name, nid); + try { + LinkedHashMap bm = new LinkedHashMap(); + if (all.canRead() && all.isFile()) { + LineReader lr1 = new LineReader(all, log); + ArrayList c = new ArrayList(); + lr1.read(new LineReader.SimpleLineCollector(), c); + for (String s : c) { + int x = s.indexOf(' '); + try { + if (x > 0) { + Nodeid nid = Nodeid.fromAscii(s.substring(0, x)); + String name = new String(s.substring(x+1)); + if (repo.getRepo().getChangelog().isKnown(nid)) { + // copy name part not to drag complete line + bm.put(name, nid); + } else { + log.dump(getClass(), LogFacility.Severity.Info, "Bookmark %s points to non-existent revision %s, ignored.", name, nid); + } } else { - log.dump(getClass(), LogFacility.Severity.Info, "Bookmark %s points to non-existent revision %s, ignored.", name, nid); + log.dump(getClass(), LogFacility.Severity.Warn, "Can't parse bookmark entry: %s", s); } - } else { - log.dump(getClass(), LogFacility.Severity.Warn, "Can't parse bookmark entry: %s", s); + } catch (IllegalArgumentException ex) { + log.dump(getClass(), LogFacility.Severity.Warn, ex, String.format("Can't parse bookmark entry: %s", s)); } - } catch (IllegalArgumentException ex) { - log.dump(getClass(), LogFacility.Severity.Warn, ex, String.format("Can't parse bookmark entry: %s", s)); } + bookmarks = bm; + } else { + bookmarks = Collections.emptyMap(); } - bookmarks = bm; - } else { - bookmarks = Collections.emptyMap(); + if (bmFileTracker == null) { + bmFileTracker = new FileChangeMonitor(all); + } + bmFileTracker.touch(this); + } catch (HgInvalidControlFileException ex) { + // do not translate HgInvalidControlFileException into another HgInvalidControlFileException + // but only HgInvalidFileException + throw ex; + } catch (HgIOException ex) { + throw new HgInvalidControlFileException(ex, true); } - if (bmFileTracker == null) { - bmFileTracker = new FileChangeMonitor(all); - } - bmFileTracker.touch(this); } - + private void readActiveBookmark() throws HgInvalidControlFileException { activeBookmark = null; File active = repo.getRepositoryFile(HgRepositoryFiles.BookmarksCurrent); - if (active.canRead() && active.isFile()) { - LineReader lr2 = new LineReader(active, repo.getLog()); - ArrayList c = new ArrayList(2); - lr2.read(new LineReader.SimpleLineCollector(), c); - if (c.size() > 0) { - activeBookmark = c.get(0); + try { + if (active.canRead() && active.isFile()) { + LineReader lr2 = new LineReader(active, repo.getLog()); + ArrayList c = new ArrayList(2); + lr2.read(new LineReader.SimpleLineCollector(), c); + if (c.size() > 0) { + activeBookmark = c.get(0); + } } + if (activeTracker == null) { + activeTracker = new FileChangeMonitor(active); + } + activeTracker.touch(this); + } catch (HgIOException ex) { + throw new HgInvalidControlFileException(ex, true); } - if (activeTracker == null) { - activeTracker = new FileChangeMonitor(active); - } - activeTracker.touch(this); } - /*package-local*/void reloadIfChanged() throws HgInvalidControlFileException { + /*package-local*/void reloadIfChanged() throws HgRuntimeException { assert activeTracker != null; assert bmFileTracker != null; if (bmFileTracker.changed(this)) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgBranches.java --- a/src/org/tmatesoft/hg/repo/HgBranches.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgBranches.java Wed May 22 15:52:31 2013 +0200 @@ -40,6 +40,7 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.ChangelogMonitor; import org.tmatesoft.hg.internal.Experimental; +import org.tmatesoft.hg.internal.FileUtils; import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.util.ProgressSupport; @@ -68,7 +69,7 @@ if (!branchheadsCache.canRead()) { return lastInCache; } - BufferedReader br = null; + BufferedReader br = null; // TODO replace with LineReader final Pattern spacePattern = Pattern.compile(" "); try { final LinkedHashMap> branchHeads = new LinkedHashMap>(); @@ -111,26 +112,17 @@ } catch (NumberFormatException ex) { repo.getSessionContext().getLog().dump(getClass(), Warn, ex, null); // FALL THROUGH - } catch (HgInvalidControlFileException ex) { - // shall not happen, thus log as error - repo.getSessionContext().getLog().dump(getClass(), Error, ex, null); - // FALL THROUGH - } catch (HgInvalidRevisionException ex) { + } catch (HgRuntimeException ex) { + // if happens, log error and pretend there's no cache repo.getSessionContext().getLog().dump(getClass(), Error, ex, null); // FALL THROUGH } finally { - if (br != null) { - try { - br.close(); - } catch (IOException ex) { - repo.getSessionContext().getLog().dump(getClass(), Warn, ex, null); // ignore - } - } + new FileUtils(repo.getSessionContext().getLog()).closeQuietly(br); } return -1; // deliberately not lastInCache, to avoid anything but -1 when 1st line was read and there's error is in lines 2..end } - void collect(final ProgressSupport ps) throws HgInvalidControlFileException { + void collect(final ProgressSupport ps) throws HgRuntimeException { branches.clear(); final HgRepository repo = internalRepo.getRepo(); ps.start(1 + repo.getChangelog().getRevisionCount() * 2); @@ -286,7 +278,7 @@ return internalRepo.getFileFromRepoDir("cache/branchheads"); } - /*package-local*/ void reloadIfChanged(ProgressSupport ps) throws HgInvalidControlFileException { + /*package-local*/ void reloadIfChanged(ProgressSupport ps) throws HgRuntimeException { if (repoChangeTracker.isChanged()) { collect(ps); } @@ -313,7 +305,7 @@ this(branchName, Nodeid.NULL, branchHeads); } - void validate(HgChangelog clog, HgRevisionMap rmap) throws HgInvalidControlFileException { + void validate(HgChangelog clog, HgRevisionMap rmap) throws HgRuntimeException { int[] localCset = new int[heads.size()]; int i = 0; for (Nodeid h : heads) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgBundle.java --- a/src/org/tmatesoft/hg/repo/HgBundle.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgBundle.java Wed May 22 15:52:31 2013 +0200 @@ -143,7 +143,7 @@ To recreate 30bd..e5, one have to take content of 9429..e0, not its p1 f1db..5e */ - public boolean element(GroupElement ge) { + public boolean element(GroupElement ge) throws HgRuntimeException { emptyChangelog = false; HgChangelog changelog = hgRepo.getChangelog(); try { @@ -194,24 +194,24 @@ // callback to minimize amount of Strings and Nodeids instantiated @Callback public interface Inspector { - void changelogStart(); - - void changelogEnd(); + void changelogStart() throws HgRuntimeException; - void manifestStart(); + void changelogEnd() throws HgRuntimeException; - void manifestEnd(); + void manifestStart() throws HgRuntimeException; - void fileStart(String name); + void manifestEnd() throws HgRuntimeException; - void fileEnd(String name); + void fileStart(String name) throws HgRuntimeException; + + void fileEnd(String name) throws HgRuntimeException; /** * XXX desperately need exceptions here * @param element data element, instance might be reused, don't keep a reference to it or its raw data * @return true to continue */ - boolean element(GroupElement element); + boolean element(GroupElement element) throws HgRuntimeException; } /** @@ -355,7 +355,7 @@ flowControl = null; } - private void internalInspectChangelog(DataAccess da, Inspector inspector) throws IOException { + private void internalInspectChangelog(DataAccess da, Inspector inspector) throws IOException, HgRuntimeException { if (da.isEmpty()) { return; } @@ -370,7 +370,7 @@ inspector.changelogEnd(); } - private void internalInspectManifest(DataAccess da, Inspector inspector) throws IOException { + private void internalInspectManifest(DataAccess da, Inspector inspector) throws IOException, HgRuntimeException { if (da.isEmpty()) { return; } @@ -385,7 +385,7 @@ inspector.manifestEnd(); } - private void internalInspectFiles(DataAccess da, Inspector inspector) throws IOException { + private void internalInspectFiles(DataAccess da, Inspector inspector) throws IOException, HgRuntimeException { while (!da.isEmpty()) { int fnameLen = da.readInt(); if (fnameLen <= 4) { @@ -406,7 +406,7 @@ } } - private static void readGroup(DataAccess da, Inspector inspector) throws IOException { + private static void readGroup(DataAccess da, Inspector inspector) throws IOException, HgRuntimeException { int len = da.readInt(); boolean good2go = true; Nodeid prevNodeid = Nodeid.NULL; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgChangelog.java --- a/src/org/tmatesoft/hg/repo/HgChangelog.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgChangelog.java Wed May 22 15:52:31 2013 +0200 @@ -53,18 +53,40 @@ super(hgRepo, content, true); } - public void all(final HgChangelog.Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { + /** + * Iterate over whole changelog + * @param inspector callback to process entries + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception + */ + public void all(final HgChangelog.Inspector inspector) throws HgRuntimeException { range(0, getLastRevision(), inspector); } - public void range(int start, int end, final HgChangelog.Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { + /** + * Iterate over changelog part + * @param start first changelog entry to process + * @param end last changelog entry to process + * @param inspector callback to process entries + * @throws HgInvalidRevisionException if any supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception + */ + public void range(int start, int end, final HgChangelog.Inspector inspector) throws HgRuntimeException { if (inspector == null) { throw new IllegalArgumentException(); } content.iterate(start, end, true, new RawCsetParser(inspector)); } - public List range(int start, int end) throws HgInvalidRevisionException, HgInvalidControlFileException { + /** + * @see #range(int, int, Inspector) + * @return changeset entry objects, never null + * @throws HgInvalidRevisionException if any supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception + */ + public List range(int start, int end) throws HgRuntimeException { final RawCsetCollector c = new RawCsetCollector(end - start + 1); range(start, end, c); return c.result; @@ -75,8 +97,11 @@ * changesets strictly in the order they are in the changelog. * @param inspector callback to get changesets * @param revisions revisions to read, unrestricted ordering. + * @throws HgInvalidRevisionException if any supplied revision doesn't identify revision from this revlog Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - public void range(final HgChangelog.Inspector inspector, final int... revisions) throws HgInvalidRevisionException, HgInvalidControlFileException { + public void range(final HgChangelog.Inspector inspector, final int... revisions) throws HgRuntimeException { Arrays.sort(revisions); rangeInternal(inspector, revisions); } @@ -84,7 +109,7 @@ /** * Friends-only version of {@link #range(Inspector, int...)}, when callers know array is sorted */ - /*package-local*/ void rangeInternal(HgChangelog.Inspector inspector, int[] sortedRevisions) throws HgInvalidRevisionException, HgInvalidControlFileException { + /*package-local*/ void rangeInternal(HgChangelog.Inspector inspector, int[] sortedRevisions) throws HgRuntimeException { if (sortedRevisions == null || sortedRevisions.length == 0) { return; } @@ -95,10 +120,12 @@ } /** - * @throws HgInvalidRevisionException if supplied nodeid doesn't identify any revision from this revlog - * @throws HgInvalidControlFileException if access to revlog index/data entry failed + * Get changeset entry object + * @throws HgInvalidRevisionException if supplied nodeid doesn't identify any revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - public RawChangeset changeset(Nodeid nid) throws HgInvalidControlFileException, HgInvalidRevisionException { + public RawChangeset changeset(Nodeid nid) throws HgRuntimeException { int x = getRevisionIndex(nid); return range(x, x).get(0); } @@ -113,7 +140,7 @@ * @param nodeid revision being inspected * @param cset changeset raw data */ - void next(int revisionIndex, Nodeid nodeid, RawChangeset cset); + void next(int revisionIndex, Nodeid nodeid, RawChangeset cset) throws HgRuntimeException; } /** @@ -396,7 +423,7 @@ } } - public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { + public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) throws HgRuntimeException { try { byte[] data = da.byteArray(); cset.init(data, 0, data.length, usersPool); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgDataFile.java --- a/src/org/tmatesoft/hg/repo/HgDataFile.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgDataFile.java Wed May 22 15:52:31 2013 +0200 @@ -194,8 +194,10 @@ /** * @return file revision as recorded in repository manifest for dirstate parent, or null if no file revision can be found + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - private Nodeid getWorkingCopyRevision() throws HgInvalidControlFileException { + private Nodeid getWorkingCopyRevision() throws HgRuntimeException { final Pair wcParents = getRepo().getWorkingCopyParents(); Nodeid p = wcParents.first().isNull() ? wcParents.second() : wcParents.first(); final HgChangelog clog = getRepo().getChangelog(); @@ -217,7 +219,7 @@ csetRevIndex = clog.getLastRevision(); } else { // bad luck, need to search honestly - csetRevIndex = getRepo().getChangelog().getRevisionIndex(p); + csetRevIndex = clog.getRevisionIndex(p); } } Nodeid fileRev = getRepo().getManifest().getFileRevision(csetRevIndex, getPath()); @@ -428,7 +430,7 @@ /** * mimic 'hg diff -r clogRevIndex1 -r clogRevIndex2' */ - public void diff(int clogRevIndex1, int clogRevIndex2, HgBlameInspector insp) throws HgCallbackTargetException { + public void diff(int clogRevIndex1, int clogRevIndex2, HgBlameInspector insp) throws HgRuntimeException, HgCallbackTargetException { int fileRevIndex1 = fileRevIndex(this, clogRevIndex1); int fileRevIndex2 = fileRevIndex(this, clogRevIndex2); BlameHelper bh = new BlameHelper(insp); @@ -439,14 +441,14 @@ /** * Walk file history up/down to revision at given changeset and report changes for each revision */ - public void annotate(int changelogRevisionIndex, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgCallbackTargetException { + public void annotate(int changelogRevisionIndex, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgRuntimeException, HgCallbackTargetException { annotate(0, changelogRevisionIndex, insp, iterateOrder); } /** * Walk file history range and report changes for each revision */ - public void annotate(int changelogRevIndexStart, int changelogRevIndexEnd, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgCallbackTargetException { + public void annotate(int changelogRevIndexStart, int changelogRevIndexEnd, HgBlameInspector insp, HgIterateDirection iterateOrder) throws HgRuntimeException, HgCallbackTargetException { if (wrongRevisionIndex(changelogRevIndexStart) || wrongRevisionIndex(changelogRevIndexEnd)) { throw new IllegalArgumentException(); } @@ -483,7 +485,7 @@ * Unlike {@link #annotate(HgDataFile, int, Inspector, HgIterateDirection)}, doesn't * walk file history, looks at the specified revision only. Handles both parents (if merge revision). */ - public void annotateSingleRevision(int changelogRevisionIndex, HgBlameInspector insp) throws HgCallbackTargetException { + public void annotateSingleRevision(int changelogRevisionIndex, HgBlameInspector insp) throws HgRuntimeException, HgCallbackTargetException { // TODO detect if file is text/binary (e.g. looking for chars < ' ' and not \t\r\n\f int fileRevIndex = fileRevIndex(this, changelogRevisionIndex); int[] fileRevParents = new int[2]; @@ -509,7 +511,7 @@ return sb.toString(); } - private void checkAndRecordMetadata(int localRev) throws HgInvalidControlFileException { + private void checkAndRecordMetadata(int localRev) throws HgRuntimeException { if (metadata == null) { metadata = new Metadata(getRepo()); } @@ -519,7 +521,7 @@ } - private static int fileRevIndex(HgDataFile df, int csetRevIndex) { + private static int fileRevIndex(HgDataFile df, int csetRevIndex) throws HgRuntimeException { Nodeid fileRev = df.getRepo().getManifest().getFileRevision(csetRevIndex, df.getPath()); return df.getRevisionIndex(fileRev); } @@ -539,7 +541,7 @@ setCancelSupport(CancelSupport.Factory.get(chain)); } - public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { + public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException { try { if (metadata.tryRead(revisionNumber, data)) { // da is in prepared state (i.e. we consumed all bytes up to metadata end). diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgInvalidControlFileException.java --- a/src/org/tmatesoft/hg/repo/HgInvalidControlFileException.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgInvalidControlFileException.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +18,7 @@ import java.io.File; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.util.Path; @@ -35,6 +36,13 @@ public HgInvalidControlFileException(String message, Throwable th, File file) { super(message, th, file); } + + public HgInvalidControlFileException(HgIOException ex, boolean replaceStackTrace) { + super(ex.getMessage(), ex.getCause(), ex.getFile()); + if (replaceStackTrace) { + setStackTrace(ex.getStackTrace()); + } + } @Override public HgInvalidControlFileException setFile(File file) { diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgInvalidFileException.java --- a/src/org/tmatesoft/hg/repo/HgInvalidFileException.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgInvalidFileException.java Wed May 22 15:52:31 2013 +0200 @@ -19,6 +19,8 @@ import java.io.File; import java.io.IOException; +import org.tmatesoft.hg.util.Path; + /** * Thrown when there are troubles working with local file. Most likely (but not necessarily) wraps IOException. Might be * perceived as specialized IOException with optional File and other repository information. @@ -59,6 +61,12 @@ details.setFile(file); return this; } + + @Override + public HgInvalidFileException setFileName(Path name) { + super.setFileName(name); + return this; + } /** * @return file object that causes troubles, or null if specific file is unknown diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgLookup.java --- a/src/org/tmatesoft/hg/repo/HgLookup.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgLookup.java Wed May 22 15:52:31 2013 +0200 @@ -23,6 +23,7 @@ import java.net.URL; import org.tmatesoft.hg.core.HgBadArgumentException; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.core.HgRepositoryNotFoundException; import org.tmatesoft.hg.core.SessionContext; import org.tmatesoft.hg.internal.BasicSessionContext; @@ -80,13 +81,19 @@ if (repository == null) { throw new HgRepositoryNotFoundException(String.format("Can't locate .hg/ directory of Mercurial repository in %s nor in parent dirs", location)).setLocation(location.getPath()); } - String repoPath = repository.getParentFile().getAbsolutePath(); - HgRepository rv = new HgRepository(getSessionContext(), repoPath, repository); - int requiresFlags = rv.getImplHelper().getRequiresFlags(); - if ((requiresFlags & RequiresFile.REVLOGV1) == 0) { - throw new HgRepositoryNotFoundException(String.format("%s: repository version is not supported (Mercurial <0.9?)", repoPath)).setLocation(location.getPath()); + try { + String repoPath = repository.getParentFile().getAbsolutePath(); + HgRepository rv = new HgRepository(getSessionContext(), repoPath, repository); + int requiresFlags = rv.getImplHelper().getRequiresFlags(); + if ((requiresFlags & RequiresFile.REVLOGV1) == 0) { + throw new HgRepositoryNotFoundException(String.format("%s: repository version is not supported (Mercurial <0.9?)", repoPath)).setLocation(location.getPath()); + } + return rv; + } catch (HgRuntimeException ex) { + HgRepositoryNotFoundException e = new HgRepositoryNotFoundException("Failed to initialize Hg4J library").setLocation(location.getPath()); + e.initCause(ex); + throw e; } - return rv; } public HgBundle loadBundle(File location) throws HgRepositoryNotFoundException { @@ -152,7 +159,7 @@ globalCfg = new ConfigFile(getSessionContext()); try { globalCfg.addLocation(new File(System.getProperty("user.home"), ".hgrc")); - } catch (HgInvalidFileException ex) { + } catch (HgIOException ex) { // XXX perhaps, makes sense to let caller/client know that we've failed to read global config? getSessionContext().getLog().dump(getClass(), Warn, ex, null); } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgManifest.java --- a/src/org/tmatesoft/hg/repo/HgManifest.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgManifest.java Wed May 22 15:52:31 2013 +0200 @@ -237,7 +237,9 @@ * * @param inspector manifest revision visitor, can't be null * @param revisionIndexes local indexes of changesets to visit, non-null - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if method argument specifies non-existent revision index. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception * @throws InvalidArgumentException if supplied arguments are nulls */ public void walk(final Inspector inspector, int... revisionIndexes) throws HgRuntimeException, IllegalArgumentException { @@ -253,10 +255,11 @@ * Tells manifest revision number that corresponds to the given changeset. May return {@link HgRepository#BAD_REVISION} * if changeset has no associated manifest (cset records NULL nodeid for manifest). * @return manifest revision index, non-negative, or {@link HgRepository#BAD_REVISION}. - * @throws HgInvalidRevisionException if method argument specifies non-existent revision index - * @throws HgInvalidControlFileException if access to revlog index/data entry failed + * @throws HgInvalidRevisionException if method argument specifies non-existent revision index. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - /*package-local*/ int fromChangelog(int changesetRevisionIndex) throws HgInvalidRevisionException, HgInvalidControlFileException { + /*package-local*/ int fromChangelog(int changesetRevisionIndex) throws HgRuntimeException { if (HgInternals.wrongRevisionIndex(changesetRevisionIndex)) { throw new HgInvalidRevisionException(changesetRevisionIndex); } @@ -296,9 +299,11 @@ * @param changelogRevisionIndex local changeset index * @param file path to file in question * @return file revision or null if manifest at specified revision doesn't list such file - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - public Nodeid getFileRevision(int changelogRevisionIndex, final Path file) throws HgInvalidRevisionException, HgInvalidControlFileException { + public Nodeid getFileRevision(int changelogRevisionIndex, final Path file) throws HgRuntimeException { // there's no need for HgDataFile to own this method, or get a delegate // as most of HgDataFile API is using file revision indexes, and there's easy step from file revision index to // both file revision and changeset revision index. But there's no easy way to go from changesetRevisionIndex to @@ -330,7 +335,9 @@ * @param file path of interest * @param inspector callback to receive details about selected file * @param changelogRevisionIndexes changeset indexes to visit - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ public void walkFileRevisions(Path file, Inspector inspector, int... changelogRevisionIndexes) throws HgRuntimeException { if (file == null || inspector == null || changelogRevisionIndexes == null) { @@ -349,9 +356,11 @@ * @param changesetRevIndex changeset revision index * @param file path to look up * @return one of predefined enum values, or null if file was not known in the specified revision - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - public Flags getFileFlags(int changesetRevIndex, Path file) throws HgInvalidRevisionException, HgInvalidControlFileException { + public Flags getFileFlags(int changesetRevIndex, Path file) throws HgRuntimeException { int manifestRevIdx = fromChangelog(changesetRevIndex); IntMap resMap = new IntMap(2); FileLookupInspector parser = new FileLookupInspector(encodingHelper, file, null, resMap); @@ -374,11 +383,11 @@ /** * @param changelogRevisionIndexes non-null * @param inspector may be null if reporting of missing manifests is not needed - * @throws HgInvalidRevisionException if arguments specify non-existent revision index - * @throws IllegalArgumentException if any index argument is not a revision index - * @throws HgInvalidControlFileException if access to revlog index/data entry failed + * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - private int[] toManifestRevisionIndexes(int[] changelogRevisionIndexes, Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { + private int[] toManifestRevisionIndexes(int[] changelogRevisionIndexes, Inspector inspector) throws HgRuntimeException { int[] manifestRevs = new int[changelogRevisionIndexes.length]; boolean needsSort = false; int j = 0; @@ -421,8 +430,9 @@ * @param manifestRevision revision of the manifest we're about to iterate through * @param changelogRevisionIndex local revision index of changelog this manifest points to * @return true to continue iteration, false to stop + * @throws HgRuntimeException propagates library issues. Runtime exception */ - boolean begin(int manifestRevisionIndex, Nodeid manifestRevision, int changelogRevisionIndex); + boolean begin(int manifestRevisionIndex, Nodeid manifestRevision, int changelogRevisionIndex) throws HgRuntimeException; /** @@ -432,16 +442,18 @@ * @param fname file name * @param flags one of {@link HgManifest.Flags} constants, not null * @return true to continue iteration, false to stop + * @throws HgRuntimeException propagates library issues. Runtime exception */ - boolean next(Nodeid nid, Path fname, Flags flags); + boolean next(Nodeid nid, Path fname, Flags flags) throws HgRuntimeException; /** * Denotes leaving specific manifest revision, after all entries were reported using {@link #next(Nodeid, Path, Flags)} * * @param manifestRevisionIndex indicates manifest revision, corresponds to opening {@link #begin(int, Nodeid, int)} * @return true to continue iteration, false to stop + * @throws HgRuntimeException propagates library issues. Runtime exception */ - boolean end(int manifestRevisionIndex); + boolean end(int manifestRevisionIndex) throws HgRuntimeException; } /** @@ -531,7 +543,7 @@ progressHelper = ProgressSupport.Factory.get(delegate); } - public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { + public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) throws HgRuntimeException { try { if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { iterateControl.stop(); @@ -623,7 +635,7 @@ private int[] changelog2manifest; RevisionLookup manifestNodeids; - private RevisionMapper(boolean useOwnRevisionLookup) { + private RevisionMapper(boolean useOwnRevisionLookup) throws HgRuntimeException { changelogRevisionCount = HgManifest.this.getRepo().getChangelog().getRevisionCount(); if (useOwnRevisionLookup) { manifestNodeids = new RevisionLookup(HgManifest.this.content); @@ -691,7 +703,7 @@ // #finish, as the manifest read operation is not complete at the moment. } - public void fixReusedManifests() { + public void fixReusedManifests() throws HgRuntimeException { if (changelog2manifest == null) { // direct, 1-1 mapping of changeset indexes to manifest return; @@ -768,15 +780,15 @@ csetIndex2Flags = null; } - void walk(int manifestRevIndex, RevlogStream content) { + void walk(int manifestRevIndex, RevlogStream content) throws HgRuntimeException { content.iterate(manifestRevIndex, manifestRevIndex, true, this); } - void walk(int[] manifestRevIndexes, RevlogStream content) { + void walk(int[] manifestRevIndexes, RevlogStream content) throws HgRuntimeException { content.iterate(manifestRevIndexes, true, this); } - public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { + public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException { ByteVector byteVector = new ByteVector(256, 128); // allocate for long paths right away try { byte b; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgMergeState.java --- a/src/org/tmatesoft/hg/repo/HgMergeState.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgMergeState.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -185,9 +185,7 @@ * @return true when recorded merge state doesn't seem to correspond to present working copy */ public boolean isStale() { - if (wcp1 == null) { - refresh(); - } + assert wcp1 != null; return !stateParent.isNull() /*there's merge state*/ && !wcp1.equals(stateParent) /*and it doesn't match*/; } @@ -198,9 +196,7 @@ * @return first parent of the working copy, never null */ public Nodeid getFirstParent() { - if (wcp1 == null) { - refresh(); - } + assert wcp1 != null; return wcp1; } @@ -208,9 +204,7 @@ * @return second parent of the working copy, never null */ public Nodeid getSecondParent() { - if (wcp2 == null) { - refresh(); - } + assert wcp2 != null; return wcp2; } @@ -218,9 +212,7 @@ * @return revision of the merge state or {@link Nodeid#NULL} if there's no merge state */ public Nodeid getStateParent() { - if (stateParent == null) { - refresh(); - } + assert stateParent != null; return stateParent; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgParentChildMap.java --- a/src/org/tmatesoft/hg/repo/HgParentChildMap.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgParentChildMap.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -88,7 +88,12 @@ } } - public void init() throws HgInvalidControlFileException { + /** + * Prepare the map + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception + */ + public void init() throws HgRuntimeException { final int revisionCount = revlog.getRevisionCount(); firstParent = new Nodeid[revisionCount]; // TODO [post 1.0] Branches/merges are less frequent, and most of secondParent would be -1/null, hence diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgRepository.java --- a/src/org/tmatesoft/hg/repo/HgRepository.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgRepository.java Wed May 22 15:52:31 2013 +0200 @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.List; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.core.SessionContext; import org.tmatesoft.hg.internal.ConfigFile; @@ -195,7 +196,7 @@ * * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public HgTags getTags() throws HgInvalidControlFileException { + public HgTags getTags() throws HgRuntimeException { if (tags == null) { tags = new HgTags(impl); tags.read(); @@ -212,7 +213,7 @@ * @return branch manager instance, never null * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public HgBranches getBranches() throws HgInvalidControlFileException { + public HgBranches getBranches() throws HgRuntimeException { final ProgressSupport ps = ProgressSupport.Factory.get(null); if (branches == null) { branches = new HgBranches(impl); @@ -226,10 +227,12 @@ /** * Access state of the recent merge * @return merge state facility, never null + * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public HgMergeState getMergeState() { + public HgMergeState getMergeState() throws HgRuntimeException { if (mergeState == null) { mergeState = new HgMergeState(impl); + mergeState.refresh(); } return mergeState; } @@ -305,7 +308,7 @@ try { ConfigFile configFile = impl.readConfiguration(); repoConfig = new HgRepoConfig(configFile); - } catch (IOException ex) { + } catch (HgIOException ex) { String m = "Errors while reading user configuration file"; getSessionContext().getLog().dump(getClass(), Warn, ex, m); return new HgRepoConfig(new ConfigFile(getSessionContext())); // empty config, do not cache, allow to try once again @@ -424,7 +427,7 @@ * @return facility to manage bookmarks, never null * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception */ - public HgBookmarks getBookmarks() throws HgInvalidControlFileException { + public HgBookmarks getBookmarks() throws HgRuntimeException { if (bookmarks == null) { bookmarks = new HgBookmarks(impl); bookmarks.read(); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgRevisionMap.java --- a/src/org/tmatesoft/hg/repo/HgRevisionMap.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgRevisionMap.java Wed May 22 15:52:31 2013 +0200 @@ -85,7 +85,7 @@ /** * @return this for convenience. */ - public HgRevisionMap init(/*XXX Pool to reuse nodeids, if possible. */) throws HgInvalidControlFileException{ + public HgRevisionMap init(/*XXX Pool to reuse nodeids, if possible. */) throws HgRuntimeException { // XXX HgRepository.register((RepoChangeListener) this); // listen to changes in repo, re-init if needed? final int revisionCount = revlog.getRevisionCount(); sequential = new Nodeid[revisionCount]; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgStatusCollector.java --- a/src/org/tmatesoft/hg/repo/HgStatusCollector.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgStatusCollector.java Wed May 22 15:52:31 2013 +0200 @@ -73,7 +73,7 @@ return repo; } - private ManifestRevision get(int rev) throws HgInvalidControlFileException { + private ManifestRevision get(int rev) throws HgRuntimeException { ManifestRevision i = cache.get(rev); if (i == null) { if (rev == NO_REVISION) { @@ -98,7 +98,7 @@ } } - private void initCacheRange(int minRev, int maxRev) throws HgInvalidControlFileException { + private void initCacheRange(int minRev, int maxRev) throws HgRuntimeException { ensureCacheSize(); // In fact, walk(minRev, maxRev) doesn't imply // there would be maxRev-minRev+1 revisions visited. For example, @@ -159,7 +159,7 @@ * @return * @throws HgInvalidControlFileException */ - /*package-local*/ ManifestRevision raw(int rev) throws HgInvalidControlFileException { + /*package-local*/ ManifestRevision raw(int rev) throws HgRuntimeException { return get(rev); } /*package-local*/ Convertor getPathPool() { @@ -344,9 +344,11 @@ * @param rev1 from changeset index * @param rev2 to changeset index * @return information object that describes change between the revisions - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if any supplied revision doesn't identify changeset revision. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - public Record status(int rev1, int rev2) throws HgInvalidRevisionException, HgInvalidControlFileException { + public Record status(int rev1, int rev2) throws HgRuntimeException { Record rv = new Record(); try { walk(rev1, rev2, rv); @@ -359,7 +361,7 @@ return rv; } - /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Collection originals, int originalChangelogRevision) throws HgInvalidFileException { + /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Collection originals, int originalChangelogRevision) throws HgRuntimeException { HgDataFile df = hgRepo.getFileNode(fname); if (!df.exists()) { String msg = String.format("Didn't find file '%s' in the repo. Perhaps, bad storage name conversion?", fname); @@ -417,7 +419,7 @@ statusHelper = self; } - public Nodeid nodeidBeforeChange(Path fname) throws HgInvalidControlFileException { + public Nodeid nodeidBeforeChange(Path fname) throws HgRuntimeException { if (statusHelper == null || startRev == BAD_REVISION) { return null; } @@ -426,7 +428,7 @@ } return statusHelper.raw(startRev).nodeid(fname); } - public Nodeid nodeidAfterChange(Path fname) throws HgInvalidControlFileException { + public Nodeid nodeidAfterChange(Path fname) throws HgRuntimeException { if (statusHelper == null || endRev == BAD_REVISION) { return null; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgTags.java --- a/src/org/tmatesoft/hg/repo/HgTags.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgTags.java Wed May 22 15:52:31 2013 +0200 @@ -74,13 +74,13 @@ localFromName = new TreeMap>(); } - /*package-local*/ void read() throws HgInvalidControlFileException { + /*package-local*/ void read() throws HgRuntimeException { readTagsFromHistory(); readGlobal(); readLocal(); } - private void readTagsFromHistory() throws HgInvalidControlFileException { + private void readTagsFromHistory() throws HgRuntimeException { HgDataFile hgTags = repo.getRepo().getFileNode(HgTags.getPath()); if (hgTags.exists()) { for (int i = 0; i <= hgTags.getLastRevision(); i++) { // TODO post-1.0 in fact, would be handy to have walk(start,end) @@ -280,7 +280,7 @@ } // can be called only after instance has been initialized (#read() invoked) - /*package-local*/void reloadIfChanged() throws HgInvalidControlFileException { + /*package-local*/void reloadIfChanged() throws HgRuntimeException { assert repoChangeMonitor != null; assert localTagsFileMonitor != null; assert globalTagsFileMonitor != null; @@ -312,7 +312,13 @@ return localFromName.containsKey(name); } - public String branch() throws HgInvalidControlFileException { + /** + * @return name of the branch this tag belongs to, never null + * @throws HgInvalidRevisionException if revision of the tag is not a valid changeset revision. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception + */ + public String branch() throws HgRuntimeException { if (branch == null) { int x = repo.getRepo().getChangelog().getRevisionIndex(revision()); branch = repo.getRepo().getChangelog().range(x, x).get(0).branch(); diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java --- a/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgWorkingCopyStatusCollector.java Wed May 22 15:52:31 2013 +0200 @@ -34,6 +34,7 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.core.SessionContext; import org.tmatesoft.hg.internal.ByteArrayChannel; +import org.tmatesoft.hg.internal.FileUtils; import org.tmatesoft.hg.internal.FilterByteChannel; import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.ManifestRevision; @@ -130,7 +131,7 @@ return dirstate; } - private ManifestRevision getManifest(int changelogLocalRev) throws HgInvalidControlFileException { + private ManifestRevision getManifest(int changelogLocalRev) throws HgRuntimeException { assert changelogLocalRev >= 0; ManifestRevision mr; if (baseRevisionCollector != null) { @@ -142,7 +143,7 @@ return mr; } - private void initDirstateParentManifest() throws HgInvalidControlFileException { + private void initDirstateParentManifest() throws HgRuntimeException { Nodeid dirstateParent = getDirstateImpl().parents().first(); if (dirstateParent.isNull()) { dirstateParentManifest = baseRevisionCollector != null ? baseRevisionCollector.raw(NO_REVISION) : HgStatusCollector.createEmptyManifestRevision(); @@ -407,7 +408,7 @@ } // XXX refactor checkLocalStatus methods in more OO way - private void checkLocalStatusAgainstBaseRevision(Set baseRevNames, ManifestRevision collect, int baseRevision, Path fname, FileInfo f, HgStatusInspector inspector) { + private void checkLocalStatusAgainstBaseRevision(Set baseRevNames, ManifestRevision collect, int baseRevision, Path fname, FileInfo f, HgStatusInspector inspector) throws HgRuntimeException { // fname is in the dirstate, either Normal, Added, Removed or Merged Nodeid nid1 = collect.nodeid(fname); HgManifest.Flags flags = collect.flags(fname); @@ -501,7 +502,7 @@ // The question is whether original Hg treats this case (same content, different parents and hence nodeids) as 'modified' or 'clean' } - private boolean areTheSame(FileInfo f, HgDataFile dataFile, Nodeid revision) throws HgInvalidFileException { + private boolean areTheSame(FileInfo f, HgDataFile dataFile, Nodeid revision) throws HgRuntimeException { // XXX consider adding HgDataDile.compare(File/byte[]/whatever) operation to optimize comparison ByteArrayChannel bac = new ByteArrayChannel(); try { @@ -588,13 +589,7 @@ } catch (IOException ex) { throw new HgInvalidFileException("File comparison failed", ex).setFileName(p); } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ex) { - repo.getSessionContext().getLog().dump(getClass(), Info, ex, null); - } - } + new FileUtils(repo.getSessionContext().getLog()).closeQuietly(is); } } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/Revlog.java --- a/src/org/tmatesoft/hg/repo/Revlog.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/Revlog.java Wed May 22 15:52:31 2013 +0200 @@ -94,7 +94,8 @@ /** * @return total number of revisions kept in this revlog - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ public final int getRevisionCount() throws HgRuntimeException { return content.revisionCount(); @@ -102,7 +103,8 @@ /** * @return index of last known revision, a.k.a. {@link HgRepository#TIP}, or {@link HgRepository#NO_REVISION} if revlog is empty - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ public final int getLastRevision() throws HgRuntimeException { // although old code gives correct result when revlog is empty (NO_REVISION deliberately == -1), @@ -117,7 +119,9 @@ * @param revisionIndex index of the entry in this revlog, may be {@link HgRepository#TIP} * @return revision nodeid of the entry * - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if any supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ public final Nodeid getRevision(int revisionIndex) throws HgRuntimeException { // XXX cache nodeids? Rather, if context.getCache(this).getRevisionMap(create == false) != null, use it @@ -130,7 +134,9 @@ *

  • ordering of the revisions in the return list is unspecified, it's likely won't match that of the method argument *
  • supplied array get modified (sorted) * @return list of mapped revisions in no particular order - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if any supplied revision doesn't identify revision from this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ public final List getRevisions(int... revisions) throws HgRuntimeException { ArrayList rv = new ArrayList(revisions.length); @@ -139,7 +145,7 @@ return rv; } - /*package-local*/ void getRevisionsInternal(final List retVal, int[] sortedRevs) throws HgInvalidRevisionException, HgInvalidControlFileException { + /*package-local*/ void getRevisionsInternal(final List retVal, int[] sortedRevs) throws HgRuntimeException { // once I have getRevisionMap and may find out whether it is avalable from cache, // may use it, perhaps only for small number of revisions content.iterate(sortedRevs, false, new RevlogStream.Inspector() { @@ -159,7 +165,9 @@ * * @param nid revision to look up * @return revision local index in this revlog - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidRevisionException if revision was not found in this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ public final int getRevisionIndex(Nodeid nid) throws HgRuntimeException { final int revision = doFindWithCache(nid); @@ -172,7 +180,7 @@ return revision; } - private int doFindWithCache(Nodeid nid) { + private int doFindWithCache(Nodeid nid) throws HgRuntimeException { if (useRevisionLookup) { if (revisionLookup == null || content.shallDropDerivedCaches()) { content.detach(revisionLookupCleaner); @@ -199,7 +207,8 @@ * * @param nodeid * @return true if revision is part of this revlog - * @throws HgRuntimeException subclass thereof to indicate issues with the library. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ public final boolean isKnown(Nodeid nodeid) throws HgRuntimeException { final int rn = doFindWithCache(nodeid); @@ -219,13 +228,14 @@ * @param nodeid revision to retrieve * @param sink data destination * - * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog - * @throws HgInvalidControlFileException if access to revlog index/data entry failed + * @see #rawContent(int, ByteChannel) + * * @throws CancelledException if content retrieval operation was cancelled - * - * @see #rawContent(int, ByteChannel) + * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - protected void rawContent(Nodeid nodeid, ByteChannel sink) throws HgInvalidControlFileException, CancelledException, HgInvalidRevisionException { + protected void rawContent(Nodeid nodeid, ByteChannel sink) throws CancelledException, HgRuntimeException { rawContent(getRevisionIndex(nodeid), sink); } @@ -235,11 +245,12 @@ * @param revisionIndex index of this revlog change (not a changelog revision index), non-negative. From predefined constants, only {@link HgRepository#TIP} makes sense. * @param sink data destination * - * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog - * @throws HgInvalidControlFileException if access to revlog index/data entry failed * @throws CancelledException if content retrieval operation was cancelled + * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog. Runtime exception + * @throws HgInvalidControlFileException if failed to access revlog index/data entry. Runtime exception + * @throws HgRuntimeException subclass thereof to indicate other issues with the library. Runtime exception */ - protected void rawContent(int revisionIndex, ByteChannel sink) throws HgInvalidControlFileException, CancelledException, HgInvalidRevisionException { + protected void rawContent(int revisionIndex, ByteChannel sink) throws CancelledException, HgRuntimeException { if (sink == null) { throw new IllegalArgumentException(); } @@ -348,7 +359,7 @@ content.iterate(_start, end, false, new RevlogStream.Inspector() { private int i = 0; - public void next(int revisionIndex, int actualLen, int baseRevIndex, int linkRevIndex, int parent1RevIndex, int parent2RevIndex, byte[] nodeid, DataAccess data) { + public void next(int revisionIndex, int actualLen, int baseRevIndex, int linkRevIndex, int parent1RevIndex, int parent2RevIndex, byte[] nodeid, DataAccess data) throws HgRuntimeException { Nodeid nid = Nodeid.fromBinary(nodeid, 0); if (revisionInsp != null) { revisionInsp.next(revisionIndex, nid, linkRevIndex); @@ -417,16 +428,16 @@ @Experimental public interface RevisionInspector extends Inspector { - void next(int revisionIndex, Nodeid revision, int linkedRevisionIndex); + void next(int revisionIndex, Nodeid revision, int linkedRevisionIndex) throws HgRuntimeException; } @Experimental public interface ParentInspector extends Inspector { // XXX document whether parentX is -1 or a constant (BAD_REVISION? or dedicated?) - void next(int revisionIndex, Nodeid revision, int parent1, int parent2, Nodeid nidParent1, Nodeid nidParent2); + void next(int revisionIndex, Nodeid revision, int parent1, int parent2, Nodeid nidParent1, Nodeid nidParent2) throws HgRuntimeException; } - protected HgParentChildMap getParentWalker() { + protected HgParentChildMap getParentWalker() throws HgRuntimeException { HgParentChildMap pw = new HgParentChildMap(this); pw.init(); return pw; diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/ext/MqManager.java --- a/src/org/tmatesoft/hg/repo/ext/MqManager.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/ext/MqManager.java Wed May 22 15:52:31 2013 +0200 @@ -27,11 +27,11 @@ import java.util.List; import java.util.Map; +import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.LineReader; import org.tmatesoft.hg.repo.HgInvalidControlFileException; -import org.tmatesoft.hg.repo.HgInvalidFileException; import org.tmatesoft.hg.util.LogFacility; import org.tmatesoft.hg.util.Path; @@ -136,10 +136,8 @@ allKnown.add(pr); } } - } catch (HgInvalidFileException ex) { - HgInvalidControlFileException th = new HgInvalidControlFileException(ex.getMessage(), ex.getCause(), ex.getFile()); - th.setStackTrace(ex.getStackTrace()); - throw th; + } catch (HgIOException ex) { + throw new HgInvalidControlFileException(ex, true); } return this; } diff -r 5153eb73b18d -r 6526d8adbc0f src/org/tmatesoft/hg/repo/ext/Rebase.java --- a/src/org/tmatesoft/hg/repo/ext/Rebase.java Tue May 21 20:17:33 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/ext/Rebase.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 TMate Software Ltd + * Copyright (c) 2012-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,6 @@ import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.LineReader; -import org.tmatesoft.hg.repo.HgInvalidFileException; import org.tmatesoft.hg.repo.HgInvalidStateException; /** @@ -94,8 +93,6 @@ throw new HgIOException("Bad format of rebase state file", f); } catch (HgBadNodeidFormatException ex) { throw new HgIOException("Bad format of rebase state file", ex, f); - } catch (HgInvalidFileException ex) { - throw new HgIOException("Bad format of rebase state file", ex, f); } return this; } diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java --- a/test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java Wed May 22 15:52:31 2013 +0200 @@ -26,6 +26,7 @@ import org.tmatesoft.hg.repo.HgManifest; import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.repo.HgTags; import org.tmatesoft.hg.repo.HgTags.TagInfo; import org.tmatesoft.hg.repo.HgRevisionMap; @@ -160,7 +161,7 @@ final Map changesetToNodeid_3 = new HashMap(); fileNode.indexWalk(0, TIP, new HgDataFile.RevisionInspector() { - public void next(int fileRevisionIndex, Nodeid revision, int linkedRevisionIndex) { + public void next(int fileRevisionIndex, Nodeid revision, int linkedRevisionIndex) throws HgRuntimeException { changesetToNodeid_3.put(clog.getRevision(linkedRevisionIndex), revision); } }); @@ -273,7 +274,7 @@ return tagLocalRevs; } - public void collectTagsPerFile() throws HgException, CancelledException { + public void collectTagsPerFile() throws HgException, CancelledException, HgRuntimeException { final long start = System.currentTimeMillis(); final HgRepository repository = new HgLookup().detect(new File("/home/artem/hg/cpython")); final HgTags tags = repository.getTags(); @@ -301,7 +302,7 @@ // Approach 1. Build map with all files, their revisions and corresponding tags // - private void collectTagsPerFile_Approach_1(final HgRevisionMap clogrmap, final int[] tagLocalRevs, final TagInfo[] allTags, Path targetPath) throws HgException { + private void collectTagsPerFile_Approach_1(final HgRevisionMap clogrmap, final int[] tagLocalRevs, final TagInfo[] allTags, Path targetPath) throws HgException, IllegalArgumentException, HgRuntimeException { HgRepository repository = clogrmap.getRepo(); final long start = System.currentTimeMillis(); // file2rev2tag value is array of revisions, always of allTags.length. Revision index in the array @@ -373,7 +374,7 @@ } } - private void collectTagsPerFile_Approach_2(HgRepository repository, final int[] tagLocalRevs, final IntMap> tagRevIndex2TagInfo, Path targetPath) throws HgException { + private void collectTagsPerFile_Approach_2(HgRepository repository, final int[] tagLocalRevs, final IntMap> tagRevIndex2TagInfo, Path targetPath) throws HgException, HgRuntimeException { // // Approach 2. No all-file map. Collect file revisions recorded at the time of tagging, // then for each file revision check if it is among those above, and if yes, take corresponding tags @@ -457,7 +458,7 @@ } } - public static void main2(String[] args) throws HgCallbackTargetException, HgException, CancelledException { + public static void main2(String[] args) throws HgCallbackTargetException, HgException, CancelledException, HgRuntimeException { final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); final Path targetPath = Path.create("README"); final HgTags tags = repository.getTags(); diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/TestAuxUtilities.java --- a/test/org/tmatesoft/hg/test/TestAuxUtilities.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestAuxUtilities.java Wed May 22 15:52:31 2013 +0200 @@ -41,6 +41,7 @@ import org.tmatesoft.hg.repo.HgManifest; import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Adaptable; import org.tmatesoft.hg.util.ByteChannel; import org.tmatesoft.hg.util.CancelSupport; @@ -285,7 +286,7 @@ fileNode.indexWalk(0, TIP, new HgDataFile.RevisionInspector() { int i = 0; - public void next(int localRevision, Nodeid revision, int linkedRevision) { + public void next(int localRevision, Nodeid revision, int linkedRevision) throws HgRuntimeException { assertEquals(i++, localRevision); assertEquals(fileNode.getChangesetRevisionIndex(localRevision), linkedRevision); assertEquals(fileNode.getRevision(localRevision), revision); diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/TestBlame.java --- a/test/org/tmatesoft/hg/test/TestBlame.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestBlame.java Wed May 22 15:52:31 2013 +0200 @@ -277,7 +277,7 @@ // String[] apiResult = splitLines(bos.toString()); String[] expected = splitLines(gp.result()); - Assert.assertArrayEquals(expected, apiResult); + Assert.assertArrayEquals("diff -r " + cs + " - r 8", expected, apiResult); gp.reset(); } } diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/TestCommit.java --- a/test/org/tmatesoft/hg/test/TestCommit.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestCommit.java Wed May 22 15:52:31 2013 +0200 @@ -37,9 +37,8 @@ import org.tmatesoft.hg.internal.ByteArrayChannel; import org.tmatesoft.hg.internal.COWTransaction; import org.tmatesoft.hg.internal.CommitFacility; +import org.tmatesoft.hg.internal.DataSerializer.ByteArrayDataSource; import org.tmatesoft.hg.internal.DirstateReader; -import org.tmatesoft.hg.internal.DataSerializer.ByteArrayDataSource; -import org.tmatesoft.hg.internal.FileChangeMonitor; import org.tmatesoft.hg.internal.FileContentSupplier; import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.internal.Transaction; diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/TestFileFlags.java --- a/test/org/tmatesoft/hg/test/TestFileFlags.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestFileFlags.java Wed May 22 15:52:31 2013 +0200 @@ -30,6 +30,7 @@ import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.FileInfo; import org.tmatesoft.hg.util.FileWalker; import org.tmatesoft.hg.util.Path; @@ -52,7 +53,7 @@ private HgRepository repo; @Test - public void testFlagsInManifest() { + public void testFlagsInManifest() throws HgRuntimeException { HgDataFile link = repo.getFileNode("file-link"); HgDataFile exec = repo.getFileNode("file-exec"); HgDataFile file = repo.getFileNode("regular-file"); diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/TestHistory.java --- a/test/org/tmatesoft/hg/test/TestHistory.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestHistory.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,6 +45,7 @@ import org.tmatesoft.hg.internal.AdapterPlug; import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.test.LogOutputParser.Record; import org.tmatesoft.hg.util.Adaptable; import org.tmatesoft.hg.util.CancelSupport; @@ -626,7 +627,7 @@ } - public void treeElement(TreeElement entry) throws HgCallbackTargetException { + public void treeElement(TreeElement entry) throws HgCallbackTargetException, HgRuntimeException { // check consistency Nodeid cset = entry.changeset().getNodeid(); errorCollector.assertEquals(entry.changesetRevision(), cset); diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/TestPhases.java --- a/test/org/tmatesoft/hg/test/TestPhases.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestPhases.java Wed May 22 15:52:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 TMate Software Ltd + * Copyright (c) 2012-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgPhase; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; /** * {hg4j.tests.repos}/test-phases/ @@ -67,7 +68,7 @@ System.out.printf("With ParentWalker(simulates log command for whole repo): %,d μs (pw init: %,d ns)\n", (end - start1)/1000, start2 - start1); } - private HgPhase[] initAndCheck(PhasesHelper ph, HgPhase[] expected) { + private HgPhase[] initAndCheck(PhasesHelper ph, HgPhase[] expected) throws HgRuntimeException { HgChangelog clog = ph.getRepo().getChangelog(); HgPhase[] result = new HgPhase[clog.getRevisionCount()]; for (int i = 0, l = clog.getLastRevision(); i <= l; i++) { diff -r 5153eb73b18d -r 6526d8adbc0f test/org/tmatesoft/hg/test/TestRevlog.java --- a/test/org/tmatesoft/hg/test/TestRevlog.java Tue May 21 20:17:33 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestRevlog.java Wed May 22 15:52:31 2013 +0200 @@ -33,6 +33,7 @@ import org.tmatesoft.hg.repo.HgManifest; import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.Path; /** @@ -187,7 +188,7 @@ return patch1; } - private byte[] getRevisionTrueContent(File repoLoc, final int manifestRev, int clogRev) throws HgRepositoryNotFoundException { + private byte[] getRevisionTrueContent(File repoLoc, final int manifestRev, int clogRev) throws HgRepositoryNotFoundException, IllegalArgumentException, HgRuntimeException { HgRepository hgRepo = new HgLookup().detect(repoLoc); final ByteArrayOutputStream out = new ByteArrayOutputStream(1024 * 1000); hgRepo.getManifest().walk(clogRev, clogRev, new HgManifest.Inspector() {