Merge branch 'stable-6.1' into stable-6.2

* stable-6.1:
  Add verification in GcKeepFilesTest that bitmaps are generated
  Express the explicit intention of creating bitmaps in GC
  GC: prune all packfiles after the loosen phase
  Prepare 5.13.3-SNAPSHOT builds
  JGit v5.13.2.202306221912-r

Change-Id: I5b16c3b613a95b7f28c8f6ac0b20c4c593759cea
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcKeepFilesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcKeepFilesTest.java
index 840c098..571f261 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcKeepFilesTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcKeepFilesTest.java
@@ -48,11 +48,15 @@ public void testKeepFiles() throws Exception {
 		assertEquals(4, stats.numberOfLooseObjects);
 		assertEquals(4, stats.numberOfPackedObjects);
 		assertEquals(1, stats.numberOfPackFiles);
+		PackFile bitmapFile = singlePack.getPackFile().create(PackExt.BITMAP_INDEX);
+		assertTrue(keepFile.exists());
+		assertTrue(bitmapFile.delete());
 		gc.gc().get();
 		stats = gc.getStatistics();
 		assertEquals(0, stats.numberOfLooseObjects);
 		assertEquals(8, stats.numberOfPackedObjects);
 		assertEquals(2, stats.numberOfPackFiles);
+		assertEquals(1, stats.numberOfBitmaps);
 
 		// check that no object is packed twice
 		Iterator<Pack> packs = repo.getObjectDatabase().getPacks()
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 fef8a35..b261cb1 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
@@ -345,6 +345,7 @@ private void deleteOldPacks(Collection<Pack> oldPacks,
 
 		prunePreserved();
 		long packExpireDate = getPackExpireDate();
+		List<PackFile> packFilesToPrune = new ArrayList<>();
 		oldPackLoop: for (Pack oldPack : oldPacks) {
 			checkCancelled();
 			String oldName = oldPack.getPackName();
@@ -362,9 +363,10 @@ private void deleteOldPacks(Collection<Pack> oldPacks,
 					loosen(inserter, reader, oldPack, ids);
 				}
 				oldPack.close();
-				prunePack(oldPack.getPackFile());
+				packFilesToPrune.add(oldPack.getPackFile());
 			}
 		}
+		packFilesToPrune.forEach(this::prunePack);
 
 		// close the complete object database. That's my only chance to force
 		// rescanning and to detect that certain pack files are now deleted.
@@ -858,7 +860,7 @@ public Collection<Pack> repack() throws IOException {
 		Pack heads = null;
 		if (!allHeadsAndTags.isEmpty()) {
 			heads = writePack(allHeadsAndTags, PackWriter.NONE, allTags,
-					refsToExcludeFromBitmap, tagTargets, excluded);
+					refsToExcludeFromBitmap, tagTargets, excluded, true);
 			if (heads != null) {
 				ret.add(heads);
 				excluded.add(0, heads.getIndex());
@@ -866,13 +868,13 @@ public Collection<Pack> repack() throws IOException {
 		}
 		if (!nonHeads.isEmpty()) {
 			Pack rest = writePack(nonHeads, allHeadsAndTags, PackWriter.NONE,
-					PackWriter.NONE, tagTargets, excluded);
+					PackWriter.NONE, tagTargets, excluded, false);
 			if (rest != null)
 				ret.add(rest);
 		}
 		if (!txnHeads.isEmpty()) {
 			Pack txn = writePack(txnHeads, PackWriter.NONE, PackWriter.NONE,
-					PackWriter.NONE, null, excluded);
+					PackWriter.NONE, null, excluded, false);
 			if (txn != null)
 				ret.add(txn);
 		}
@@ -1142,7 +1144,7 @@ private Set<ObjectId> listNonHEADIndexObjects()
 	private Pack writePack(@NonNull Set<? extends ObjectId> want,
 			@NonNull Set<? extends ObjectId> have, @NonNull Set<ObjectId> tags,
 			@NonNull Set<ObjectId> excludedRefsTips,
-			Set<ObjectId> tagTargets, List<ObjectIdSet> excludeObjects)
+			Set<ObjectId> tagTargets, List<ObjectIdSet> excludeObjects, boolean createBitmap)
 			throws IOException {
 		checkCancelled();
 		File tmpPack = null;
@@ -1173,6 +1175,7 @@ private Pack writePack(@NonNull Set<? extends ObjectId> want,
 			if (excludeObjects != null)
 				for (ObjectIdSet idx : excludeObjects)
 					pw.excludeObjects(idx);
+			pw.setCreateBitmaps(createBitmap);
 			pw.preparePack(pm, want, have, PackWriter.NONE,
 					union(tags, excludedRefsTips));
 			if (pw.getObjectCount() == 0)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
index 59aa5c9..cd3f536 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
@@ -254,6 +254,8 @@ public static Iterable<PackWriter> getInstances() {
 
 	private boolean useBitmaps;
 
+	private boolean createBitmaps = true;
+
 	private boolean ignoreMissingUninteresting = true;
 
 	private boolean pruneCurrentObjectList;
@@ -575,6 +577,26 @@ public void setUseBitmaps(boolean useBitmaps) {
 	}
 
 	/**
+	 * Whether to generate bitmaps.
+	 *
+	 * @param createBitmaps
+	 *            if set to true, bitmaps will be generated when creating a pack.
+	 */
+	public void setCreateBitmaps(boolean createBitmaps) {
+		this.createBitmaps = createBitmaps;
+	}
+
+	/**
+	 * Whether the bitmap file is to be created by this PackWriter.
+	 *
+	 * @return {@code true} if the bitmap file is to be created by this
+	 *         PackWriter.
+	 */
+	public boolean isCreateBitmaps() {
+		return createBitmaps;
+	}
+
+	/**
 	 * Whether the index file cannot be created by this PackWriter.
 	 *
 	 * @return {@code true} if the index file cannot be created by this
@@ -1910,7 +1932,7 @@ private void findObjectsToPack(@NonNull ProgressMonitor countingMonitor,
 		canBuildBitmaps = config.isBuildBitmaps()
 				&& !shallowPack
 				&& have.isEmpty()
-				&& (excludeInPacks == null || excludeInPacks.length == 0);
+				&& createBitmaps;
 		if (!shallowPack && useBitmaps) {
 			BitmapIndex bitmapIndex = reader.getBitmapIndex();
 			if (bitmapIndex != null) {