Merge branch 'stable-4.6' into stable-4.7

* stable-4.6:
  Prepare 4.5.8-SNAPSHOT builds
  JGit v4.5.7.201904151645-r
  Remember the cause for invalidating a packfile
  Fix API problem filters
  Fix pack files scan when filesnapshot isn't modified

Change-Id: I6ea51dde6608a4163d681aa1ebf710f06da44b21
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index 9fa97b4..ef81a33 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -3,11 +3,25 @@
     <resource path="META-INF/MANIFEST.MF">
         <filter id="924844039">
             <message_arguments>
-                <message_argument value="4.7.8"/>
+                <message_argument value="4.7.9"/>
                 <message_argument value="4.7.0"/>
             </message_arguments>
         </filter>
     </resource>
+    <resource path="src/org/eclipse/jgit/errors/PackInvalidException.java" type="org.eclipse.jgit.errors.PackInvalidException">
+        <filter id="1142947843">
+            <message_arguments>
+                <message_argument value="4.5.7"/>
+                <message_argument value="PackInvalidException(File, Throwable)"/>
+            </message_arguments>
+        </filter>
+        <filter id="1142947843">
+            <message_arguments>
+                <message_argument value="4.5.7"/>
+                <message_argument value="PackInvalidException(String, Throwable)"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
         <filter id="336658481">
             <message_arguments>
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 8c216c3..09be9ec 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 @@
 	 *
 	 * @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 @@
 	 *
 	 * @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 f15d427..4586370 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 @@
 	/** 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}.
 	 * <p>
@@ -235,8 +238,9 @@
 				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 @@
 				}
 			} catch (EOFException e) {
 				invalid = true;
+				invalidatingCause = e;
 				IOException e2 = new IOException(MessageFormat.format(
 						DfsText.get().shortReadOfIndex,
 						packDesc.getFileName(INDEX)));
@@ -274,6 +279,7 @@
 				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 @@
 
 	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 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 e1934a1..acd4677 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 @@
 
 	private final File alternatesFile;
 
-	private final AtomicReference<PackList> packList;
-
 	private final FS fs;
 
 	private final AtomicReference<AlternateHandle[]> alternates;
@@ -143,6 +141,8 @@
 
 	private Set<ObjectId> shallowCommitsIds;
 
+	final AtomicReference<PackList> packList;
+
 	/**
 	 * Initialize a reference to an on-disk object directory.
 	 *
@@ -595,13 +595,8 @@
 			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 @@
 		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 @@
 			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 @@
 		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 e7db11d..c4e0d66 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 @@
 
 	private volatile boolean invalid;
 
+	private volatile Exception invalidatingCause;
+
 	private boolean invalidBitmap;
 
 	private AtomicInteger transientErrorCount = new AtomicInteger();
@@ -179,8 +181,9 @@
 
 	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 @@
 				throw e;
 			} catch (IOException e) {
 				invalid = true;
+				invalidatingCause = e;
 				throw e;
 			}
 		}
@@ -647,7 +651,7 @@
 
 	private void doOpen() throws IOException {
 		if (invalid) {
-			throw new PackInvalidException(packFile);
+			throw new PackInvalidException(packFile, invalidatingCause);
 		}
 		try {
 			synchronized (readLock) {
@@ -657,13 +661,13 @@
 			}
 		} 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 @@
 				| 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 @@
 				// 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);