Merge branch 'stable-4.5' into stable-4.6

* stable-4.5:
  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: I0b4eaa521ebdea83ab18c05915d691c07a575a7d
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 c74a500..4a2663b 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -17,6 +17,20 @@
             </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/errors/UnsupportedPackIndexVersionException.java" type="org.eclipse.jgit.errors.UnsupportedPackIndexVersionException">
         <filter id="1108344834">
             <message_arguments>
@@ -65,22 +79,6 @@
                 <message_argument value="supportsAtomicCreateNewFile()"/>
             </message_arguments>
         </filter>
-        <filter id="924844039">
-            <message_arguments>
-                <message_argument value="4.5.6"/>
-                <message_argument value="4.5.0"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
-        <filter id="336658481">
-            <message_arguments>
-                <message_argument value="org.eclipse.jgit.lib.ConfigConstants"/>
-                <message_argument value="CONFIG_KEY_SUPPORTSATOMICFILECREATION"/>
-            </message_arguments>
-        </filter>
-    </resource>
-    <resource path="src/org/eclipse/jgit/util/FS.java" type="org.eclipse.jgit.util.FS">
         <filter id="1142947843">
             <message_arguments>
                 <message_argument value="4.5.6"/>
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 4eabb03..f845453 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>
@@ -236,8 +239,9 @@
 				return idx;
 		}
 
-		if (invalid)
-			throw new PackInvalidException(getPackName());
+		if (invalid) {
+			throw new PackInvalidException(getPackName(), invalidatingCause);
+		}
 
 		Repository.getGlobalListenerList()
 				.dispatch(new BeforeDfsPackIndexLoadedEvent(this));
@@ -268,6 +272,7 @@
 				}
 			} catch (EOFException e) {
 				invalid = true;
+				invalidatingCause = e;
 				IOException e2 = new IOException(MessageFormat.format(
 						DfsText.get().shortReadOfIndex,
 						packDesc.getFileName(INDEX)));
@@ -275,6 +280,7 @@
 				throw e2;
 			} catch (IOException e) {
 				invalid = true;
+				invalidatingCause = e;
 				IOException e2 = new IOException(MessageFormat.format(
 						DfsText.get().cannotReadIndex,
 						packDesc.getFileName(INDEX)));
@@ -743,8 +749,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,
@@ -766,8 +774,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 44ad99b..019d3ed 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
@@ -127,8 +127,6 @@
 
 	private final File alternatesFile;
 
-	private final AtomicReference<PackList> packList;
-
 	private final FS fs;
 
 	private final AtomicReference<AlternateHandle[]> alternates;
@@ -141,6 +139,8 @@
 
 	private Set<ObjectId> shallowCommitsIds;
 
+	final AtomicReference<PackList> packList;
+
 	/**
 	 * Initialize a reference to an on-disk object directory.
 	 *
@@ -581,13 +581,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
@@ -674,7 +669,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
@@ -822,7 +817,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;
 			}
@@ -960,7 +956,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 7a51a5a..f49e57d 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
@@ -133,6 +133,8 @@
 
 	private volatile boolean invalid;
 
+	private volatile Exception invalidatingCause;
+
 	private boolean invalidBitmap;
 
 	private AtomicInteger transientErrorCount = new AtomicInteger();
@@ -177,8 +179,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));
@@ -196,6 +199,7 @@
 				throw e;
 			} catch (IOException e) {
 				invalid = true;
+				invalidatingCause = e;
 				throw e;
 			}
 		}
@@ -644,7 +648,7 @@
 
 	private void doOpen() throws IOException {
 		if (invalid) {
-			throw new PackInvalidException(packFile);
+			throw new PackInvalidException(packFile, invalidatingCause);
 		}
 		try {
 			synchronized (readLock) {
@@ -654,13 +658,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
@@ -668,20 +672,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();
 	}
 
@@ -708,7 +713,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);