diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters index 9fa97b4e2..ef81a33f4 100644 --- a/org.eclipse.jgit/.settings/.api_filters +++ b/org.eclipse.jgit/.settings/.api_filters @@ -3,11 +3,25 @@ - + + + + + + + + + + + + + + + diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java index 8c216c3d4..09be9ec34 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java @@ -58,9 +58,24 @@ public class PackInvalidException extends IOException { * * @param path * path of the invalid pack file. + * @deprecated Use {@link #PackInvalidException(File, Throwable)}. */ + @Deprecated public PackInvalidException(final File path) { - this(path.getAbsolutePath()); + this(path, null); + } + + /** + * Construct a pack invalid error with cause. + * + * @param path + * path of the invalid pack file. + * @param cause + * cause of the pack file becoming invalid. + * @since 4.5.7 + */ + public PackInvalidException(final File path, Throwable cause) { + this(path.getAbsolutePath(), cause); } /** @@ -68,8 +83,23 @@ public PackInvalidException(final File path) { * * @param path * path of the invalid pack file. + * @deprecated Use {@link #PackInvalidException(String, Throwable)}. */ + @Deprecated public PackInvalidException(final String path) { - super(MessageFormat.format(JGitText.get().packFileInvalid, path)); + this(path, null); + } + + /** + * Construct a pack invalid error with cause. + * + * @param path + * path of the invalid pack file. + * @param cause + * cause of the pack file becoming invalid. + * @since 4.5.7 + */ + public PackInvalidException(final String path, Throwable cause) { + super(MessageFormat.format(JGitText.get().packFileInvalid, path), cause); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java index f15d427f8..4586370d6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java @@ -135,6 +135,9 @@ public final class DfsPackFile { /** True once corruption has been detected that cannot be worked around. */ private volatile boolean invalid; + /** Exception that caused the packfile to be flagged as invalid */ + private volatile Exception invalidatingCause; + /** * Lock for initialization of {@link #index} and {@link #corruptObjects}. *

@@ -235,8 +238,9 @@ private PackIndex idx(DfsReader ctx) throws IOException { return idx; } - if (invalid) - throw new PackInvalidException(getPackName()); + if (invalid) { + throw new PackInvalidException(getPackName(), invalidatingCause); + } Repository.getGlobalListenerList() .dispatch(new BeforeDfsPackIndexLoadedEvent(this)); @@ -267,6 +271,7 @@ else if (bs <= 0) } } catch (EOFException e) { invalid = true; + invalidatingCause = e; IOException e2 = new IOException(MessageFormat.format( DfsText.get().shortReadOfIndex, packDesc.getFileName(INDEX))); @@ -274,6 +279,7 @@ else if (bs <= 0) throw e2; } catch (IOException e) { invalid = true; + invalidatingCause = e; IOException e2 = new IOException(MessageFormat.format( DfsText.get().cannotReadIndex, packDesc.getFileName(INDEX))); @@ -751,8 +757,10 @@ void setInvalid() { private IOException packfileIsTruncated() { invalid = true; - return new IOException(MessageFormat.format( + IOException exc = new IOException(MessageFormat.format( JGitText.get().packfileIsTruncated, getPackName())); + invalidatingCause = exc; + return exc; } private void readFully(long position, byte[] dstbuf, int dstoff, int cnt, @@ -774,8 +782,9 @@ DfsBlock getOrLoadBlock(long pos, DfsReader ctx) throws IOException { DfsBlock readOneBlock(long pos, DfsReader ctx) throws IOException { - if (invalid) - throw new PackInvalidException(getPackName()); + if (invalid) { + throw new PackInvalidException(getPackName(), invalidatingCause); + } ReadableChannel rc = ctx.db.openFile(packDesc, PACK); try { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java index e1934a13d..acd467751 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java @@ -129,8 +129,6 @@ public class ObjectDirectory extends FileObjectDatabase { private final File alternatesFile; - private final AtomicReference packList; - private final FS fs; private final AtomicReference alternates; @@ -143,6 +141,8 @@ public class ObjectDirectory extends FileObjectDatabase { private Set shallowCommitsIds; + final AtomicReference packList; + /** * Initialize a reference to an on-disk object directory. * @@ -595,13 +595,8 @@ private void handlePackError(IOException e, PackFile p) { transientErrorCount = p.incrementTransientErrorCount(); } if (warnTmpl != null) { - if (LOG.isDebugEnabled()) { - LOG.debug(MessageFormat.format(warnTmpl, - p.getPackFile().getAbsolutePath()), e); - } else { - LOG.warn(MessageFormat.format(warnTmpl, - p.getPackFile().getAbsolutePath())); - } + LOG.warn(MessageFormat.format(warnTmpl, + p.getPackFile().getAbsolutePath()), e); } else { if (doLogExponentialBackoff(transientErrorCount)) { // Don't remove the pack from the list, as the error may be @@ -688,7 +683,7 @@ InsertLooseObjectResult insertUnpackedObject(File tmp, ObjectId id, return InsertLooseObjectResult.FAILURE; } - private boolean searchPacksAgain(PackList old) { + boolean searchPacksAgain(PackList old) { // Whether to trust the pack folder's modification time. If set // to false we will always scan the .git/objects/pack folder to // check for new pack files. If set to true (default) we use the @@ -843,7 +838,8 @@ private PackList scanPacksImpl(final PackList old) { final String packName = base + PACK.getExtension(); final File packFile = new File(packDirectory, packName); final PackFile oldPack = forReuse.remove(packName); - if (oldPack != null && oldPack.getFileSnapshot().isModified(packFile)) { + if (oldPack != null + && !oldPack.getFileSnapshot().isModified(packFile)) { list.add(oldPack); continue; } @@ -982,7 +978,7 @@ public File fileFor(AnyObjectId objectId) { return new File(new File(getDirectory(), d), f); } - private static final class PackList { + static final class PackList { /** State just before reading the pack directory. */ final FileSnapshot snapshot; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java index e7db11d08..c4e0d66c3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java @@ -135,6 +135,8 @@ public int compare(final PackFile a, final PackFile b) { private volatile boolean invalid; + private volatile Exception invalidatingCause; + private boolean invalidBitmap; private AtomicInteger transientErrorCount = new AtomicInteger(); @@ -179,8 +181,9 @@ public PackFile(final File packFile, int extensions) { private synchronized PackIndex idx() throws IOException { if (loadedIdx == null) { - if (invalid) - throw new PackInvalidException(packFile); + if (invalid) { + throw new PackInvalidException(packFile, invalidatingCause); + } try { final PackIndex idx = PackIndex.open(extFile(INDEX)); @@ -198,6 +201,7 @@ private synchronized PackIndex idx() throws IOException { throw e; } catch (IOException e) { invalid = true; + invalidatingCause = e; throw e; } } @@ -647,7 +651,7 @@ synchronized boolean endWindowCache() { private void doOpen() throws IOException { if (invalid) { - throw new PackInvalidException(packFile); + throw new PackInvalidException(packFile, invalidatingCause); } try { synchronized (readLock) { @@ -657,13 +661,13 @@ private void doOpen() throws IOException { } } catch (InterruptedIOException e) { // don't invalidate the pack, we are interrupted from another thread - openFail(false); + openFail(false, e); throw e; } catch (FileNotFoundException fn) { // don't invalidate the pack if opening an existing file failed // since it may be related to a temporary lack of resources (e.g. // max open files) - openFail(!packFile.exists()); + openFail(!packFile.exists(), fn); throw fn; } catch (EOFException | AccessDeniedException | NoSuchFileException | CorruptObjectException | NoPackSignatureException @@ -671,20 +675,21 @@ private void doOpen() throws IOException { | UnsupportedPackIndexVersionException | UnsupportedPackVersionException pe) { // exceptions signaling permanent problems with a pack - openFail(true); + openFail(true, pe); throw pe; } catch (IOException | RuntimeException ge) { // generic exceptions could be transient so we should not mark the // pack invalid to avoid false MissingObjectExceptions - openFail(false); + openFail(false, ge); throw ge; } } - private void openFail(boolean invalidate) { + private void openFail(boolean invalidate, Exception cause) { activeWindows = 0; activeCopyRawData = 0; invalid = invalidate; + invalidatingCause = cause; doClose(); } @@ -711,7 +716,7 @@ ByteArrayWindow read(final long pos, int size) throws IOException { // Detect the situation and throw a proper exception so that can be properly // managed by the main packfile search loop and the Git client won't receive // any failures. - throw new PackInvalidException(packFile); + throw new PackInvalidException(packFile, invalidatingCause); } if (length < pos + size) size = (int) (length - pos);