Merge branch 'stable-5.4' into stable-5.5

* stable-5.4:
  Prepare 5.3.9-SNAPSHOT builds
  JGit v5.3.8.202011260953-r
  Prepare 5.1.15-SNAPSHOT builds
  JGit v5.1.14.202011251942-r
  GC#deleteOrphans: log warning for deleted orphaned files
  GC#deleteOrphans: handle failure to list files in pack directory
  Ensure that GC#deleteOrphans respects pack lock
  Update API warning filters
  Remove unused imports

Change-Id: Icc34f809a3bb019d8d640b9bdb71363e617942e2
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
new file mode 100644
index 0000000..b75b3d5
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/feature.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.jgit.pgm.source"
+      label="%featureName"
+      version="5.3.9.qualifier"
+      provider-name="%providerName">
+
+   <description url="http://www.eclipse.org/jgit/">
+     %description
+   </description>
+
+   <copyright>
+     %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+     %license
+   </license>
+
+   <url>
+      <update label="%updateSiteName" url="http://download.eclipse.org/egit/updates"/>
+      <discovery label="%updateSiteName" url="http://download.eclipse.org/egit/updates"/>
+   </url>
+
+   <plugin
+         id="org.eclipse.jgit.pgm.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+</feature>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
new file mode 100644
index 0000000..6c1b30b
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.source.feature/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (C) 2012, Matthias Sohn <matthias.sohn@sap.com>
+   and other copyright owners as documented in the project's IP log.
+
+   This program and the accompanying materials are made available
+   under the terms of the Eclipse Distribution License v1.0 which
+   accompanies this distribution, is reproduced below, and is
+   available at http://www.eclipse.org/org/documents/edl-v10.php
+
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or
+   without modification, are permitted provided that the following
+   conditions are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above
+     copyright notice, this list of conditions and the following
+     disclaimer in the documentation and/or other materials provided
+     with the distribution.
+
+   - Neither the name of the Eclipse Foundation, Inc. nor the
+     names of its contributors may be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.eclipse.jgit</groupId>
+    <artifactId>jgit.tycho.parent</artifactId>
+    <version>5.3.9-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.eclipse.jgit.feature</groupId>
+  <artifactId>org.eclipse.jgit.pgm.source</artifactId>
+  <packaging>eclipse-feature</packaging>
+
+  <name>JGit Command Line Interface Source Feature</name>
+
+</project>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/feature.xml
new file mode 100644
index 0000000..54e81e9
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/feature.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+      id="org.eclipse.jgit.ssh.apache.source"
+      label="%featureName"
+      version="5.3.9.qualifier"
+      provider-name="%providerName">
+
+   <description url="http://www.eclipse.org/jgit/">
+     %description
+   </description>
+
+   <copyright>
+     %copyright
+   </copyright>
+
+   <license url="%licenseURL">
+     %license
+   </license>
+
+   <url>
+      <update label="%updateSiteName" url="http://download.eclipse.org/egit/updates"/>
+      <discovery label="%updateSiteName" url="http://download.eclipse.org/egit/updates"/>
+   </url>
+
+   <plugin
+         id="org.eclipse.jgit.ssh.apache.source"
+         download-size="0"
+         install-size="0"
+         version="0.0.0"
+         unpack="false"/>
+</feature>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/pom.xml
new file mode 100644
index 0000000..017aef7
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.source.feature/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (C) 2018 Thomas Wolf <thomas.wolf@paranor.ch>
+   and other copyright owners as documented in the project's IP log.
+
+   This program and the accompanying materials are made available
+   under the terms of the Eclipse Distribution License v1.0 which
+   accompanies this distribution, is reproduced below, and is
+   available at http://www.eclipse.org/org/documents/edl-v10.php
+
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or
+   without modification, are permitted provided that the following
+   conditions are met:
+
+   - Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above
+     copyright notice, this list of conditions and the following
+     disclaimer in the documentation and/or other materials provided
+     with the distribution.
+
+   - Neither the name of the Eclipse Foundation, Inc. nor the
+     names of its contributors may be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.eclipse.jgit</groupId>
+    <artifactId>jgit.tycho.parent</artifactId>
+    <version>5.3.9-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.eclipse.jgit.feature</groupId>
+  <artifactId>org.eclipse.jgit.ssh.apache.source</artifactId>
+  <packaging>eclipse-feature</packaging>
+
+  <name>JGit Apache MINA ssh Source Feature</name>
+
+</project>
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
index 5a5ae1d..858f5b9 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java
@@ -19,7 +19,6 @@
 import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
-import org.eclipse.jgit.internal.storage.dfs.DfsRefDatabase;
 import org.eclipse.jgit.internal.storage.reftable.RefCursor;
 import org.eclipse.jgit.internal.storage.reftable.ReftableConfig;
 import org.eclipse.jgit.internal.storage.reftable.ReftableReader;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java
index 79d72c5..e54c4ad 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcOrphanFilesTest.java
@@ -57,11 +57,15 @@
 
 	private final static String BITMAP_File_1 = PACK + "-1.bitmap";
 
-	private final static String IDX_File_2 = PACK + "-2.idx";
+	private static final String BITMAP_File_2 = PACK + "-2.bitmap";
+
+	private static final String IDX_File_2 = PACK + "-2.idx";
 
 	private final static String IDX_File_malformed = PACK + "-1234idx";
 
-	private final static String PACK_File_2 = PACK + "-2.pack";
+	private static final String KEEP_File_2 = PACK + "-2.keep";
+
+	private static final String PACK_File_2 = PACK + "-2.pack";
 
 	private final static String PACK_File_3 = PACK + "-3.pack";
 
@@ -105,6 +109,22 @@
 		assertTrue(new File(packDir, IDX_File_malformed).exists());
 	}
 
+	@Test
+	public void keepPreventsDeletionOfIndexFilesForMissingPackFile()
+			throws Exception {
+		createFileInPackFolder(BITMAP_File_1);
+		createFileInPackFolder(IDX_File_2);
+		createFileInPackFolder(BITMAP_File_2);
+		createFileInPackFolder(KEEP_File_2);
+		createFileInPackFolder(PACK_File_3);
+		gc.gc();
+		assertFalse(new File(packDir, BITMAP_File_1).exists());
+		assertTrue(new File(packDir, BITMAP_File_2).exists());
+		assertTrue(new File(packDir, IDX_File_2).exists());
+		assertTrue(new File(packDir, KEEP_File_2).exists());
+		assertTrue(new File(packDir, PACK_File_3).exists());
+	}
+
 	private void createFileInPackFolder(String fileName) throws IOException {
 		if (!packDir.exists() || !packDir.isDirectory()) {
 			assertTrue(packDir.mkdirs());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StatsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StatsTest.java
index 8b25382..0303bb4 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StatsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StatsTest.java
@@ -45,7 +45,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import org.eclipse.jgit.util.Stats;
 import org.junit.Test;
 
 public class StatsTest {
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index 52359d1..14ab51c 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -214,6 +214,7 @@
 deepenSinceWithDeepen=Cannot combine deepen with deepen-since
 deleteBranchUnexpectedResult=Delete branch returned unexpected result {0}
 deleteFileFailed=Could not delete file {0}
+deletedOrphanInPackDir=Deleted orphaned file {}
 deleteRequiresZeroNewId=Delete requires new ID to be zero
 deleteTagUnexpectedResult=Delete tag returned unexpected result {0}
 deletingNotSupported=Deleting {0} not supported.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 61b1456..cd7d1e5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -275,6 +275,7 @@
 	/***/ public String deepenSinceWithDeepen;
 	/***/ public String deleteBranchUnexpectedResult;
 	/***/ public String deleteFileFailed;
+	/***/ public String deletedOrphanInPackDir;
 	/***/ public String deleteRequiresZeroNewId;
 	/***/ public String deleteTagUnexpectedResult;
 	/***/ public String deletingNotSupported;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
index 08bb6cb..0ff3f61 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
@@ -148,6 +148,8 @@
 
 	private static final String INDEX_EXT = "." + PackExt.INDEX.getExtension(); //$NON-NLS-1$
 
+	private static final String KEEP_EXT = "." + PackExt.KEEP.getExtension(); //$NON-NLS-1$
+
 	private static final int DEFAULT_AUTOPACKLIMIT = 50;
 
 	private static final int DEFAULT_AUTOLIMIT = 6700;
@@ -978,11 +980,15 @@
 			fileNames = files.map(path -> path.getFileName().toString())
 					.filter(name -> (name.endsWith(PACK_EXT)
 							|| name.endsWith(BITMAP_EXT)
-							|| name.endsWith(INDEX_EXT)))
+							|| name.endsWith(INDEX_EXT)
+							|| name.endsWith(KEEP_EXT)))
+					// sort files with same base name in the order:
+					// .pack, .keep, .index, .bitmap to avoid look ahead
 					.sorted(Collections.reverseOrder())
 					.collect(Collectors.toList());
-		} catch (IOException e1) {
-			// ignore
+		} catch (IOException e) {
+			LOG.error(e.getMessage(), e);
+			return;
 		}
 		if (fileNames == null) {
 			return;
@@ -990,12 +996,14 @@
 
 		String base = null;
 		for (String n : fileNames) {
-			if (n.endsWith(PACK_EXT)) {
+			if (n.endsWith(PACK_EXT) || n.endsWith(KEEP_EXT)) {
 				base = n.substring(0, n.lastIndexOf('.'));
 			} else {
 				if (base == null || !n.startsWith(base)) {
 					try {
-						Files.delete(packDir.resolve(n));
+						Path delete = packDir.resolve(n);
+						Files.delete(delete);
+						LOG.warn(JGitText.get().deletedOrphanInPackDir, delete);
 					} catch (IOException e) {
 						LOG.error(e.getMessage(), e);
 					}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java
index bded527..4f2e558 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GitmoduleEntry.java
@@ -42,8 +42,6 @@
  */
 package org.eclipse.jgit.lib;
 
-import org.eclipse.jgit.lib.AnyObjectId;
-
 /**
  * A .gitmodules file found in the pack. Store the blob of the file itself (e.g.
  * to access its contents) and the tree where it was found (e.g. to check if it