Merge branch 'master' into stable-7.5
* master:
InterruptTimer: don't use Yoda-style condition
InterruptTimer: avoid expensive notify when begin is soon after end
InterruptTimer: avoid unneeded notify for end()
Disable MergeToolTest#testEmptyToolName
Fix hamcrest version to 3.0.0 in target platform
Add InterruptTimer Tests
Update slf4j to 2.0.17
Update org.hamcrest to 3.0.0
DfsPackFile: asObjectIdSet() when only inclusion is needed.
DfsObjDatabase: read reftables from midx covered packs
Update jetty to 12.1.3
Fix signed push failing when using push options
DfsReader/PackFile: Move bitmap inclusion check to the packfile
Use generic Map interface in signature of internal API methods
Allow to discover bitmap on disk created after the packfile
DfsPackCompactor: add toPrune method
MidxPackList: Helper to get packs/midx and overlaps between them
DfsPackFileMidx: make the class public
[ssh] Fix order of keys in pubkey auth if an agent is used
Update bytebuddy to 1.17.8
Update jetty to 12.1.2
DfsPackCompactor: Move #autoAdd to the tests (its only caller)
DfsPackFileMidx: add #getAllCoveredPacks() method
DfsGarbageCollector: handle pack lists with multipack indexes
DfsPackFileMidx: Return bitmap from any underlying pack
midx: caller chooses the order of packs in the midx
DfsObjDatabase: make #setUseMultipackIndex public
MidxPackFilterTest: Remove unused import
DfsObjDatabase: move pack mangling to helper MidxPackFilter
Document how to test a release staged in Maven Central Portal
DfsMidxWriter: helper class to create a pack with an midx
DfsObjDatabase: make useMultipackIndex getter/setter protected
Update Maven plugins
DfsObjDatabase: introduce multipack index
Prepare 5.13.6-SNAPSHOT builds
JGit v5.13.5.202508271544-r
Remove resolver option from target-platform-configuration
Add missing release property to maven build
Suppress API errors for minor API changes in service releases
Remove unnecessary casts
Change-Id: I6fba55292e9948ae74808e4c0883742b4048c2ac
diff --git a/WORKSPACE b/WORKSPACE
index b690564..644e283 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -142,16 +142,18 @@
sha1 = "a3fcc5d3c29b2b03433aa2d2f2d2c1b1638924a1",
)
+SLF4J_VERS = "2.0.17"
+
maven_jar(
name = "log-api",
- artifact = "org.slf4j:slf4j-api:1.7.36",
- sha1 = "6c62681a2f655b49963a5983b8b0950a6120ae14",
+ artifact = "org.slf4j:slf4j-api:" + SLF4J_VERS,
+ sha1 = "d9e58ac9c7779ba3bf8142aff6c830617a7fe60f",
)
maven_jar(
name = "slf4j-simple",
- artifact = "org.slf4j:slf4j-simple:1.7.36",
- sha1 = "a41f9cfe6faafb2eb83a1c7dd2d0dfd844e2a936",
+ artifact = "org.slf4j:slf4j-simple:" + SLF4J_VERS,
+ sha1 = "9872a3fd794ffe7b18d17747926a64d61526ca96",
)
maven_jar(
@@ -198,8 +200,8 @@
maven_jar(
name = "hamcrest",
- artifact = "org.hamcrest:hamcrest:2.2",
- sha1 = "1820c0968dba3a11a1b30669bb1f01978a91dedc",
+ artifact = "org.hamcrest:hamcrest:3.0",
+ sha1 = "8fd9b78a8e6a6510a078a9e30e9e86a6035cfaf7",
)
maven_jar(
@@ -214,18 +216,18 @@
sha1 = "8f34ccd6808899ad1d0aac6a770b73191f2f2a53",
)
-BYTE_BUDDY_VERSION = "1.17.7"
+BYTE_BUDDY_VERSION = "1.17.8"
maven_jar(
name = "bytebuddy",
artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
- sha1 = "3856bfab61beb23e099a0d6629f2ba8de4b98ace",
+ sha1 = "af5735f63d00ca47a9375fae5c7471a36331c6ed",
)
maven_jar(
name = "bytebuddy-agent",
artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
- sha1 = "fbf3d6d649ed37fc9e9c59480a05be0a26e3c2da",
+ sha1 = "f09415827a71be7ed621c7bd02550678f28bc81c",
)
maven_jar(
@@ -240,54 +242,54 @@
sha1 = "48b8230771e573b54ce6e867a9001e75977fe78e",
)
-JETTY_VER = "12.1.1"
+JETTY_VER = "12.1.3"
maven_jar(
name = "jetty-servlet",
artifact = "org.eclipse.jetty.ee10:jetty-ee10-servlet:" + JETTY_VER,
- sha1 = "28e6e238d77f94d71714945a7d064fedcefa6918",
+ sha1 = "b2709dddac048fb03735c9ea85673dbfcec8bdfc",
)
maven_jar(
name = "jetty-security",
artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER,
- sha1 = "089c47852a9ac216e66b2d3d2e12b8721b9b8ca2",
+ sha1 = "f40cb316ef0e9a168f59eaf0b2d0440b7adcb1f8",
)
maven_jar(
name = "jetty-server",
artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER,
- sha1 = "4a34529a4737bcc4868186914a72a097edee1a52",
+ sha1 = "7741aafcd7d6dc718d04d4cfb883982e361d6577",
)
maven_jar(
name = "jetty-session",
artifact = "org.eclipse.jetty:jetty-session:" + JETTY_VER,
- sha1 = "7db390e7856c75e001b1ade978e27397dcbc97eb",
+ sha1 = "0837f081a357a2c835a96ceaa09445921a33b0e9",
)
maven_jar(
name = "jetty-http",
artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER,
- sha1 = "4c087942e5cdaf4b716146312f9ff4c5a1e289d9",
+ sha1 = "3822fb03ec85e4157cf68c1ac661b5d06fd19b25",
)
maven_jar(
name = "jetty-io",
artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER,
- sha1 = "f9efcb4d69ee757721c5f0f3bf4cd55b48a44b48",
+ sha1 = "2c46bf53f41e40df72ff457c40553da2ace7b956",
)
maven_jar(
name = "jetty-util",
artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER,
- sha1 = "582a66cbad2b577ad11b7945e434bd5732c1e45d",
+ sha1 = "9606f6cc440419f62214ceaa2c8ab4b312baf6be",
)
maven_jar(
name = "jetty-util-ajax",
artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VER,
- sha1 = "81d03427b838dfc994c072eadd69e8a8a3802c0d",
+ sha1 = "d0b0a631434ca2cf5a913d2852893779bfecebf8",
)
BOUNCYCASTLE_VER = "1.82"
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index 1dde9aa..0157b21 100644
--- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
@@ -14,5 +14,5 @@
org.eclipse.jgit.junit;version="[7.5.0,7.6.0)",
org.eclipse.jgit.lib;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util;version="[7.5.0,7.6.0)",
- org.hamcrest.core;version="[1.1.0,3.0.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)"
diff --git a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
index 44a76a1..10544b6 100644
--- a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
@@ -8,7 +8,6 @@
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
Import-Package: org.bouncycastle.asn1.cryptlib;version="[1.80.0,2.0.0)",
org.bouncycastle.jce.provider;version="[1.80.0,2.0.0)",
org.bouncycastle.openpgp;version="[1.80.0,2.0.0)",
@@ -18,6 +17,7 @@
org.eclipse.jgit.gpg.bc.internal;version="[7.5.0,7.6.0)",
org.eclipse.jgit.gpg.bc.internal.keys;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util.sha1;version="[7.5.0,7.6.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.runner;version="[4.13,5.0.0)",
org.junit.runners;version="[4.13,5.0.0)"
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index d1d82a8..8c4b4cb 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -8,8 +8,6 @@
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)",
- org.hamcrest.library;bundle-version="[1.3.0,2.0.0)"
Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
jakarta.servlet.http;version="[6.0.0,7.0.0)",
net.bytebuddy.agent;version="[1.9.0,2.0.0)",
@@ -50,6 +48,7 @@
org.eclipse.jgit.transport.http.apache;version="[7.5.0,7.6.0)",
org.eclipse.jgit.transport.resolver;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util;version="[7.5.0,7.6.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.rules;version="[4.13,5.0.0)",
org.junit.runner;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
index b7bd24d..cbe0465 100644
--- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
@@ -45,7 +45,7 @@
org.eclipse.jgit.treewalk;version="[7.5.0,7.6.0)",
org.eclipse.jgit.treewalk.filter;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util;version="[7.5.0,7.6.0)",
- org.hamcrest.core;version="[1.1.0,3.0.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.rules;version="[4.13,5.0.0)",
org.junit.runner;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
index f460a8c..cc1b4cc 100644
--- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
@@ -24,7 +24,7 @@
org.eclipse.jgit.treewalk;version="[7.5.0,7.6.0)",
org.eclipse.jgit.treewalk.filter;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util;version="[7.5.0,7.6.0)",
- org.hamcrest.core;version="[1.1.0,3.0.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.runner;version="[4.13,5.0.0)",
org.junit.runners;version="[4.13,5.0.0)"
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
index eef699c..08294c7 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
@@ -234,6 +234,24 @@
<bundle id="org.osgi.service.cm.source">
<category name="JGit-dependency-bundles"/>
</bundle>
+ <bundle id="org.objectweb.asm">
+ <category name="JGit-dependency-bundles"/>
+ </bundle>
+ <bundle id="org.objectweb.asm.commons">
+ <category name="JGit-dependency-bundles"/>
+ </bundle>
+ <bundle id="org.objectweb.asm.util">
+ <category name="JGit-dependency-bundles"/>
+ </bundle>
+ <bundle id="org.objectweb.asm.tree">
+ <category name="JGit-dependency-bundles"/>
+ </bundle>
+ <bundle id="org.objectweb.asm.tree.analysis">
+ <category name="JGit-dependency-bundles"/>
+ </bundle>
+ <bundle id="org.apache.aries.spifly.dynamic.bundle">
+ <category name="JGit-dependency-bundles"/>
+ </bundle>
<category-def name="JGit" label="Java implementation of Git">
<description>
Java implementation of Git
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target
deleted file mode 100644
index a91976c..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target
+++ /dev/null
@@ -1,288 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde?>
-<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.32" sequenceNumber="1759825554">
- <locations>
- <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
- <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
- <unit id="com.jcraft.jsch.source" version="0.1.55.v20230916-1400"/>
- <unit id="com.jcraft.jzlib" version="1.1.3.v20230916-1400"/>
- <unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
- <unit id="org.apache.ant" version="1.10.14.v20230922-1200"/>
- <unit id="org.apache.ant.source" version="1.10.14.v20230922-1200"/>
- <unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
- <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
- <unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
- <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
- <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.junit" version="4.13.2.v20230809-1000"/>
- <unit id="org.junit.source" version="4.13.2.v20230809-1000"/>
- <unit id="org.objenesis" version="3.4.0"/>
- <unit id="org.objenesis.source" version="3.4.0"/>
- <unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
- <unit id="org.osgi.service.cm.source" version="1.6.1.202109301733"/>
- <repository location="https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-06"/>
- </location>
- <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
- <unit id="org.eclipse.osgi" version="0.0.0"/>
- <repository location="https://download.eclipse.org/staging/2024-06/"/>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="xz">
- <dependencies>
- <dependency>
- <groupId>org.tukaani</groupId>
- <artifactId>xz</artifactId>
- <version>1.10</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="slf4j">
- <dependencies>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.7.36</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <version>1.7.36</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
- <dependencies>
- <dependency>
- <groupId>org.apache.sshd</groupId>
- <artifactId>sshd-osgi</artifactId>
- <version>2.16.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.apache.sshd</groupId>
- <artifactId>sshd-sftp</artifactId>
- <version>2.16.0</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="mockito">
- <dependencies>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>5.20.0</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jna">
- <dependencies>
- <dependency>
- <groupId>net.java.dev.jna</groupId>
- <artifactId>jna</artifactId>
- <version>5.18.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>net.java.dev.jna</groupId>
- <artifactId>jna-platform</artifactId>
- <version>5.18.1</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jetty">
- <dependencies>
- <dependency>
- <groupId>org.eclipse.jetty.ee10</groupId>
- <artifactId>jetty-ee10-servlet</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-session</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util-ajax</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>jakarta.servlet</groupId>
- <artifactId>jakarta.servlet-api</artifactId>
- <version>6.1.0</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="javaewah">
- <dependencies>
- <dependency>
- <groupId>com.googlecode.javaewah</groupId>
- <artifactId>JavaEWAH</artifactId>
- <version>1.2.3</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="hamcrest">
- <dependencies>
- <dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest</artifactId>
- <version>2.2</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="gson">
- <dependencies>
- <dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>2.13.2</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bytebuddy">
- <dependencies>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy</artifactId>
- <version>1.17.7</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy-agent</artifactId>
- <version>1.17.7</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bouncycastle">
- <dependencies>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcpg-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcpkix-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcutil-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="assertj">
- <dependencies>
- <dependency>
- <groupId>org.assertj</groupId>
- <artifactId>assertj-core</artifactId>
- <version>3.27.6</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="args4j">
- <dependencies>
- <dependency>
- <groupId>args4j</groupId>
- <artifactId>args4j</artifactId>
- <version>2.37</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="apache">
- <dependencies>
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>1.19.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-compress</artifactId>
- <version>1.28.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.19.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.20.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <version>1.3.5</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- </locations>
-</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.tpd
deleted file mode 100644
index b8574c7..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.tpd
+++ /dev/null
@@ -1,8 +0,0 @@
-target "jgit-4.32" with source configurePhase
-
-include "orbit/orbit-4.32.tpd"
-include "maven/dependencies.tpd"
-
-location "https://download.eclipse.org/staging/2024-06/" {
- org.eclipse.osgi lazy
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target
deleted file mode 100644
index 220a42a..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target
+++ /dev/null
@@ -1,288 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?pde?>
-<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.33" sequenceNumber="1759825555">
- <locations>
- <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
- <unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
- <unit id="com.jcraft.jsch.source" version="0.1.55.v20230916-1400"/>
- <unit id="com.jcraft.jzlib" version="1.1.3.v20230916-1400"/>
- <unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
- <unit id="org.apache.ant" version="1.10.14.v20230922-1200"/>
- <unit id="org.apache.ant.source" version="1.10.14.v20230922-1200"/>
- <unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
- <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
- <unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
- <unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
- <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.junit" version="4.13.2.v20230809-1000"/>
- <unit id="org.junit.source" version="4.13.2.v20230809-1000"/>
- <unit id="org.objenesis" version="3.4.0"/>
- <unit id="org.objenesis.source" version="3.4.0"/>
- <unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
- <unit id="org.osgi.service.cm.source" version="1.6.1.202109301733"/>
- <repository location="https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-09"/>
- </location>
- <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
- <unit id="org.eclipse.osgi" version="0.0.0"/>
- <repository location="https://download.eclipse.org/releases/2024-09/"/>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="xz">
- <dependencies>
- <dependency>
- <groupId>org.tukaani</groupId>
- <artifactId>xz</artifactId>
- <version>1.10</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="slf4j">
- <dependencies>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.7.36</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <version>1.7.36</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="sshd">
- <dependencies>
- <dependency>
- <groupId>org.apache.sshd</groupId>
- <artifactId>sshd-osgi</artifactId>
- <version>2.16.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.apache.sshd</groupId>
- <artifactId>sshd-sftp</artifactId>
- <version>2.16.0</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="mockito">
- <dependencies>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>5.20.0</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jna">
- <dependencies>
- <dependency>
- <groupId>net.java.dev.jna</groupId>
- <artifactId>jna</artifactId>
- <version>5.18.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>net.java.dev.jna</groupId>
- <artifactId>jna-platform</artifactId>
- <version>5.18.1</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="jetty">
- <dependencies>
- <dependency>
- <groupId>org.eclipse.jetty.ee10</groupId>
- <artifactId>jetty-ee10-servlet</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-io</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-session</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util-ajax</artifactId>
- <version>12.1.1</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>jakarta.servlet</groupId>
- <artifactId>jakarta.servlet-api</artifactId>
- <version>6.1.0</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="javaewah">
- <dependencies>
- <dependency>
- <groupId>com.googlecode.javaewah</groupId>
- <artifactId>JavaEWAH</artifactId>
- <version>1.2.3</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="hamcrest">
- <dependencies>
- <dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest</artifactId>
- <version>2.2</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="gson">
- <dependencies>
- <dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>2.13.2</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bytebuddy">
- <dependencies>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy</artifactId>
- <version>1.17.7</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy-agent</artifactId>
- <version>1.17.7</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="bouncycastle">
- <dependencies>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcpg-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcpkix-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcutil-jdk18on</artifactId>
- <version>1.82</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="assertj">
- <dependencies>
- <dependency>
- <groupId>org.assertj</groupId>
- <artifactId>assertj-core</artifactId>
- <version>3.27.6</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="args4j">
- <dependencies>
- <dependency>
- <groupId>args4j</groupId>
- <artifactId>args4j</artifactId>
- <version>2.37</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- <location includeDependencyDepth="none" includeDependencyScopes="compile" includeSource="true" missingManifest="error" type="Maven" label="apache">
- <dependencies>
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>1.19.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-compress</artifactId>
- <version>1.28.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.19.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.20.0</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <version>1.3.5</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </location>
- </locations>
-</target>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.tpd
deleted file mode 100644
index 74c6878..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.tpd
+++ /dev/null
@@ -1,8 +0,0 @@
-target "jgit-4.33" with source configurePhase
-
-include "orbit/orbit-4.33.tpd"
-include "maven/dependencies.tpd"
-
-location "https://download.eclipse.org/releases/2024-09/" {
- org.eclipse.osgi lazy
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target
index 95494e8..c323c45 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.34" sequenceNumber="1759825554">
+<target name="jgit-4.34" sequenceNumber="1761604946">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -10,16 +10,20 @@
<unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
<unit id="org.apache.ant" version="1.10.15.v20240901-1000"/>
<unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+ <unit id="org.apache.aries.spifly.dynamic.bundle" version="1.3.7"/>
<unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
- <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
+ <unit id="org.hamcrest" version="3.0.0"/>
+ <unit id="org.hamcrest.source" version="3.0.0"/>
<unit id="org.junit" version="4.13.2.v20240929-1000"/>
<unit id="org.junit.source" version="4.13.2.v20240929-1000"/>
+ <unit id="org.objectweb.asm" version="9.7.1"/>
+ <unit id="org.objectweb.asm.commons" version="9.7.1"/>
+ <unit id="org.objectweb.asm.util" version="9.7.1"/>
+ <unit id="org.objectweb.asm.tree" version="9.7.1"/>
+ <unit id="org.objectweb.asm.tree.analysis" version="9.7.1"/>
<unit id="org.objenesis" version="3.4.0"/>
<unit id="org.objenesis.source" version="3.4.0"/>
<unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
@@ -45,13 +49,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -103,49 +107,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
@@ -171,7 +175,7 @@
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
- <version>2.2</version>
+ <version>3.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -191,13 +195,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
</dependencies>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target
index dd06ccd..baf1e3b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.35" sequenceNumber="1759825554">
+<target name="jgit-4.35" sequenceNumber="1761604946">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -10,16 +10,20 @@
<unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
<unit id="org.apache.ant" version="1.10.15.v20240901-1000"/>
<unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+ <unit id="org.apache.aries.spifly.dynamic.bundle" version="1.3.7"/>
<unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
- <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
+ <unit id="org.hamcrest" version="3.0.0"/>
+ <unit id="org.hamcrest.source" version="3.0.0"/>
<unit id="org.junit" version="4.13.2.v20240929-1000"/>
<unit id="org.junit.source" version="4.13.2.v20240929-1000"/>
+ <unit id="org.objectweb.asm" version="9.7.1"/>
+ <unit id="org.objectweb.asm.commons" version="9.7.1"/>
+ <unit id="org.objectweb.asm.util" version="9.7.1"/>
+ <unit id="org.objectweb.asm.tree" version="9.7.1"/>
+ <unit id="org.objectweb.asm.tree.analysis" version="9.7.1"/>
<unit id="org.objenesis" version="3.4.0"/>
<unit id="org.objenesis.source" version="3.4.0"/>
<unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
@@ -45,13 +49,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -103,49 +107,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
@@ -171,7 +175,7 @@
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
- <version>2.2</version>
+ <version>3.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -191,13 +195,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
</dependencies>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target
index e6cf65a..298bc2a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.36" sequenceNumber="1759825554">
+<target name="jgit-4.36" sequenceNumber="1761604946">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -10,16 +10,20 @@
<unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
<unit id="org.apache.ant" version="1.10.15.v20240901-1000"/>
<unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+ <unit id="org.apache.aries.spifly.dynamic.bundle" version="1.3.7"/>
<unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
- <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
+ <unit id="org.hamcrest" version="3.0.0"/>
+ <unit id="org.hamcrest.source" version="3.0.0"/>
<unit id="org.junit" version="4.13.2.v20240929-1000"/>
<unit id="org.junit.source" version="4.13.2.v20240929-1000"/>
+ <unit id="org.objectweb.asm" version="9.8.0"/>
+ <unit id="org.objectweb.asm.commons" version="9.8.0"/>
+ <unit id="org.objectweb.asm.util" version="9.8.0"/>
+ <unit id="org.objectweb.asm.tree" version="9.8.0"/>
+ <unit id="org.objectweb.asm.tree.analysis" version="9.8.0"/>
<unit id="org.objenesis" version="3.4.0"/>
<unit id="org.objenesis.source" version="3.4.0"/>
<unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
@@ -45,13 +49,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -103,49 +107,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
@@ -171,7 +175,7 @@
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
- <version>2.2</version>
+ <version>3.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -191,13 +195,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
</dependencies>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target
index 3765962..ec93cd0 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.37.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.37" sequenceNumber="1759825554">
+<target name="jgit-4.37" sequenceNumber="1761604946">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -10,16 +10,20 @@
<unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
<unit id="org.apache.ant" version="1.10.15.v20240901-1000"/>
<unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+ <unit id="org.apache.aries.spifly.dynamic.bundle" version="1.3.7"/>
<unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
- <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
+ <unit id="org.hamcrest" version="3.0.0"/>
+ <unit id="org.hamcrest.source" version="3.0.0"/>
<unit id="org.junit" version="4.13.2.v20240929-1000"/>
<unit id="org.junit.source" version="4.13.2.v20240929-1000"/>
+ <unit id="org.objectweb.asm" version="9.8.0"/>
+ <unit id="org.objectweb.asm.commons" version="9.8.0"/>
+ <unit id="org.objectweb.asm.util" version="9.8.0"/>
+ <unit id="org.objectweb.asm.tree" version="9.8.0"/>
+ <unit id="org.objectweb.asm.tree.analysis" version="9.8.0"/>
<unit id="org.objenesis" version="3.4.0"/>
<unit id="org.objenesis.source" version="3.4.0"/>
<unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
@@ -45,13 +49,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -103,49 +107,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
@@ -171,7 +175,7 @@
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
- <version>2.2</version>
+ <version>3.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -191,13 +195,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
</dependencies>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target
index 71ac500..c0f3dd9 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.38.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="jgit-4.38" sequenceNumber="1759825922">
+<target name="jgit-4.38" sequenceNumber="1761604947">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="com.jcraft.jsch" version="0.1.55.v20230916-1400"/>
@@ -10,16 +10,20 @@
<unit id="com.jcraft.jzlib.source" version="1.1.3.v20230916-1400"/>
<unit id="org.apache.ant" version="1.10.15.v20240901-1000"/>
<unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+ <unit id="org.apache.aries.spifly.dynamic.bundle" version="1.3.7"/>
<unit id="org.apache.httpcomponents.httpclient" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpclient.source" version="4.5.14"/>
<unit id="org.apache.httpcomponents.httpcore" version="4.4.16"/>
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.16"/>
- <unit id="org.hamcrest.core" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.core.source" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library" version="1.3.0.v20230809-1000"/>
- <unit id="org.hamcrest.library.source" version="1.3.0.v20230809-1000"/>
+ <unit id="org.hamcrest" version="3.0.0"/>
+ <unit id="org.hamcrest.source" version="3.0.0"/>
<unit id="org.junit" version="4.13.2.v20240929-1000"/>
<unit id="org.junit.source" version="4.13.2.v20240929-1000"/>
+ <unit id="org.objectweb.asm" version="9.9.0"/>
+ <unit id="org.objectweb.asm.commons" version="9.9.0"/>
+ <unit id="org.objectweb.asm.util" version="9.9.0"/>
+ <unit id="org.objectweb.asm.tree" version="9.9.0"/>
+ <unit id="org.objectweb.asm.tree.analysis" version="9.9.0"/>
<unit id="org.objenesis" version="3.4.0"/>
<unit id="org.objenesis.source" version="3.4.0"/>
<unit id="org.osgi.service.cm" version="1.6.1.202109301733"/>
@@ -45,13 +49,13 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
- <version>1.7.36</version>
+ <version>2.0.17</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -103,49 +107,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.1.1</version>
+ <version>12.1.3</version>
<type>jar</type>
</dependency>
<dependency>
@@ -171,7 +175,7 @@
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
- <version>2.2</version>
+ <version>3.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -191,13 +195,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.17.7</version>
+ <version>1.17.8</version>
<type>jar</type>
</dependency>
</dependencies>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd
index 2f2f0b3..5e4f998 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd
@@ -97,12 +97,12 @@
dependency {
groupId = "net.bytebuddy"
artifactId = "byte-buddy"
- version = "1.17.7"
+ version = "1.17.8"
}
dependency {
groupId = "net.bytebuddy"
artifactId = "byte-buddy-agent"
- version = "1.17.7"
+ version = "1.17.8"
}
}
@@ -128,7 +128,7 @@
dependency {
groupId = "org.hamcrest"
artifactId = "hamcrest"
- version = "2.2"
+ version = "3.0"
}
}
@@ -154,42 +154,42 @@
dependency {
groupId = "org.eclipse.jetty.ee10"
artifactId = "jetty-ee10-servlet"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-http"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-io"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-security"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-server"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-session"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-util"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-util-ajax"
- version = "12.1.1"
+ version = "12.1.3"
}
dependency {
groupId = "jakarta.servlet"
@@ -256,12 +256,12 @@
dependency {
groupId = "org.slf4j"
artifactId = "slf4j-api"
- version = "1.7.36"
+ version = "2.0.17"
}
dependency {
groupId = "org.slf4j"
artifactId = "slf4j-simple"
- version = "1.7.36"
+ version = "2.0.17"
}
}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd
deleted file mode 100644
index 59fcd87..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd
+++ /dev/null
@@ -1,25 +0,0 @@
-target "orbit-4.32" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-06" {
- com.jcraft.jsch [0.1.55.v20230916-1400,0.1.55.v20230916-1400]
- com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400]
- com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
- com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
- org.apache.ant [1.10.14.v20230922-1200,1.10.14.v20230922-1200]
- org.apache.ant.source [1.10.14.v20230922-1200,1.10.14.v20230922-1200]
- org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
- org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
- org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
- org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
- org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.junit [4.13.2.v20230809-1000,4.13.2.v20230809-1000]
- org.junit.source [4.13.2.v20230809-1000,4.13.2.v20230809-1000]
- org.objenesis [3.4,3.4]
- org.objenesis.source [3.4,3.4]
- org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
- org.osgi.service.cm.source [1.6.1.202109301733,1.6.1.202109301733]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd
deleted file mode 100644
index 2cfa0a8..0000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd
+++ /dev/null
@@ -1,25 +0,0 @@
-target "orbit-4.33" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024-09" {
- com.jcraft.jsch [0.1.55.v20230916-1400,0.1.55.v20230916-1400]
- com.jcraft.jsch.source [0.1.55.v20230916-1400,0.1.55.v20230916-1400]
- com.jcraft.jzlib [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
- com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
- org.apache.ant [1.10.14.v20230922-1200,1.10.14.v20230922-1200]
- org.apache.ant.source [1.10.14.v20230922-1200,1.10.14.v20230922-1200]
- org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
- org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
- org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
- org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
- org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.junit [4.13.2.v20230809-1000,4.13.2.v20230809-1000]
- org.junit.source [4.13.2.v20230809-1000,4.13.2.v20230809-1000]
- org.objenesis [3.4,3.4]
- org.objenesis.source [3.4,3.4]
- org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
- org.osgi.service.cm.source [1.6.1.202109301733,1.6.1.202109301733]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd
index d3e15bb..d3c2f2f 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd
@@ -8,16 +8,20 @@
com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
+ org.apache.aries.spifly.dynamic.bundle [1.3.7,1.3.7]
org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
- org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+ org.hamcrest [3.0.0,3.0.0]
+ org.hamcrest.source [3.0.0,3.0.0]
org.junit [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
org.junit.source [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
+ org.objectweb.asm [9.7.1,9.7.1]
+ org.objectweb.asm.commons [9.7.1,9.7.1]
+ org.objectweb.asm.util [9.7.1,9.7.1]
+ org.objectweb.asm.tree [9.7.1,9.7.1]
+ org.objectweb.asm.tree.analysis [9.7.1,9.7.1]
org.objenesis [3.4,3.4]
org.objenesis.source [3.4,3.4]
org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd
index ec6996e..f5f9a08 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd
@@ -8,16 +8,20 @@
com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
+ org.apache.aries.spifly.dynamic.bundle [1.3.7,1.3.7]
org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
- org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+ org.hamcrest [3.0.0,3.0.0]
+ org.hamcrest.source [3.0.0,3.0.0]
org.junit [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
org.junit.source [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
+ org.objectweb.asm [9.7.1,9.7.1]
+ org.objectweb.asm.commons [9.7.1,9.7.1]
+ org.objectweb.asm.util [9.7.1,9.7.1]
+ org.objectweb.asm.tree [9.7.1,9.7.1]
+ org.objectweb.asm.tree.analysis [9.7.1,9.7.1]
org.objenesis [3.4,3.4]
org.objenesis.source [3.4,3.4]
org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.36.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.36.tpd
index 4f46583..b60e90d 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.36.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.36.tpd
@@ -8,16 +8,20 @@
com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
+ org.apache.aries.spifly.dynamic.bundle [1.3.7,1.3.7]
org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
- org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+ org.hamcrest [3.0.0,3.0.0]
+ org.hamcrest.source [3.0.0,3.0.0]
org.junit [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
org.junit.source [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
+ org.objectweb.asm [9.8.0,9.8.0]
+ org.objectweb.asm.commons [9.8.0,9.8.0]
+ org.objectweb.asm.util [9.8.0,9.8.0]
+ org.objectweb.asm.tree [9.8.0,9.8.0]
+ org.objectweb.asm.tree.analysis [9.8.0,9.8.0]
org.objenesis [3.4,3.4]
org.objenesis.source [3.4,3.4]
org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.37.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.37.tpd
index 9c1ba4f..c142490 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.37.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.37.tpd
@@ -8,16 +8,20 @@
com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
+ org.apache.aries.spifly.dynamic.bundle [1.3.7,1.3.7]
org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
- org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+ org.hamcrest [3.0.0,3.0.0]
+ org.hamcrest.source [3.0.0,3.0.0]
org.junit [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
org.junit.source [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
+ org.objectweb.asm [9.8.0,9.8.0]
+ org.objectweb.asm.commons [9.8.0,9.8.0]
+ org.objectweb.asm.util [9.8.0,9.8.0]
+ org.objectweb.asm.tree [9.8.0,9.8.0]
+ org.objectweb.asm.tree.analysis [9.8.0,9.8.0]
org.objenesis [3.4,3.4]
org.objenesis.source [3.4,3.4]
org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.38.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.38.tpd
index cfa3682..7601cc4 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.38.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.38.tpd
@@ -8,16 +8,20 @@
com.jcraft.jzlib.source [1.1.3.v20230916-1400,1.1.3.v20230916-1400]
org.apache.ant [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
org.apache.ant.source [1.10.15.v20240901-1000,1.10.15.v20240901-1000]
+ org.apache.aries.spifly.dynamic.bundle [1.3.7,1.3.7]
org.apache.httpcomponents.httpclient [4.5.14,4.5.14]
org.apache.httpcomponents.httpclient.source [4.5.14,4.5.14]
org.apache.httpcomponents.httpcore [4.4.16,4.4.16]
org.apache.httpcomponents.httpcore.source [4.4.16,4.4.16]
- org.hamcrest.core [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.core.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
- org.hamcrest.library.source [1.3.0.v20230809-1000,1.3.0.v20230809-1000]
+ org.hamcrest [3.0.0,3.0.0]
+ org.hamcrest.source [3.0.0,3.0.0]
org.junit [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
org.junit.source [4.13.2.v20240929-1000,4.13.2.v20240929-1000]
+ org.objectweb.asm [9.9.0,9.9.0]
+ org.objectweb.asm.commons [9.9.0,9.9.0]
+ org.objectweb.asm.util [9.9.0,9.9.0]
+ org.objectweb.asm.tree [9.9.0,9.9.0]
+ org.objectweb.asm.tree.analysis [9.9.0,9.9.0]
org.objenesis [3.4,3.4]
org.objenesis.source [3.4,3.4]
org.osgi.service.cm [1.6.1.202109301733,1.6.1.202109301733]
diff --git a/org.eclipse.jgit.packaging/pom.xml b/org.eclipse.jgit.packaging/pom.xml
index 8215c2c..301ed91 100644
--- a/org.eclipse.jgit.packaging/pom.xml
+++ b/org.eclipse.jgit.packaging/pom.xml
@@ -31,7 +31,7 @@
<properties>
<java.version>17</java.version>
<tycho-version>4.0.13</tycho-version>
- <target-platform>jgit-4.32</target-platform>
+ <target-platform>jgit-4.34</target-platform>
<project.build.outputTimestamp>${git.commit.time}</project.build.outputTimestamp>
</properties>
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java
index 1844223..a7df4fa 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java
@@ -16,8 +16,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.LinkedHashMap;
import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
import org.eclipse.jgit.internal.storage.file.Pack;
@@ -87,7 +86,7 @@ private void writeMultiPackIndex() throws IOException {
ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
- Map<String, PackIndex> indexes = new HashMap<>();
+ LinkedHashMap<String, PackIndex> indexes = new LinkedHashMap<>();
for (Pack pack : odb.getPacks()) {
PackFile packFile = pack.getPackFile().create(PackExt.INDEX);
try {
diff --git a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
index c74fa22..c10f613 100644
--- a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
@@ -8,8 +8,8 @@
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
-Import-Package: org.apache.sshd.certificate;version="[2.16.0,2.17.0)",
+Import-Package: org.apache.sshd.agent;version="[2.16.0,2.17.0)",
+ org.apache.sshd.certificate;version="[2.16.0,2.17.0)",
org.apache.sshd.client.config.hosts;version="[2.16.0,2.17.0)",
org.apache.sshd.common;version="[2.16.0,2.17.0)",
org.apache.sshd.common.auth;version="[2.16.0,2.17.0)",
@@ -42,6 +42,7 @@
org.eclipse.jgit.transport.sshd;version="[7.5.0,7.6.0)",
org.eclipse.jgit.transport.sshd.agent;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util;version="[7.5.0,7.6.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.experimental.theories;version="[4.13,5.0.0)",
org.junit.rules;version="[4.13.0,5.0.0)",
diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
index 8739457..98478e5 100644
--- a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
+++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/transport/sshd/ApacheSshTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, 2022 Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2018, 2025 Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -16,8 +16,10 @@
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.InputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URISyntaxException;
@@ -26,12 +28,17 @@
import java.nio.file.StandardOpenOption;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
+import org.apache.sshd.agent.SshAgentConstants;
import org.apache.sshd.client.config.hosts.KnownHostEntry;
import org.apache.sshd.client.config.hosts.KnownHostHashValue;
import org.apache.sshd.common.NamedFactory;
@@ -43,7 +50,12 @@
import org.apache.sshd.common.kex.DHFactory;
import org.apache.sshd.common.kex.KeyExchangeFactory;
import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.signature.BuiltinSignatures;
+import org.apache.sshd.common.signature.Signature;
+import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.common.util.net.SshdSocketAddress;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.core.CoreModuleProperties;
import org.apache.sshd.server.ServerAuthenticationManager;
import org.apache.sshd.server.ServerBuilder;
import org.apache.sshd.server.SshServer;
@@ -55,6 +67,8 @@
import org.eclipse.jgit.transport.RemoteSession;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.sshd.agent.Connector;
+import org.eclipse.jgit.transport.sshd.agent.ConnectorFactory;
import org.eclipse.jgit.util.FS;
import org.junit.Test;
import org.junit.experimental.theories.Theories;
@@ -63,13 +77,13 @@
@RunWith(Theories.class)
public class ApacheSshTest extends SshTestBase {
- @Override
- protected SshSessionFactory createSessionFactory() {
+ private SshSessionFactory createSessionFactory(
+ ConnectorFactory agentFactory) {
return new SshdSessionFactoryBuilder()
// No proxies in tests
.setProxyDataFactory(null)
// No ssh-agent in tests
- .setConnectorFactory(null)
+ .setConnectorFactory(agentFactory)
// The home directory is mocked at this point!
.setHomeDirectory(FS.DETECTED.userHome())
.setSshDirectory(sshDir)
@@ -77,6 +91,11 @@ protected SshSessionFactory createSessionFactory() {
}
@Override
+ protected SshSessionFactory createSessionFactory() {
+ return createSessionFactory(null);
+ }
+
+ @Override
protected void installConfig(String... config) {
File configFile = new File(sshDir, Constants.CONFIG);
if (config != null) {
@@ -133,6 +152,35 @@ public void testWrongKeyFirst() throws Exception {
"IdentityFile " + userKey.getAbsolutePath());
}
+ /**
+ * Test for ext-info-c being sent. Try authenticating first with a wrong RSA
+ * key. If ext-info-c is not set, the client will re-try three times with
+ * the wrong key (once for each RSA signature algorithm). Since we set the
+ * server to disconnect after three failed attempts, the test will fail. If
+ * ext-info-c _is_ sent, the client will try only once and then try the
+ * correct ed25519 key next and will succeed.
+ *
+ * @throws Exception
+ * on errors
+ */
+ @Test
+ public void testKexExtension() throws Exception {
+ File userKey = new File(getTemporaryDirectory(), "userkey");
+ copyTestResource("id_ed25519", userKey);
+ File publicKey = new File(getTemporaryDirectory(), "userkey.pub");
+ copyTestResource("id_ed25519.pub", publicKey);
+ server.setTestUserPublicKey(publicKey.toPath());
+ CoreModuleProperties.MAX_AUTH_REQUESTS.set(server.getPropertyResolver(),
+ Integer.valueOf(3));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + privateKey1.getAbsolutePath(), // RSA
+ "IdentityFile " + userKey.getAbsolutePath());
+ }
+
@Test
public void testHashedKnownHosts() throws Exception {
assertTrue("Failed to delete known_hosts", knownHosts.delete());
@@ -894,4 +942,182 @@ public void testCipherModificationUnknown() throws Exception {
"Ciphers 3des-cbc"));
assertTrue(e.getLocalizedMessage().contains("3des-cbc"));
}
+
+ /**
+ * Tests that the client does not try agent keys in an arbitrary order. It
+ * should try agent keys that correspond to a listed IdentityFile first.
+ *
+ * @throws Exception
+ * on errors
+ */
+ @Test
+ public void testAgentWithIdentities() throws Exception {
+ try (FakeAgentConnector fakeAgent = new FakeAgentConnector()) {
+ // Fill the agent with a few fake RSA key pairs
+ KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
+ generator.initialize(1024);
+ fakeAgent.add(generator.generateKeyPair());
+ fakeAgent.add(generator.generateKeyPair());
+ fakeAgent.add(generator.generateKeyPair());
+ fakeAgent.add(generator.generateKeyPair());
+
+ File userKey = new File(getTemporaryDirectory(), "userkey");
+ copyTestResource("id_ed25519", userKey);
+ File publicKey = new File(getTemporaryDirectory(), "userkey.pub");
+ copyTestResource("id_ed25519.pub", publicKey);
+ server.setTestUserPublicKey(publicKey.toPath());
+ try (InputStream in = new BufferedInputStream(
+ Files.newInputStream(userKey.toPath()))) {
+ Iterable<KeyPair> pairs = SecurityUtils
+ .loadKeyPairIdentities(null, null, in, null);
+ fakeAgent.add(pairs.iterator().next());
+ }
+
+ ConnectorFactory fakeFactory = new FakeConnectorFactory() {
+
+ @Override
+ public Connector create(String identityAgent, File homeDir)
+ throws IOException {
+ return fakeAgent;
+ }
+ };
+ SshSessionFactory.setInstance(createSessionFactory(fakeFactory));
+ CoreModuleProperties.MAX_AUTH_REQUESTS
+ .set(server.getPropertyResolver(), Integer.valueOf(2));
+ cloneWith("ssh://git/doesntmatter", defaultCloneDir, null, //
+ "Host git", //
+ "HostName localhost", //
+ "Port " + testPort, //
+ "User " + TEST_USER, //
+ "IdentityFile " + userKey.getAbsolutePath());
+ assertTrue("Agent should have been called", fakeAgent.signCalled);
+ }
+ }
+
+ /**
+ * A little dummy implementation of an SSH agent for testing.
+ */
+ private static class FakeAgentConnector implements Connector {
+
+ private Map<String, KeyPair> keys = new LinkedHashMap<>();
+
+ boolean signCalled;
+
+ void add(KeyPair pair) {
+ keys.put(KeyUtils.getFingerPrint(pair.getPublic()), pair);
+ }
+
+ @Override
+ public void close() throws IOException {
+ // Nothing to do
+ }
+
+ @Override
+ public boolean connect() throws IOException {
+ return true;
+ }
+
+ @Override
+ public byte[] rpc(byte command, byte[] message) throws IOException {
+ switch (command) {
+ case SshAgentConstants.SSH2_AGENTC_REQUEST_IDENTITIES:
+ return list();
+ case SshAgentConstants.SSH2_AGENTC_SIGN_REQUEST:
+ signCalled = true;
+ return sign(message);
+ default:
+ return new byte[] { SshAgentConstants.SSH_AGENT_SUCCESS };
+ }
+ }
+
+ private byte[] list() {
+ ByteArrayBuffer result = new ByteArrayBuffer();
+ result.putByte(SshAgentConstants.SSH2_AGENT_IDENTITIES_ANSWER);
+ result.putInt(keys.size());
+ for (KeyPair pair : keys.values()) {
+ result.putPublicKey(pair.getPublic());
+ result.putString(""); // Comment
+ }
+ return result.getCompactData();
+ }
+
+ private byte[] sign(byte[] message) {
+ ByteArrayBuffer buf = new ByteArrayBuffer(message, 5,
+ message.length - 5);
+ try {
+ PublicKey pk = buf.getPublicKey();
+ byte[] dataToSign = buf.getBytes();
+ int flags = buf.getInt();
+ KeyPair pair = keys.get(KeyUtils.getFingerPrint(pk));
+ if (pair == null) {
+ return new byte[] { SshAgentConstants.SSH_AGENT_FAILURE };
+ }
+ // Figure out key type and signature
+ PrivateKey sk = pair.getPrivate();
+ String keyType = KeyUtils.getKeyType(sk);
+ String signatureAlgorithm = keyType;
+ // We ignore complications for sk-keys or certificates here
+ if (keyType.equals("ssh-rsa")) {
+ switch (flags & 6) {
+ case 2:
+ signatureAlgorithm = KeyUtils.RSA_SHA256_KEY_TYPE_ALIAS;
+ break;
+ case 4:
+ signatureAlgorithm = KeyUtils.RSA_SHA512_KEY_TYPE_ALIAS;
+ break;
+ default:
+ break;
+ }
+ }
+ Signature signer = BuiltinSignatures
+ .fromFactoryName(signatureAlgorithm).create();
+ signer.initSigner(null, sk);
+ signer.update(null, dataToSign);
+ ByteArrayBuffer sig = new ByteArrayBuffer();
+ sig.putString(signatureAlgorithm);
+ sig.putBytes(signer.sign(null));
+ ByteArrayBuffer result = new ByteArrayBuffer();
+ result.putByte(SshAgentConstants.SSH2_AGENT_SIGN_RESPONSE);
+ result.putBytes(sig.getCompactData());
+ return result.getCompactData();
+ } catch (Exception e) {
+ return new byte[] { SshAgentConstants.SSH_AGENT_FAILURE };
+ }
+ }
+ }
+
+ abstract static class FakeConnectorFactory implements ConnectorFactory {
+
+ @Override
+ public boolean isSupported() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return "fake";
+ }
+
+ @Override
+ public Collection<ConnectorDescriptor> getSupportedConnectors() {
+ return Collections.singleton(getDefaultConnector());
+ }
+
+ @Override
+ public ConnectorDescriptor getDefaultConnector() {
+ return new ConnectorDescriptor() {
+
+ @Override
+ public String getIdentityAgent() {
+ return "fake";
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "fake";
+ }
+ };
+ }
+
+ }
}
diff --git a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties
index 773c4b9..c91a64a 100644
--- a/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties
+++ b/org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties
@@ -69,6 +69,7 @@
knownHostsUserAskCreationMsg=File {0} does not exist.
knownHostsUserAskCreationPrompt=Create file {0} ?
loginDenied=Cannot log in at {0}:{1}
+noExplicitKeys=Host config for {0} has 'IdentitiesOnly yes' but no valid 'IdentityFile' configured.
passwordPrompt=Password
pkcs11Error=ERROR: {0}
pkcs11FailedInstantiation=HostConfig for host {0} (hostname {1}): could not instantiate {2} {3}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java
index 6aace47..7aaa5c2 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/JGitPublicKeyAuthentication.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, 2023 Thomas Wolf <twolf@apache.org> and others
+ * Copyright (C) 2018, 2025 Thomas Wolf <twolf@apache.org> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -32,6 +32,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -381,60 +382,39 @@ protected Iterable<KeyAgentIdentity> initializeAgentIdentities(
if (allAgentKeys == null) {
return null;
}
- Collection<PublicKey> identityFiles = identitiesOnly();
- if (GenericUtils.isEmpty(identityFiles)) {
+ if (hostConfig == null) {
+ return allAgentKeys;
+ }
+ Collection<PublicKey> explicitKeys = getExplicitKeys(
+ hostConfig.getIdentities());
+ if (GenericUtils.isEmpty(explicitKeys)) {
+ if (hostConfig.isIdentitiesOnly()) {
+ log.warn(LOG_FORMAT, format(SshdText.get().noExplicitKeys,
+ hostConfig.getHost()));
+ return Collections.emptyList();
+ }
return allAgentKeys;
}
- // Only consider agent or PKCS11 keys that match a known public key
- // file.
- return () -> new Iterator<>() {
-
- private final Iterator<KeyAgentIdentity> identities = allAgentKeys
- .iterator();
-
- private KeyAgentIdentity next;
-
- @Override
- public boolean hasNext() {
- while (next == null && identities.hasNext()) {
- KeyAgentIdentity val = identities.next();
- PublicKey pk = val.getKeyIdentity().getPublic();
- // This checks against all explicit keys for any agent
- // key, but since identityFiles.size() is typically 1,
- // it should be fine.
- if (identityFiles.stream()
- .anyMatch(k -> KeyUtils.compareKeys(k, pk))) {
- next = val;
- return true;
- }
- if (log.isTraceEnabled()) {
- log.trace(
- "Ignoring SSH agent or PKCS11 {} key not in explicit IdentityFile in SSH config: {}", //$NON-NLS-1$
- KeyUtils.getKeyType(pk),
- KeyUtils.getFingerPrint(pk));
- }
- }
- return next != null;
+ // Sort the identities such that the ones for the explicitly listed
+ // keys come first, in the order listed.
+ Map<String, KeyAgentIdentity> fromAgent = new LinkedHashMap<>();
+ allAgentKeys.forEach(k -> fromAgent.computeIfAbsent(
+ KeyUtils.getFingerPrint(k.getKeyIdentity().getPublic()),
+ x -> k));
+ List<KeyAgentIdentity> result = new ArrayList<>();
+ for (PublicKey pk : explicitKeys) {
+ KeyAgentIdentity id = fromAgent
+ .remove(KeyUtils.getFingerPrint(pk));
+ if (id != null) {
+ result.add(id);
}
-
- @Override
- public KeyAgentIdentity next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- KeyAgentIdentity result = next;
- next = null;
- return result;
- }
- };
- }
-
- private Collection<PublicKey> identitiesOnly() {
- if (hostConfig != null && hostConfig.isIdentitiesOnly()) {
- return getExplicitKeys(hostConfig.getIdentities());
}
- return Collections.emptyList();
+ if (!hostConfig.isIdentitiesOnly()) {
+ result.addAll(fromAgent.values());
+ }
+
+ return result;
}
private Iterable<KeyAgentIdentity> getAgentIdentities()
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java
index e401378..d40ec83 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, 2024 Thomas Wolf <twolf@apache.org> and others
+ * Copyright (C) 2018, 2025 Thomas Wolf <twolf@apache.org> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -91,6 +91,7 @@ public static SshdText get() {
/***/ public String knownHostsUserAskCreationMsg;
/***/ public String knownHostsUserAskCreationPrompt;
/***/ public String loginDenied;
+ /***/ public String noExplicitKeys;
/***/ public String passwordPrompt;
/***/ public String pkcs11Error;
/***/ public String pkcs11FailedInstantiation;
diff --git a/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
index 2443823..5823845 100644
--- a/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
@@ -8,7 +8,6 @@
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
Import-Package: com.jcraft.jsch;version="[0.1.54,0.2.0)",
org.eclipse.jgit.errors;version="[7.5.0,7.6.0)",
org.eclipse.jgit.internal.storage.file;version="[7.5.0,7.6.0)",
@@ -18,6 +17,7 @@
org.eclipse.jgit.transport;version="[7.5.0,7.6.0)",
org.eclipse.jgit.transport.ssh.jsch;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util;version="[7.5.0,7.6.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.experimental.theories;version="[4.13,5.0.0)",
org.junit.runner;version="[4.13,5.0.0)"
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index 9689f43..c724d35 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -8,8 +8,6 @@
Bundle-Vendor: %Bundle-Vendor
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-SCM: url=https://github.com/eclipse-jgit/jgit, connection=scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit.git, developerConnection=scm:git:https://eclipse.gerrithub.io/a/eclipse-jgit/jgit.git
-Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)",
- org.hamcrest.library;bundle-version="[1.3.0,2.0.0)"
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
net.bytebuddy.agent;version="[1.9.0,2.0.0)",
net.bytebuddy.dynamic.loading;version="[1.9.0,2.0.0)",
@@ -83,6 +81,8 @@
org.eclipse.jgit.util;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util.io;version="[7.5.0,7.6.0)",
org.eclipse.jgit.util.sha1;version="[7.5.0,7.6.0)",
+ org.hamcrest;version="[3.0.0,4.0.0)",
+ org.hamcrest.collection;version="[3.0.0,4.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.experimental.theories;version="[4.13,5.0.0)",
org.junit.function;version="[4.13.0,5.0.0)",
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 80bd689..b340636 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
@@ -4,6 +4,7 @@
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC_REST;
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.INSERT;
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.UNREACHABLE_GARBAGE;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
@@ -18,9 +19,12 @@
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneOffset;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
import org.eclipse.jgit.internal.storage.commitgraph.CommitGraphWriter;
@@ -42,6 +46,7 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevBlob;
@@ -62,12 +67,15 @@ public class DfsGarbageCollectorTest {
private DfsObjDatabase odb;
private MockSystemReader mockSystemReader;
+ private static final ProgressMonitor NULL_PM = NullProgressMonitor.INSTANCE;
+
@Before
public void setUp() throws IOException {
DfsRepositoryDescription desc = new DfsRepositoryDescription("test");
git = new TestRepository<>(new InMemoryRepository(desc));
repo = git.getRepository();
odb = repo.getObjectDatabase();
+ odb.setUseMultipackIndex(true);
mockSystemReader = new MockSystemReader();
SystemReader.setInstance(mockSystemReader);
}
@@ -1227,6 +1235,117 @@ public void objectSizeIndex_unreachableGarbage_noIdx() throws Exception {
}
@Test
+ public void midx_oneMidx_deleteMidxs_allObjectsOneGC() throws Exception {
+ String master = "refs/heads/master";
+ RevCommit root = git.branch(master).commit().message("root").noParents()
+ .create();
+ git.branch(master).commit().message("commit on head")
+ .add("file.txt", git.blob("a blob")).parent(root).create();
+ assertEquals(3, countPacks(INSERT));
+
+ DfsPackDescription midx = DfsMidxWriter.writeMidx(
+ NullProgressMonitor.INSTANCE, odb,
+ Arrays.asList(odb.getPacks()), null);
+ odb.commitPack(List.of(midx), null);
+
+ gcNoTtl();
+
+ // Only one pack, is GC but not multipack index
+ assertEquals(1, odb.getPacks().length);
+ DfsPackDescription actualDesc = odb.getPacks()[0].getPackDescription();
+ assertEquals(GC, actualDesc.getPackSource());
+ assertFalse(actualDesc.hasFileExt(MULTI_PACK_INDEX));
+ DfsPackFile pack = odb.getPacks()[0];
+ assertFalse(pack instanceof DfsPackFileMidx);
+ assertTrue(isObjectInPack(root, pack));
+ }
+
+ @Test
+ public void midx_chainedMidx_deleteMidxs_allObjsInOneGC() throws Exception {
+ String master = "refs/heads/master";
+ List<RevCommit> knownCommits = new ArrayList<>(11);
+ RevCommit root = git.branch(master).commit().message("root").noParents()
+ .create();
+ knownCommits.add(root);
+ RevCommit tip = root;
+ for (int i = 0; i < 10; i++) {
+ tip = git.branch(master).commit().message("commit on head")
+ .add("file.txt", git.blob("a blob " + i)).parent(tip)
+ .create();
+ knownCommits.add(tip);
+ // Each of these creates two packs
+ }
+ assertEquals(21, countPacks(INSERT));
+
+ List<DfsPackFile> basicPacks = Arrays.stream(odb.getPacks())
+ .collect(Collectors.toUnmodifiableList());
+ DfsPackDescription midx = DfsMidxWriter.writeMidx(NULL_PM, odb,
+ basicPacks.subList(0, 9), null);
+ odb.commitPack(List.of(midx), null);
+
+ DfsPackDescription midx2 = DfsMidxWriter.writeMidx(NULL_PM, odb,
+ basicPacks.subList(9, 21), midx);
+ odb.commitPack(List.of(midx2), null);
+
+ // Verify we got one pack that is an midx
+ // This is testing the test code
+ assertEquals(1, odb.getPacks().length);
+ assertTrue(odb.getPacks()[0] instanceof DfsPackFileMidx);
+ DfsPackDescription theDesc = odb.getPacks()[0].getPackDescription();
+ assertTrue(theDesc.hasFileExt(MULTI_PACK_INDEX));
+ assertEquals(12, theDesc.getCoveredPacks().size());
+ assertEquals(theDesc.getMultiPackIndexBase(), midx);
+ assertEquals(9,
+ theDesc.getMultiPackIndexBase().getCoveredPacks().size());
+ gcNoTtl();
+
+ // One pack, GC WITHOUT multipack index, contains ALL objects
+ assertEquals(1, odb.getPacks().length);
+ DfsPackFile pack = odb.getPacks()[0];
+ assertEquals(GC, pack.getPackDescription().getPackSource());
+ assertFalse(pack instanceof DfsPackFileMidx);
+ assertFalse(pack.getPackDescription().hasFileExt(MULTI_PACK_INDEX));
+ for (RevCommit c : knownCommits) {
+ assertTrue(isObjectInPack(c, pack));
+ }
+ }
+
+ @Test
+ public void midx_packAndMidx_deleteMidxs_allObjectsOneGC()
+ throws Exception {
+ String master = "refs/heads/master";
+ RevCommit root = git.branch(master).commit().message("root").noParents()
+ .create();
+ RevCommit tip = git.branch(master).commit().message("commit on head")
+ .add("file.txt", git.blob("a blob")).parent(root).create();
+ assertEquals(3, countPacks(INSERT));
+
+ List<DfsPackFile> packs = Arrays.stream(odb.getPacks()).toList();
+ DfsPackDescription midx = DfsMidxWriter.writeMidx(NULL_PM, odb, packs,
+ null);
+ odb.commitPack(List.of(midx), null);
+
+ RevBlob blobOutOfMidx = git.blob("some content");
+ RevCommit commitOutOfMidx = git.branch(master).commit()
+ .message("an extra commit").add("other.txt", blobOutOfMidx)
+ .parent(tip).create();
+ assertEquals(3, odb.getPacks().length); // midx + 2 new packs
+ gcNoTtl();
+
+ // Only one pack, is GC but not multipack index
+ assertEquals(1, odb.getPacks().length);
+ DfsPackDescription actualDesc = odb.getPacks()[0].getPackDescription();
+ assertEquals(GC, actualDesc.getPackSource());
+ assertFalse(actualDesc.hasFileExt(MULTI_PACK_INDEX));
+
+ DfsPackFile pack = odb.getPacks()[0];
+ assertTrue(isObjectInPack(root, pack));
+ assertTrue(isObjectInPack(root, pack));
+ assertTrue(isObjectInPack(blobOutOfMidx, pack));
+ assertTrue(isObjectInPack(commitOutOfMidx, pack));
+ }
+
+ @Test
public void bitmapIndexWrittenDuringGc() throws Exception {
int numBranches = 2;
int commitsPerBranch = 50;
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabaseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabaseTest.java
new file mode 100644
index 0000000..c30753e
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabaseTest.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2025, Google LLC
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.COMPACT;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.INSERT;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DfsObjDatabaseTest {
+ InMemoryRepository db;
+
+ private static final DfsRepositoryDescription repoDesc = new DfsRepositoryDescription(
+ "test");
+
+ @Before
+ public void setUp() {
+ db = new InMemoryRepository(repoDesc);
+ }
+
+ @Test
+ public void getPacks_allInMidx_midxEnabled_onlyMidx() throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(true);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK);
+ DfsPackDescription compactTwoPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription multiPackIndex = pack("xxxx", GC, 104,
+ MULTI_PACK_INDEX);
+ multiPackIndex
+ .setCoveredPacks(List.of(gcPack, compactPack, compactTwoPack));
+
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, compactTwoPack, multiPackIndex),
+ Collections.emptyList());
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertPackList(packs, multiPackIndex);
+ }
+
+ @Test
+ public void getPacks_allInMidx_midxDisabled_packsNoMidx()
+ throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(false);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK);
+ DfsPackDescription compactTwoPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription multiPackIndex = pack("xxxx", GC, 104,
+ MULTI_PACK_INDEX);
+ multiPackIndex
+ .setCoveredPacks(List.of(gcPack, compactPack, compactTwoPack));
+
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, compactTwoPack, multiPackIndex),
+ Collections.emptyList());
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertPackList(packs, compactTwoPack, compactPack, gcPack);
+ }
+
+ @Test
+ public void getPacks_someInMidx_midxEnabled_midxPlusUncovered()
+ throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(true);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK);
+ DfsPackDescription insertPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription multiPackIndex = pack("xxxx", GC, 104,
+ MULTI_PACK_INDEX);
+ multiPackIndex.setCoveredPacks(List.of(gcPack, compactPack, insertPack));
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, insertPack, multiPackIndex),
+ null);
+
+ DfsPackDescription uncoveredPack = pack("dddd", COMPACT, 103, PACK);
+ db.getObjectDatabase().commitPack(List.of(uncoveredPack), null);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertPackList(packs, uncoveredPack, multiPackIndex);
+ }
+
+ @Test
+ public void getPacks_someInMidx_midxDisabled_packsNoMidx()
+ throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(false);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK);
+ DfsPackDescription insertPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription multiPackIndex = pack("xxxx", GC, 104,
+ MULTI_PACK_INDEX);
+ multiPackIndex
+ .setCoveredPacks(List.of(gcPack, compactPack, insertPack));
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, insertPack, multiPackIndex), null);
+
+ DfsPackDescription uncoveredPack = pack("dddd", COMPACT, 103, PACK);
+ db.getObjectDatabase().commitPack(List.of(uncoveredPack), null);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertPackList(packs, uncoveredPack, insertPack, compactPack, gcPack);
+ }
+
+ @Test
+ public void getPacks_midxChain_midxEnabled_topMidx() throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(true);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK);
+ DfsPackDescription insertPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription midxBase = pack("xxxx", GC, 104,
+ MULTI_PACK_INDEX);
+ midxBase.setCoveredPacks(List.of(gcPack, compactPack, insertPack));
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, insertPack, midxBase),
+ null);
+
+ DfsPackDescription insert1 = pack("insert1", INSERT, 105, PACK);
+ DfsPackDescription insert2 = pack("insert2", INSERT, 106, PACK);
+ DfsPackDescription midxTip = pack("xxx2", GC, 107, MULTI_PACK_INDEX);
+ midxTip.setCoveredPacks(List.of(insert1, insert2));
+ midxTip.setMultiPackIndexBase(midxBase);
+ db.getObjectDatabase().commitPack(List.of(insert1, insert2, midxTip), null);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertPackList(packs, midxTip);
+ }
+
+ @Test
+ public void getPacks_midxChain_midxDisabled_packsNoMidx()
+ throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(false);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK);
+ DfsPackDescription insertPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription midxBase = pack("xxxx", GC, 104, MULTI_PACK_INDEX);
+ midxBase.setCoveredPacks(List.of(gcPack, compactPack, insertPack));
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, insertPack, midxBase), null);
+
+ DfsPackDescription insert1 = pack("insert1", INSERT, 105, PACK);
+ DfsPackDescription insert2 = pack("insert2", INSERT, 106, PACK);
+ DfsPackDescription midxTip = pack("xxx2", GC, 107, MULTI_PACK_INDEX);
+ midxTip.setCoveredPacks(List.of(insert1, insert2));
+ midxTip.setMultiPackIndexBase(midxBase);
+ db.getObjectDatabase().commitPack(List.of(insert1, insert2, midxTip),
+ null);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertPackList(packs, insert2, insert1, insertPack, compactPack,
+ gcPack);
+ }
+
+ @Test
+ public void getReftables_multipleInsideMidx() throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(true);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK, REFTABLE);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK,
+ REFTABLE);
+ DfsPackDescription compactTwoPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription multiPackIndex = pack("xxxx", GC, 104,
+ MULTI_PACK_INDEX);
+ multiPackIndex
+ .setCoveredPacks(List.of(gcPack, compactPack, compactTwoPack));
+
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, compactTwoPack, multiPackIndex),
+ Collections.emptyList());
+
+ DfsReftable[] reftables = db.getObjectDatabase().getReftables();
+ assertReftableList(reftables, gcPack, compactPack);
+ }
+
+ @Test
+ public void getReftables_midxChain() throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(true);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK, REFTABLE);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK,
+ REFTABLE);
+ DfsPackDescription insertPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription midxBase = pack("xxxx", GC, 104, MULTI_PACK_INDEX);
+ midxBase.setCoveredPacks(List.of(gcPack, compactPack, insertPack));
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, insertPack, midxBase), null);
+
+ DfsPackDescription insert1 = pack("insert1", INSERT, 105, PACK,
+ REFTABLE);
+ DfsPackDescription insert2 = pack("insert2", INSERT, 106, PACK);
+ DfsPackDescription midxTip = pack("xxx2", GC, 107, MULTI_PACK_INDEX);
+ midxTip.setCoveredPacks(List.of(insert1, insert2));
+ midxTip.setMultiPackIndexBase(midxBase);
+ db.getObjectDatabase().commitPack(List.of(insert1, insert2, midxTip),
+ null);
+
+ DfsReftable[] reftables = db.getObjectDatabase().getReftables();
+ assertReftableList(reftables, gcPack, compactPack, insert1);
+ }
+
+ @Test
+ public void getReftables_inAndOutOfMidx() throws IOException {
+ db.getObjectDatabase().setUseMultipackIndex(true);
+
+ DfsPackDescription gcPack = pack("aaaa", GC, 100, PACK, REFTABLE);
+ DfsPackDescription compactPack = pack("cccc", COMPACT, 101, PACK);
+ DfsPackDescription insertPack = pack("bbbb", COMPACT, 102, PACK);
+
+ DfsPackDescription multiPackIndex = pack("xxxx", GC, 104,
+ MULTI_PACK_INDEX);
+ multiPackIndex
+ .setCoveredPacks(List.of(gcPack, compactPack, insertPack));
+ db.getObjectDatabase().commitPack(
+ List.of(gcPack, compactPack, insertPack, multiPackIndex), null);
+
+ DfsPackDescription uncoveredPack = pack("dddd", COMPACT, 103, PACK,
+ REFTABLE);
+ db.getObjectDatabase().commitPack(List.of(uncoveredPack), null);
+
+ DfsReftable[] reftables = db.getObjectDatabase().getReftables();
+ assertReftableList(reftables, gcPack, uncoveredPack);
+ }
+
+ private static DfsPackDescription pack(String name,
+ DfsObjDatabase.PackSource source, long timeMs, PackExt... ext) {
+ DfsPackDescription desc = new DfsPackDescription(repoDesc, name,
+ source);
+ desc.setLastModified(timeMs);
+ for (PackExt packExt : ext) {
+ desc.addFileExt(packExt);
+ }
+ return desc;
+ }
+
+ private static void assertPackList(DfsPackFile[] actual,
+ DfsPackDescription... expected) {
+ assertEquals(expected.length, actual.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals(expected[i], actual[i].getPackDescription());
+ }
+ }
+
+ private static void assertReftableList(DfsReftable[] actual,
+ DfsPackDescription... expected) {
+ assertEquals(expected.length, actual.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals(expected[i], actual[i].getPackDescription());
+ }
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackCompacterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackCompacterTest.java
index c3b6aa8..84505a8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackCompacterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackCompacterTest.java
@@ -14,6 +14,7 @@
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.INSERT;
import static org.eclipse.jgit.internal.storage.pack.PackExt.OBJECT_SIZE_INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -21,14 +22,20 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;
+import java.util.zip.Deflater;
+import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.junit.TestRng;
import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;
public class DfsPackCompacterTest {
+ private static final int AUTO_ADD_SIZE = 5 * 1024 * 1024; // 5 MiB
+
private TestRepository<InMemoryRepository> git;
private InMemoryRepository repo;
private DfsObjDatabase odb;
@@ -137,19 +144,62 @@ public void testObjectSizeIndexNotWritten() throws Exception {
assertFalse(compactPack.get().getPackDescription().hasFileExt(OBJECT_SIZE_INDEX));
}
+ @Test
+ public void testPrunePack() throws Exception {
+ ObjectId o1 = writePackWithRandomBlob(200);
+ ObjectId o2 = writePackWithRandomBlob(100);
+ ObjectId o3 = writePackWithRandomBlob(210);
+ DfsPackFile[] packsToCompact = odb.getPacks();
+
+ DfsPackCompactor compactor = new DfsPackCompactor(repo);
+ compactor.add(packsToCompact[1]);
+ compactor.add(packsToCompact[2]);
+ compactor.prune(packsToCompact[0]);
+
+ compactor.compact(null);
+
+ assertEquals(1, odb.getPacks().length);
+ assertFalse(odb.has(o3)); // pack with o3 was pruned
+ assertTrue(odb.has(o1));
+ assertTrue(odb.has(o2));
+ }
+
private TestRepository<InMemoryRepository>.CommitBuilder commit() {
return git.commit();
}
private void compact() throws IOException {
DfsPackCompactor compactor = new DfsPackCompactor(repo);
- compactor.autoAdd();
+ DfsObjDatabase objdb = repo.getObjectDatabase();
+ for (DfsPackFile pack : objdb.getPacks()) {
+ DfsPackDescription d = pack.getPackDescription();
+ if (d.getFileSize(PACK) < AUTO_ADD_SIZE) {
+ compactor.add(pack);
+ } else {
+ compactor.exclude(pack);
+ }
+ }
compactor.compact(null);
odb.clearCache();
}
private static void writeObjectSizeIndex(DfsRepository repo, boolean should) {
repo.getConfig().setInt(ConfigConstants.CONFIG_PACK_SECTION, null,
- ConfigConstants.CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX, should ? 0 : -1);
+ ConfigConstants.CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX,
+ should ? 0 : -1);
+ }
+
+ private ObjectId writePackWithBlob(byte[] data) throws IOException {
+ DfsInserter ins = (DfsInserter) repo.newObjectInserter();
+ ins.setCompressionLevel(Deflater.NO_COMPRESSION);
+ ObjectId blobId = ins.insert(OBJ_BLOB, data);
+ ins.flush();
+ return blobId;
+ }
+
+ // Do not use the size twice into the same test (it gives the same blob!)
+ private ObjectId writePackWithRandomBlob(int size) throws IOException {
+ byte[] data = new TestRng(JGitTestUtil.getName()).nextBytes(size);
+ return writePackWithBlob(data);
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxTest.java
index 998ea0d..3fd4e2c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxTest.java
@@ -29,6 +29,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -36,6 +37,7 @@
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.internal.storage.dfs.DfsPackFileMidx.VOffsetCalculator;
+import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
import org.eclipse.jgit.internal.storage.file.PackIndex;
import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.PackOffset;
import org.eclipse.jgit.internal.storage.midx.MultiPackIndexWriter;
@@ -302,36 +304,35 @@ public void midx_findOffset() throws IOException {
ObjectId o1 = writePackWithRandomBlob(100);
ObjectId o2 = writePackWithRandomBlob(200);
ObjectId o3 = writePackWithRandomBlob(150);
+ // Packs are written in the midx in reverse insertion time
DfsPackFileMidx midx = writeMultipackIndex();
DfsPackFile packOne = findPack(o1);
- long packOneSize = packOne.getPackDescription().getFileSize(PACK);
DfsPackFile packTwo = findPack(o2);
long packTwoSize = packTwo.getPackDescription().getFileSize(PACK);
DfsPackFile packThree = findPack(o3);
+ long packThreeSize = packThree.getPackDescription().getFileSize(PACK);
- // Packs have sequential names (pack-NN-INSERT) and midx uses pack-name
- // order. We rely on that to know the pack offsets
try (DfsReader ctx = db.getObjectDatabase().newReader()) {
long posOne = midx.findOffset(ctx, o1);
DfsPackFileMidx.DfsPackOffset po = midx.getOffsetCalculator()
.decode(posOne);
assertEquals(12, po.getPackOffset());
- assertEquals(0, po.getPackStart());
+ assertEquals(packThreeSize + packTwoSize, po.getPackStart());
assertEquals(packOne.getPackDescription(),
po.getPack().getPackDescription());
long posTwo = midx.findOffset(ctx, o2);
po = midx.getOffsetCalculator().decode(posTwo);
assertEquals(12, po.getPackOffset());
- assertEquals(packOneSize, po.getPackStart());
+ assertEquals(packThreeSize, po.getPackStart());
assertEquals(packTwo.getPackDescription(),
po.getPack().getPackDescription());
long posThree = midx.findOffset(ctx, o3);
po = midx.getOffsetCalculator().decode(posThree);
assertEquals(12, po.getPackOffset());
- assertEquals(packOneSize + packTwoSize, po.getPackStart());
+ assertEquals(0, po.getPackStart());
assertEquals(packThree.getPackDescription(),
po.getPack().getPackDescription());
@@ -420,15 +421,15 @@ public void midx_findAllFromPack() throws Exception {
true);
assertEquals(3, allFromPack.size());
- // Objects are in (pack, offset) order (i.e. pack)
+ // Objects are in (pack, offset) order (i.e. reverse pack insert)
DfsObjectToPack oneToPack = allFromPack.get(0);
- assertEquals(midx.findOffset(ctx, o1), oneToPack.getOffset());
+ assertEquals(midx.findOffset(ctx, o3), oneToPack.getOffset());
DfsObjectToPack twoToPack = allFromPack.get(1);
assertEquals(midx.findOffset(ctx, o2), twoToPack.getOffset());
DfsObjectToPack threeToPack = allFromPack.get(2);
- assertEquals(midx.findOffset(ctx, o3), threeToPack.getOffset());
+ assertEquals(midx.findOffset(ctx, o1), threeToPack.getOffset());
}
}
@@ -442,7 +443,7 @@ public void midx_findAllFromPack_withBase() throws Exception {
ObjectId o6 = writePackWithRandomBlob(600);
DfsPackFile[] packs = db.getObjectDatabase().getPacks();
- // Packs are in reverse insertion order
+ // Packs are in reverse insertion order (o6 -> o1)
DfsPackFileMidx midxBase = writeMultipackIndex(
Arrays.copyOfRange(packs, 3, 6), null);
DfsPackFileMidx midxTip = writeMultipackIndex(
@@ -461,24 +462,25 @@ public void midx_findAllFromPack_withBase() throws Exception {
otps, true);
assertEquals(6, allFromPack.size());
- // Objects are in (pack, offset) order (i.e. pack)
+ // Objects are in midx-offset order which is:
+ // base(o3 < o2 < o1) -> tip (06 < 05 < o4)
DfsObjectToPack oneToPack = allFromPack.get(0);
- assertEquals(midxTip.findOffset(ctx, o1), oneToPack.getOffset());
+ assertEquals(midxTip.findOffset(ctx, o3), oneToPack.getOffset());
DfsObjectToPack twoToPack = allFromPack.get(1);
assertEquals(midxTip.findOffset(ctx, o2), twoToPack.getOffset());
DfsObjectToPack threeToPack = allFromPack.get(2);
- assertEquals(midxTip.findOffset(ctx, o3), threeToPack.getOffset());
+ assertEquals(midxTip.findOffset(ctx, o1), threeToPack.getOffset());
DfsObjectToPack fourToPack = allFromPack.get(3);
- assertEquals(midxTip.findOffset(ctx, o4), fourToPack.getOffset());
+ assertEquals(midxTip.findOffset(ctx, o6), fourToPack.getOffset());
DfsObjectToPack fiveToPack = allFromPack.get(4);
assertEquals(midxTip.findOffset(ctx, o5), fiveToPack.getOffset());
DfsObjectToPack sixToPack = allFromPack.get(5);
- assertEquals(midxTip.findOffset(ctx, o6), sixToPack.getOffset());
+ assertEquals(midxTip.findOffset(ctx, o4), sixToPack.getOffset());
}
}
@@ -842,6 +844,92 @@ public void midx_fillRepresentation_withBase() throws Exception {
}
@Test
+ public void midx_getBitmapIndex() throws Exception {
+ RevCommit c1 = writePackWithCommit();
+ RevCommit c2 = writePackWithCommit();
+ gcWithBitmaps();
+
+ ObjectId blob = writePackWithRandomBlob(300);
+ DfsPackFileMidx dfsPackFileMidx = writeMultipackIndex();
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ PackBitmapIndex bitmapIndex = dfsPackFileMidx.getBitmapIndex(ctx);
+ assertNotNull(bitmapIndex);
+ // Both commits have same tree and blob
+ assertEquals(4, bitmapIndex.getObjectCount());
+ assertEquals(1, bitmapIndex.findPosition(c1));
+ assertEquals(0, bitmapIndex.findPosition(c2));
+ assertEquals(-1, bitmapIndex.findPosition(blob));
+ }
+ }
+
+ @Test
+ public void midx_getAllCoveredPacks() throws Exception {
+ writePackWithCommit();
+ writePackWithRandomBlob(300);
+ writePackWithRandomBlob(500);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(4, packs.length);
+ DfsPackFileMidx midx = writeMultipackIndex(packs, null);
+
+ assertEquals(4, midx.getAllCoveredPacks().size());
+ List<DfsPackDescription> expected = Arrays.stream(packs)
+ .map(p -> p.getPackDescription()).toList();
+ List<DfsPackDescription> actual = midx.getAllCoveredPacks().stream()
+ .map(DfsPackFile::getPackDescription).toList();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void midx_getAllCoveredPacks_withBase() throws Exception {
+ writePackWithCommit();
+ writePackWithRandomBlob(300);
+ writePackWithRandomBlob(500);
+ writePackWithRandomBlob(100);
+ writePackWithCommit();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(6, packs.length);
+ DfsPackFileMidx midxBase = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 4, 6), null);
+ DfsPackFileMidx midxMiddle = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 2, 4), midxBase);
+ DfsPackFileMidx midxTip = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 0, 2), midxMiddle);
+
+ assertEquals(6, midxTip.getAllCoveredPacks().size());
+ List<DfsPackDescription> expected = Arrays.stream(packs)
+ .map(DfsPackFile::getPackDescription).toList();
+ List<DfsPackDescription> actual = midxTip.getAllCoveredPacks().stream()
+ .map(DfsPackFile::getPackDescription).toList();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void midx_getCoveredPacks_withBase_onlyTopMidx() throws Exception {
+ writePackWithCommit();
+ writePackWithRandomBlob(300);
+ writePackWithRandomBlob(500);
+ writePackWithRandomBlob(100);
+ writePackWithCommit();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(6, packs.length);
+ DfsPackFileMidx midxBase = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 3, 6), null);
+ DfsPackFileMidx midxTip = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 0, 3), midxBase);
+
+ assertEquals(3, midxTip.getCoveredPacks().size());
+ List<DfsPackDescription> expected = Arrays
+ .stream(Arrays.copyOfRange(packs, 0, 3))
+ .map(DfsPackFile::getPackDescription).toList();
+ List<DfsPackDescription> actual = midxTip.getCoveredPacks().stream()
+ .map(DfsPackFile::getPackDescription).toList();
+ assertEquals(expected, actual);
+ }
+
+ @Test
public void midx_corrupt() throws Exception {
RevCommit commit = writePackWithCommit();
writePackWithRandomBlob(200);
@@ -1067,16 +1155,22 @@ private DfsPackFileMidx writeMultipackIndex() throws IOException {
return writeMultipackIndex(db.getObjectDatabase().getPacks(), null);
}
+ private void gcWithBitmaps() throws IOException {
+ DfsGarbageCollector garbageCollector = new DfsGarbageCollector(db);
+ garbageCollector.pack(NullProgressMonitor.INSTANCE);
+ }
+
private DfsPackFileMidx writeMultipackIndex(DfsPackFile[] packs,
DfsPackFileMidx base) throws IOException {
- Map<String, PackIndex> forMidx = new HashMap<>(packs.length);
- Map<String, DfsPackDescription> requiredPacks = new HashMap<>(
+ LinkedHashMap<String, PackIndex> forMidx = new LinkedHashMap<>(
+ packs.length);
+ Map<String, DfsPackDescription> descByName = new HashMap<>(
packs.length);
try (DfsReader ctx = db.getObjectDatabase().newReader()) {
for (DfsPackFile pack : packs) {
forMidx.put(pack.getPackDescription().getPackName(),
pack.getPackIndex(ctx));
- requiredPacks.put(pack.getPackDescription().getPackName(),
+ descByName.put(pack.getPackDescription().getPackName(),
pack.getPackDescription());
}
}
@@ -1087,7 +1181,7 @@ private DfsPackFileMidx writeMultipackIndex(DfsPackFile[] packs,
MultiPackIndexWriter.Result midxStats = w
.write(NullProgressMonitor.INSTANCE, out, forMidx);
desc.setCoveredPacks(midxStats.packNames().stream()
- .map(requiredPacks::get).toList());
+ .map(descByName::get).toList());
desc.addFileExt(PackExt.MULTI_PACK_INDEX);
}
db.getObjectDatabase().commitPack(List.of(desc), null);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackFilterTest.java
new file mode 100644
index 0000000..584bab1
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackFilterTest.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.COMPACT;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.INSERT;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.junit.Test;
+
+public class MidxPackFilterTest {
+ private static final DfsRepositoryDescription repoDesc = new DfsRepositoryDescription(
+ "test");
+
+ private static int timeCounter = 0;
+
+ @Test
+ public void useMidx_oneMidxCoversAll_onlyMidx() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription compactTwo = pack("bbbb", COMPACT, PACK);
+ DfsPackDescription midx = pack("midx", GC, MULTI_PACK_INDEX);
+ midx.setCoveredPacks(List.of(gc, compact, compactTwo));
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .useMidx(List.of(gc, compact, compactTwo, midx));
+ assertEquals(1, reorgPacks.size());
+ assertEquals(midx, reorgPacks.get(0));
+ }
+
+ @Test
+ public void useMidx_midxAndOneUncoveredPack_midxAndPack() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription compactTwo = pack("bbbb", COMPACT, PACK);
+ DfsPackDescription midx = pack("midx", GC, MULTI_PACK_INDEX);
+ midx.setCoveredPacks(List.of(gc, compact, compactTwo));
+
+ DfsPackDescription extra = pack("extra", COMPACT, PACK);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .useMidx(List.of(gc, compact, compactTwo, midx, extra));
+ assertEquals(2, reorgPacks.size());
+ assertTrue(reorgPacks.contains(midx));
+ assertTrue(reorgPacks.contains(extra));
+ }
+
+ @Test
+ public void useMidx_noMidx_allPacks() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription compactTwo = pack("bbbb", COMPACT, PACK);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .useMidx(List.of(gc, compact, compactTwo));
+ assertEquals(3, reorgPacks.size());
+ assertTrue(reorgPacks.contains(gc));
+ assertTrue(reorgPacks.contains(compact));
+ assertTrue(reorgPacks.contains(compactTwo));
+ }
+
+ @Test
+ public void useMidx_midxMissesOnePack_onlyPacks() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription compactTwo = pack("bbbb", COMPACT, PACK);
+ DfsPackDescription midx = pack("midx", GC, MULTI_PACK_INDEX);
+ midx.setCoveredPacks(List.of(gc, compact, compactTwo));
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .useMidx(List.of(gc, compactTwo, midx)); // compact missing
+ assertEquals(2, reorgPacks.size());
+ assertTrue(reorgPacks.contains(gc));
+ assertTrue(reorgPacks.contains(compactTwo));
+ }
+
+ @Test
+ public void useMidx_nestedMidx_onlyTopMidx() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription firstMidx = pack("midx1", GC, MULTI_PACK_INDEX);
+ firstMidx.setCoveredPacks(List.of(gc, compact));
+
+ DfsPackDescription compact2 = pack("dddd", COMPACT, PACK);
+ DfsPackDescription compact3 = pack("eeee", COMPACT, PACK);
+ DfsPackDescription topMidx = pack("midx2", GC, MULTI_PACK_INDEX);
+ topMidx.setCoveredPacks(List.of(compact2, compact3));
+ topMidx.setMultiPackIndexBase(firstMidx);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter.useMidx(
+ List.of(gc, compact, firstMidx, compact2, compact3, topMidx));
+ assertEquals(1, reorgPacks.size());
+ assertTrue(reorgPacks.contains(topMidx));
+ }
+
+ @Test
+ public void useMidx_nestedMidxAndOnePack_topMidxAndPack() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription firstMidx = pack("midx1", GC, MULTI_PACK_INDEX);
+ firstMidx.setCoveredPacks(List.of(gc, compact));
+
+ DfsPackDescription compact2 = pack("dddd", COMPACT, PACK);
+ DfsPackDescription compact3 = pack("eeee", COMPACT, PACK);
+ DfsPackDescription topMidx = pack("midx2", GC, MULTI_PACK_INDEX);
+ topMidx.setCoveredPacks(List.of(compact2, compact3));
+ topMidx.setMultiPackIndexBase(firstMidx);
+
+ DfsPackDescription uncovered = pack("uncovered", INSERT, PACK);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter.useMidx(List.of(gc,
+ compact, firstMidx, compact2, compact3, topMidx, uncovered));
+ assertEquals(2, reorgPacks.size());
+ assertTrue(reorgPacks.contains(topMidx));
+ assertTrue(reorgPacks.contains(uncovered));
+ }
+
+ @Test
+ public void skipMidx_oneMidxCoversAll_allPacks() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription compactTwo = pack("bbbb", COMPACT, PACK);
+ DfsPackDescription midx = pack("midx", GC, MULTI_PACK_INDEX);
+ midx.setCoveredPacks(List.of(gc, compact, compactTwo));
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .skipMidxs(List.of(gc, compact, compactTwo, midx));
+ assertEquals(3, reorgPacks.size());
+ assertTrue(reorgPacks.contains(gc));
+ assertTrue(reorgPacks.contains(compact));
+ assertTrue(reorgPacks.contains(compactTwo));
+ }
+
+ @Test
+ public void skipMidx_midxAndOneUncoveredPack_allPacks() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription compactTwo = pack("bbbb", COMPACT, PACK);
+ DfsPackDescription midx = pack("midx", GC, MULTI_PACK_INDEX);
+ midx.setCoveredPacks(List.of(gc, compact, compactTwo));
+
+ DfsPackDescription extra = pack("extra", COMPACT, PACK);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .skipMidxs(List.of(gc, compact, compactTwo, midx, extra));
+ assertEquals(4, reorgPacks.size());
+ assertTrue(reorgPacks.contains(gc));
+ assertTrue(reorgPacks.contains(compact));
+ assertTrue(reorgPacks.contains(compactTwo));
+ assertTrue(reorgPacks.contains(extra));
+ }
+
+ @Test
+ public void skipMidx_noMidx_allPacks() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription compactTwo = pack("bbbb", COMPACT, PACK);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .skipMidxs(List.of(gc, compact, compactTwo));
+ assertEquals(3, reorgPacks.size());
+ assertTrue(reorgPacks.contains(gc));
+ assertTrue(reorgPacks.contains(compact));
+ assertTrue(reorgPacks.contains(compactTwo));
+ }
+
+ @Test
+ public void skipMidx_nestedMidx_allPacks() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription firstMidx = pack("midx1", GC, MULTI_PACK_INDEX);
+ firstMidx.setCoveredPacks(List.of(gc, compact));
+
+ DfsPackDescription compact2 = pack("dddd", COMPACT, PACK);
+ DfsPackDescription compact3 = pack("eeee", COMPACT, PACK);
+ DfsPackDescription topMidx = pack("midx2", GC, MULTI_PACK_INDEX);
+ topMidx.setCoveredPacks(List.of(compact2, compact3));
+ topMidx.setMultiPackIndexBase(firstMidx);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter.skipMidxs(
+ List.of(gc, compact, firstMidx, compact2, compact3, topMidx));
+ assertEquals(4, reorgPacks.size());
+ assertTrue(reorgPacks.contains(gc));
+ assertTrue(reorgPacks.contains(compact));
+ assertTrue(reorgPacks.contains(compact2));
+ assertTrue(reorgPacks.contains(compact3));
+ }
+
+ @Test
+ public void skipMidx_nestedMidxAndOnePack_allPacks() {
+ DfsPackDescription gc = pack("aaaa", GC, PACK);
+ DfsPackDescription compact = pack("cccc", COMPACT, PACK);
+ DfsPackDescription firstMidx = pack("midx1", GC, MULTI_PACK_INDEX);
+ firstMidx.setCoveredPacks(List.of(gc, compact));
+
+ DfsPackDescription compact2 = pack("dddd", COMPACT, PACK);
+ DfsPackDescription compact3 = pack("eeee", COMPACT, PACK);
+ DfsPackDescription topMidx = pack("midx2", GC, MULTI_PACK_INDEX);
+ topMidx.setCoveredPacks(List.of(compact2, compact3));
+ topMidx.setMultiPackIndexBase(firstMidx);
+
+ DfsPackDescription uncovered = pack("uncovered", INSERT, PACK);
+
+ List<DfsPackDescription> reorgPacks = MidxPackFilter
+ .skipMidxs(List.of(gc, compact, firstMidx, compact2, compact3,
+ topMidx, uncovered));
+ assertEquals(5, reorgPacks.size());
+ assertTrue(reorgPacks.contains(gc));
+ assertTrue(reorgPacks.contains(compact));
+ assertTrue(reorgPacks.contains(compact2));
+ assertTrue(reorgPacks.contains(compact3));
+ assertTrue(reorgPacks.contains(uncovered));
+ }
+
+ private static DfsPackDescription pack(String name,
+ DfsObjDatabase.PackSource source, PackExt ext) {
+ DfsPackDescription desc = new DfsPackDescription(repoDesc, name,
+ source);
+ desc.setLastModified(timeCounter++);
+ desc.addFileExt(ext);
+ return desc;
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackListTest.java
new file mode 100644
index 0000000..6ab1156
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/MidxPackListTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static java.util.Arrays.asList;
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.zip.Deflater;
+
+import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.junit.TestRng;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MidxPackListTest {
+
+ InMemoryRepository db;
+
+ @Before
+ public void setUp() {
+ db = new InMemoryRepository(new DfsRepositoryDescription("test"));
+ db.getObjectDatabase().setUseMultipackIndex(true);
+ }
+
+ @Test
+ public void getAllPlainPacks_onlyPlain() throws IOException {
+ setupThreePacks();
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ MidxPackList packList = MidxPackList.create(packs);
+ assertEquals(3, packList.getAllPlainPacks().size());
+ }
+
+ @Test
+ public void getAllPlainPacks_onlyMidx() throws IOException {
+ setupThreePacksAndMidx();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(1, packs.length);
+ MidxPackList packList = MidxPackList.create(packs);
+ assertEquals(3, packList.getAllPlainPacks().size());
+ }
+
+ @Test
+ public void getAllPlainPacks_midxPlusOne() throws IOException {
+ setupThreePacksAndMidx();
+ writePackWithRandomBlob(60);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(2, packs.length);
+ MidxPackList packList = MidxPackList.create(packs);
+ assertEquals(4, packList.getAllPlainPacks().size());
+ }
+
+ @Test
+ public void getAllPlainPacks_nestedMidx() throws IOException {
+ setupSixPacksThreeMidx();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(1, packs.length);
+ MidxPackList packList = MidxPackList.create(packs);
+ assertEquals(6, packList.getAllPlainPacks().size());
+ }
+
+ @Test
+ public void getAllMidxPacks_onlyPlain() throws IOException {
+ setupThreePacks();
+
+ MidxPackList packList = MidxPackList
+ .create(db.getObjectDatabase().getPacks());
+ assertEquals(0, packList.getAllMidxPacks().size());
+ }
+
+ @Test
+ public void getAllMidxPacks_onlyMidx() throws IOException {
+ setupThreePacksAndMidx();
+
+ MidxPackList packList = MidxPackList
+ .create(db.getObjectDatabase().getPacks());
+ assertEquals(1, packList.getAllMidxPacks().size());
+ }
+
+ @Test
+ public void getAllMidxPacks_midxPlusOne() throws IOException {
+ setupThreePacksAndMidx();
+ writePackWithRandomBlob(60);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(2, packs.length);
+ MidxPackList packList = MidxPackList.create(packs);
+ assertEquals(1, packList.getAllMidxPacks().size());
+ }
+
+ @Test
+ public void getAllMidxPacks_nestedMidx() throws IOException {
+ setupSixPacksThreeMidx();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(1, packs.length);
+ MidxPackList packList = MidxPackList.create(packs);
+ assertEquals(3, packList.getAllMidxPacks().size());
+ }
+
+ @Test
+ public void findAllImpactedMidx_onlyPacks() throws IOException {
+ setupThreePacks();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ MidxPackList packList = MidxPackList
+ .create(db.getObjectDatabase().getPacks());
+ assertEquals(0, packList.findAllCoveringMidxs(asList(packs)).size());
+ }
+
+ @Test
+ public void findAllImpactedMidx_onlyMidx() throws IOException {
+ setupThreePacksAndMidx();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ MidxPackList packList = MidxPackList.create(packs);
+ List<DfsPackFile> covered = ((DfsPackFileMidx) packs[0])
+ .getAllCoveredPacks();
+ assertEquals(1, packList.findAllCoveringMidxs(covered.get(0)).size());
+ assertEquals(1, packList.findAllCoveringMidxs(covered.get(1)).size());
+ assertEquals(1, packList.findAllCoveringMidxs(covered.get(2)).size());
+
+ assertEquals("multiple packs covered", 1,
+ packList.findAllCoveringMidxs(covered.subList(0, 2)).size());
+ }
+
+ @Test
+ public void findAllImpactedMidx_midxPlusOne() throws IOException {
+ setupThreePacksAndMidx();
+ writePackWithRandomBlob(60);
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(2, packs.length);
+
+ DfsPackFile uncoveredPack = packs[0];
+ List<DfsPackFile> coveredPacks = ((DfsPackFileMidx) packs[1])
+ .getAllCoveredPacks();
+ assertEquals(3, coveredPacks.size());
+
+ MidxPackList packList = MidxPackList.create(packs);
+ assertEquals("one non covered", 0,
+ packList.findAllCoveringMidxs(uncoveredPack).size());
+ assertEquals("one and covered", 1,
+ packList.findAllCoveringMidxs(coveredPacks.get(1)).size());
+ assertEquals(
+ "two, only one covered", 1, packList
+ .findAllCoveringMidxs(
+ List.of(uncoveredPack, coveredPacks.get(2)))
+ .size());
+ }
+
+ @Test
+ public void findAllImpactedMidxs_nestedMidx() throws IOException {
+ setupSixPacksThreeMidx();
+
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(1, packs.length);
+ MidxPackList packList = MidxPackList.create(packs);
+ List<DfsPackFile> coveredPacks = ((DfsPackFileMidx) packs[0])
+ .getAllCoveredPacks();
+ assertEquals(6, coveredPacks.size());
+
+ assertEquals("one covered tip midx", 1,
+ packList.findAllCoveringMidxs(coveredPacks.get(0)).size());
+ assertEquals("one covered middle midx", 2,
+ packList.findAllCoveringMidxs(coveredPacks.get(2)).size());
+ assertEquals("one covered base midx", 3,
+ packList.findAllCoveringMidxs(coveredPacks.get(4)).size());
+ assertEquals(
+ "multiple covered in chain", 3, packList
+ .findAllCoveringMidxs(List.of(coveredPacks.get(1),
+ coveredPacks.get(2), coveredPacks.get(5)))
+ .size());
+ }
+
+
+
+ private void setupThreePacks() throws IOException {
+ writePackWithRandomBlob(100);
+ writePackWithRandomBlob(300);
+ writePackWithRandomBlob(50);
+ }
+
+ private void setupThreePacksAndMidx() throws IOException {
+ writePackWithRandomBlob(100);
+ writePackWithRandomBlob(300);
+ writePackWithRandomBlob(50);
+ writeMultipackIndex();
+ }
+
+ private void setupSixPacksThreeMidx() throws IOException {
+ writePackWithRandomBlob(100);
+ writePackWithRandomBlob(300);
+ writePackWithRandomBlob(50);
+ writePackWithRandomBlob(400);
+ writePackWithRandomBlob(130);
+ writePackWithRandomBlob(500);
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+ assertEquals(6, packs.length);
+ DfsPackFileMidx midxBase = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 4, 6), null);
+ DfsPackFileMidx midxMid = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 2, 4), midxBase);
+ writeMultipackIndex(Arrays.copyOfRange(packs, 0, 2), midxMid);
+ assertEquals("only top midx", 1,
+ db.getObjectDatabase().getPacks().length);
+ }
+
+ private void writeMultipackIndex() throws IOException {
+ writeMultipackIndex(db.getObjectDatabase().getPacks(), null);
+ }
+
+ private DfsPackFileMidx writeMultipackIndex(DfsPackFile[] packs,
+ DfsPackFileMidx base) throws IOException {
+ List<DfsPackFile> packfiles = asList(packs);
+ DfsPackDescription desc = DfsMidxWriter.writeMidx(
+ NullProgressMonitor.INSTANCE, db.getObjectDatabase(), packfiles,
+ base != null ? base.getPackDescription() : null);
+ db.getObjectDatabase().commitPack(List.of(desc), null);
+ return DfsPackFileMidx.create(DfsBlockCache.getInstance(), desc,
+ packfiles, base);
+ }
+
+ private ObjectId writePackWithBlob(byte[] data) throws IOException {
+ DfsInserter ins = (DfsInserter) db.newObjectInserter();
+ ins.setCompressionLevel(Deflater.NO_COMPRESSION);
+ ObjectId blobId = ins.insert(OBJ_BLOB, data);
+ ins.flush();
+ return blobId;
+ }
+
+ // Do not use the size twice into the same test (it gives the same blob!)
+ private ObjectId writePackWithRandomBlob(int size) throws IOException {
+ byte[] data = new TestRng(JGitTestUtil.getName()).nextBytes(size);
+ return writePackWithBlob(data);
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java
index 494f1d1..3c7e27d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java
@@ -17,8 +17,8 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
import org.eclipse.jgit.internal.storage.file.PackIndex;
import org.eclipse.jgit.junit.FakeIndexFactory;
@@ -64,8 +64,10 @@ public void load_validFile_basic_jgit() throws Exception {
new FakeIndexFactory.IndexObject(
"0000000000000000000000000000000000000012", 1502)));
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo, "p3",
- idxThree);
+ LinkedHashMap<String, PackIndex> packs = new LinkedHashMap<>(3);
+ packs.put("p1", idxOne);
+ packs.put("p2", idxTwo);
+ packs.put("p3", idxThree);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java
index 7af3f54..6436e31 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java
@@ -20,8 +20,8 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.internal.storage.file.PackIndex;
@@ -103,8 +103,8 @@ public void basicMidx() throws IOException {
new FakeIndexFactory.IndexObject(
"0000000000000000000000000000000000000012", 1502)));
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo, "p3",
- idxThree);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo, "p3", idxThree);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -140,7 +140,8 @@ public void jgit_largeOffsetChunk() throws IOException {
"0000000000000000000000000000000000000002", (1L << 35)),
new FakeIndexFactory.IndexObject(
"0000000000000000000000000000000000000003", 13)));
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -170,7 +171,8 @@ public void jgit_largeOffset_noChunk() throws IOException {
"0000000000000000000000000000000000000002", 501),
new FakeIndexFactory.IndexObject(
"0000000000000000000000000000000000000003", 13)));
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -206,7 +208,8 @@ public void jgit_resolve() throws IOException {
// Match
"32fe829a1c000000000000000000000000000010");
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -249,7 +252,8 @@ public void jgit_resolve_matchLimit() throws IOException {
// Match
"32fe829a1c000000000000000000000000000010");
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -283,7 +287,8 @@ public void jgit_resolve_noMatches() throws IOException {
"bbbbbb0000000000000000000000000000000003",
"32fe829a1c000000000000000000000000000010");
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -313,7 +318,8 @@ public void jgit_resolve_noMatches_last() throws IOException {
"bbbbbb0000000000000000000000000000000003",
"32fe829a1c000000000000000000000000000010");
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -334,7 +340,8 @@ public void jgit_resolve_empty() throws IOException {
PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -371,8 +378,8 @@ public void jgit_findPosition() throws IOException {
new FakeIndexFactory.IndexObject(
"0000000000000000000000000000000000000012", 1502)));
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo, "p3",
- idxThree);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo, "p3", idxThree);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -426,8 +433,8 @@ public void jgit_getObjectCount() throws IOException {
new FakeIndexFactory.IndexObject(
"0000000000000000000000000000000000000012", 1502)));
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo, "p3",
- idxThree);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo, "p3", idxThree);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -442,7 +449,8 @@ public void jgit_getObjectCount_emtpy() throws IOException {
PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = orderedMapOf("p1", idxOne,
+ "p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
@@ -472,4 +480,21 @@ private static void assertInIndex(MultiPackIndex midx, int expectedPackId,
packOffset.getPackId());
assertEquals(expectedOffset, packOffset.getOffset());
}
+
+ private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
+ PackIndex pi1, String s2, PackIndex pi2) {
+ LinkedHashMap<String, PackIndex> map = new LinkedHashMap<>(2);
+ map.put(s1, pi1);
+ map.put(s2, pi2);
+ return map;
+ }
+
+ private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
+ PackIndex pi1, String s2, PackIndex pi2, String s3, PackIndex pi3) {
+ LinkedHashMap<String, PackIndex> map = new LinkedHashMap<>(2);
+ map.put(s1, pi1);
+ map.put(s2, pi2);
+ map.put(s3, pi3);
+ return map;
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java
index 26353d8..9b085a3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java
@@ -22,8 +22,8 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
import org.eclipse.jgit.internal.storage.file.PackIndex;
import org.eclipse.jgit.junit.FakeIndexFactory;
@@ -46,8 +46,9 @@ public void write_allSmallOffsets() throws IOException {
object("0000000000000000000000000000000000000004", 1500),
object("0000000000000000000000000000000000000006", 3000));
- Map<String, PackIndex> data = Map.of("packname1", index1, "packname2",
- index2);
+ LinkedHashMap<String, PackIndex> data = new LinkedHashMap<>();
+ data.put("packname1", index1);
+ data.put("packname2", index2);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -75,13 +76,15 @@ public void write_smallOffset_limit() throws IOException {
PackIndex index1 = indexOf(
object("0000000000000000000000000000000000000001", 500),
object("0000000000000000000000000000000000000003", 1500),
- object("0000000000000000000000000000000000000005", (1L << 32) -1));
+ object("0000000000000000000000000000000000000005",
+ (1L << 32) - 1));
PackIndex index2 = indexOf(
object("0000000000000000000000000000000000000002", 500),
object("0000000000000000000000000000000000000004", 1500),
object("0000000000000000000000000000000000000006", 3000));
- Map<String, PackIndex> data =
- Map.of("packname1", index1, "packname2", index2);
+ LinkedHashMap<String, PackIndex> data = new LinkedHashMap<>(2);
+ data.put("packname1", index1);
+ data.put("packname2", index2);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -114,12 +117,14 @@ public void write_largeOffset() throws IOException {
object("0000000000000000000000000000000000000002", 500),
object("0000000000000000000000000000000000000004", 1500),
object("0000000000000000000000000000000000000006", 3000));
- Map<String, PackIndex> data =
- Map.of("packname1", index1, "packname2", index2);
+ LinkedHashMap<String, PackIndex> data = new LinkedHashMap<>(2);
+ data.put("bbbbbbbbb", index1);
+ data.put("aaaaaaaaa", index2);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
- writer.write(NullProgressMonitor.INSTANCE, out, data);
+ MultiPackIndexWriter.Result result = writer
+ .write(NullProgressMonitor.INSTANCE, out, data);
// header (12 bytes)
// + chunkHeader (7 * 12 bytes)
// + fanout table (256 * 4 bytes)
@@ -138,13 +143,18 @@ public void write_largeOffset() throws IOException {
assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_LARGEOFFSETS));
assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+
+ assertEquals("bbbbbbbbb", result.packNames().get(0));
+ assertEquals("aaaaaaaaa", result.packNames().get(1));
}
@Test
public void jgit_emptyMidx() throws IOException {
PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
- Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ LinkedHashMap<String, PackIndex> packs = new LinkedHashMap<>(2);
+ packs.put("p1", idxOne);
+ packs.put("p2", idxTwo);
MultiPackIndexWriter writer = new MultiPackIndexWriter();
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(NullProgressMonitor.INSTANCE, out, packs);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java
index 8218cbc..0eafdaf 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java
@@ -15,7 +15,7 @@
import java.util.Arrays;
import java.util.Iterator;
-import java.util.Map;
+import java.util.LinkedHashMap;
import org.eclipse.jgit.internal.storage.file.PackIndex;
import org.eclipse.jgit.junit.FakeIndexFactory;
@@ -39,7 +39,7 @@ public void rawIterator_noDuplicates() {
oidOffset("0000000000000000000000000000000000000007", 14),
oidOffset("0000000000000000000000000000000000000012", 1502));
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+ orderedMapOf("p1", idxOne, "p2", idxTwo, "p3", idxThree));
assertEquals(9, merger.getUniqueObjectCount());
assertEquals(3, merger.getPackCount());
assertFalse(merger.needsLargeOffsetsChunk());
@@ -60,13 +60,48 @@ public void rawIterator_noDuplicates() {
}
@Test
+ public void rawIterator_noDuplicates_honorPackOrder() {
+ PackIndex idxOne = indexOf(
+ oidOffset("0000000000000000000000000000000000000001", 500),
+ oidOffset("0000000000000000000000000000000000000005", 12),
+ oidOffset("0000000000000000000000000000000000000010", 1500));
+ PackIndex idxTwo = indexOf(
+ oidOffset("0000000000000000000000000000000000000002", 501),
+ oidOffset("0000000000000000000000000000000000000003", 13),
+ oidOffset("0000000000000000000000000000000000000015", 1501));
+ PackIndex idxThree = indexOf(
+ oidOffset("0000000000000000000000000000000000000004", 502),
+ oidOffset("0000000000000000000000000000000000000007", 14),
+ oidOffset("0000000000000000000000000000000000000012", 1502));
+ PackIndexMerger merger = new PackIndexMerger(
+ orderedMapOf("p3", idxThree, "p2", idxTwo, "p1", idxOne));
+ assertEquals(9, merger.getUniqueObjectCount());
+ assertEquals(3, merger.getPackCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator();
+ assertNextEntry(it, "0000000000000000000000000000000000000001", 2, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501);
+ assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13);
+ assertNextEntry(it, "0000000000000000000000000000000000000004", 0, 502);
+ assertNextEntry(it, "0000000000000000000000000000000000000005", 2, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000007", 0, 14);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 2,
+ 1500);
+ assertNextEntry(it, "0000000000000000000000000000000000000012", 0,
+ 1502);
+ assertNextEntry(it, "0000000000000000000000000000000000000015", 1,
+ 1501);
+ assertFalse(it.hasNext());
+ }
+
+ @Test
public void rawIterator_allDuplicates() {
PackIndex idxOne = indexOf(
oidOffset("0000000000000000000000000000000000000001", 500),
oidOffset("0000000000000000000000000000000000000005", 12),
oidOffset("0000000000000000000000000000000000000010", 1500));
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", idxOne, "p2", idxOne, "p3", idxOne));
+ orderedMapOf("p1", idxOne, "p2", idxOne, "p3", idxOne));
assertEquals(3, merger.getUniqueObjectCount());
assertEquals(3, merger.getPackCount());
assertFalse(merger.needsLargeOffsetsChunk());
@@ -101,7 +136,7 @@ public void bySha1Iterator_noDuplicates() {
oidOffset("0000000000000000000000000000000000000007", 14),
oidOffset("0000000000000000000000000000000000000012", 1502));
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+ orderedMapOf("p1", idxOne, "p2", idxTwo, "p3", idxThree));
assertEquals(9, merger.getUniqueObjectCount());
assertEquals(3, merger.getPackCount());
assertFalse(merger.needsLargeOffsetsChunk());
@@ -128,7 +163,7 @@ public void bySha1Iterator_allDuplicates() {
oidOffset("0000000000000000000000000000000000000005", 12),
oidOffset("0000000000000000000000000000000000000010", 1500));
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", idxOne, "p2", idxOne, "p3", idxOne));
+ orderedMapOf("p1", idxOne, "p2", idxOne, "p3", idxOne));
assertEquals(3, merger.getUniqueObjectCount());
assertEquals(3, merger.getPackCount());
assertFalse(merger.needsLargeOffsetsChunk());
@@ -152,7 +187,7 @@ public void bySha1Iterator_differentIndexSizes() {
oidOffset("0000000000000000000000000000000000000007", 12),
oidOffset("0000000000000000000000000000000000000012", 1500));
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+ orderedMapOf("p1", idxOne, "p2", idxTwo, "p3", idxThree));
assertEquals(6, merger.getUniqueObjectCount());
assertEquals(3, merger.getPackCount());
assertFalse(merger.needsLargeOffsetsChunk());
@@ -170,7 +205,7 @@ public void bySha1Iterator_differentIndexSizes() {
@Test
public void merger_noIndexes() {
- PackIndexMerger merger = new PackIndexMerger(Map.of());
+ PackIndexMerger merger = new PackIndexMerger(new LinkedHashMap<>());
assertEquals(0, merger.getUniqueObjectCount());
assertFalse(merger.needsLargeOffsetsChunk());
assertTrue(merger.getPackNames().isEmpty());
@@ -181,7 +216,7 @@ public void merger_noIndexes() {
@Test
public void merger_emptyIndexes() {
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", indexOf(), "p2", indexOf()));
+ orderedMapOf("p1", indexOf(), "p2", indexOf()));
assertEquals(0, merger.getUniqueObjectCount());
assertFalse(merger.needsLargeOffsetsChunk());
assertEquals(2, merger.getPackNames().size());
@@ -197,7 +232,7 @@ public void bySha1Iterator_largeOffsets_needsChunk() {
PackIndex idx2 = indexOf(oidOffset(
"0000000000000000000000000000000000000003", (1L << 31) + 10));
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", idx1, "p2", idx2));
+ orderedMapOf("p1", idx1, "p2", idx2));
assertTrue(merger.needsLargeOffsetsChunk());
assertEquals(2, merger.getOffsetsOver31BitsCount());
assertEquals(3, merger.getUniqueObjectCount());
@@ -213,7 +248,7 @@ public void bySha1Iterator_largeOffsets_noChunk() {
PackIndex idx2 = indexOf(oidOffset(
"0000000000000000000000000000000000000003", (1L << 31) + 10));
PackIndexMerger merger = new PackIndexMerger(
- Map.of("p1", idx1, "p2", idx2));
+ orderedMapOf("p1", idx1, "p2", idx2));
assertFalse(merger.needsLargeOffsetsChunk());
assertEquals(2, merger.getOffsetsOver31BitsCount());
assertEquals(3, merger.getUniqueObjectCount());
@@ -236,4 +271,22 @@ private static IndexObject oidOffset(String oid, long offset) {
private static PackIndex indexOf(IndexObject... objs) {
return FakeIndexFactory.indexOf(Arrays.asList(objs));
}
+
+ private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
+ PackIndex pi1, String s2, PackIndex pi2) {
+ LinkedHashMap map = new LinkedHashMap(3);
+ map.put(s1, pi1);
+ map.put(s2, pi2);
+ return map;
+ }
+
+ private static LinkedHashMap<String, PackIndex> orderedMapOf(String s1,
+ PackIndex pi1, String s2, PackIndex pi2, String s3, PackIndex pi3) {
+ LinkedHashMap map = new LinkedHashMap(3);
+ map.put(s1, pi1);
+ map.put(s2, pi2);
+ map.put(s3, pi3);
+ return map;
+ }
+
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateParserTest.java
index 5db4563..118ce18 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateParserTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateParserTest.java
@@ -57,6 +57,7 @@
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
+import java.util.List;
import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
@@ -364,6 +365,77 @@ public void testMissingPusheeField() throws Exception {
assertFalse(cert.toText().contains(PushCertificateParser.PUSHEE));
}
+ @Test
+ public void testWithPushOptions() throws Exception {
+ // Same cert as INPUT, but with push-option lines added after nonce
+ String inputWithOptions = "001ccertificate version 0.1\n"
+ + "0041pusher Dave Borowitz <dborowitz@google.com> 1433954361 -0700\n"
+ + "0024pushee git://localhost/repo.git\n"
+ + "002anonce 1433954361-bde756572d665bba81d8\n"
+ + "0024push-option label=Code-Review+2\n"
+ + "0021push-option label=Verified+1\n"
+ + "0017push-option submit\n"
+ + "0020push-option hashtag=bug fix\n"
+ + "0005\n"
+ + "00680000000000000000000000000000000000000000"
+ + " 6c2b981a177396fb47345b7df3e4d3f854c6bea7"
+ + " refs/heads/master\n"
+ + "0022-----BEGIN PGP SIGNATURE-----\n"
+ + "0016Version: GnuPG v1\n"
+ + "0005\n"
+ + "0045iQEcBAABAgAGBQJVeGg5AAoJEPfTicJkUdPkUggH/RKAeI9/i/LduuiqrL/SSdIa\n"
+ + "00459tYaSqJKLbXz63M/AW4Sp+4u+dVCQvnAt/a35CVEnpZz6hN4Kn/tiswOWVJf4CO7\n"
+ + "0045htNubGs5ZMwvD6sLYqKAnrM3WxV/2TbbjzjZW6Jkidz3jz/WRT4SmjGYiEO7aA+V\n"
+ + "00454ZdIS9f7sW5VsHHYlNThCA7vH8Uu48bUovFXyQlPTX0pToSgrWV3JnTxDNxfn3iG\n"
+ + "0045IL0zTY/qwVCdXgFownLcs6J050xrrBWIKqfcWr3u4D2aCLyR0v+S/KArr7ulZygY\n"
+ + "0045+SOklImn8TAZiNxhWtA6ens66IiammUkZYFv7SSzoPLFZT4dC84SmGPWgf94NoQ=\n"
+ + "000a=XFeC\n"
+ + "0020-----END PGP SIGNATURE-----\n"
+ + "0012push-cert-end\n";
+
+ PacketLineIn pckIn = newPacketLineIn(inputWithOptions);
+ PushCertificateParser parser =
+ new PushCertificateParser(db, newEnabledConfig());
+ parser.receiveHeader(pckIn, false);
+
+ parser.addCommand(pckIn.readString());
+ assertEquals(PushCertificateParser.BEGIN_SIGNATURE, pckIn.readString());
+ parser.receiveSignature(pckIn);
+
+ PushCertificate cert = parser.build();
+ assertNotNull(cert);
+ assertEquals("0.1", cert.getVersion());
+ assertEquals("Dave Borowitz", cert.getPusherIdent().getName());
+
+ // Verify push options were parsed and are available on the certificate
+ List<String> pushOptions = cert.getPushOptions();
+ assertEquals(4, pushOptions.size());
+ assertEquals("label=Code-Review+2", pushOptions.get(0));
+ assertEquals("label=Verified+1", pushOptions.get(1));
+ assertEquals("submit", pushOptions.get(2));
+ assertEquals("hashtag=bug fix", pushOptions.get(3));
+
+ // Verify that toText() includes push options (critical for signature verification)
+ String text = cert.toText();
+ assertTrue("toText() must include push-option lines",
+ text.contains("push-option label=Code-Review+2"));
+ assertTrue("toText() must include push-option lines",
+ text.contains("push-option label=Verified+1"));
+ assertTrue("toText() must include push-option lines",
+ text.contains("push-option submit"));
+ assertTrue("toText() must include push-option lines",
+ text.contains("push-option hashtag=bug fix"));
+
+ // Verify push options appear after nonce and before empty line
+ int nonceIndex = text.indexOf("nonce");
+ int pushOptionIndex = text.indexOf("push-option");
+ int emptyLineIndex = text.indexOf("\n\n");
+ assertTrue("push-option must appear after nonce",
+ pushOptionIndex > nonceIndex);
+ assertTrue("push-option must appear before empty line separator",
+ pushOptionIndex < emptyLineIndex);
+ }
+
private static String concatPacketLines(String input, int begin, int end)
throws IOException {
StringBuilder result = new StringBuilder();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackTest.java
index 156746d..595b970 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackTest.java
@@ -45,8 +45,15 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import org.eclipse.jgit.errors.PackProtocolException;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.transport.ReceiveCommand.Result;
import org.junit.Test;
/** Tests for receive-pack utilities. */
@@ -82,4 +89,62 @@ private void assertParseCommandFails(String input) {
// Expected.
}
}
+
+ @Test
+ public void testCertificatePushOptionsMismatch() throws Exception {
+ ReceiveCommand cmd1 = new ReceiveCommand(
+ ObjectId.fromString("0000000000000000000000000000000000000000"),
+ ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+ "refs/heads/master");
+ ReceiveCommand cmd2 = new ReceiveCommand(
+ ObjectId.fromString("0000000000000000000000000000000000000000"),
+ ObjectId.fromString("badc0ffebadc0ffebadc0ffebadc0ffebadc0ffe"),
+ "refs/heads/branch");
+
+ List<ReceiveCommand> commands = new ArrayList<>();
+ commands.add(cmd1);
+ commands.add(cmd2);
+
+ ReceivePack.validateCertificatePushOptions(
+ Arrays.asList("option1", "option2"),
+ Arrays.asList("option1", "different"), commands);
+
+ assertEquals(Result.REJECTED_OTHER_REASON, cmd1.getResult());
+ assertEquals(Result.REJECTED_OTHER_REASON, cmd2.getResult());
+ assertEquals(JGitText.get().pushCertificateInconsistentPushOptions,
+ cmd1.getMessage());
+ assertEquals(JGitText.get().pushCertificateInconsistentPushOptions,
+ cmd2.getMessage());
+ }
+
+ @Test
+ public void testCertificatePushOptionsMatch() throws Exception {
+ ReceiveCommand cmd = new ReceiveCommand(
+ ObjectId.fromString("0000000000000000000000000000000000000000"),
+ ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+ "refs/heads/master");
+
+ List<ReceiveCommand> commands = Collections.singletonList(cmd);
+
+ ReceivePack.validateCertificatePushOptions(
+ Arrays.asList("option1", "option2"),
+ Arrays.asList("option1", "option2"), commands);
+
+ assertEquals(Result.NOT_ATTEMPTED, cmd.getResult());
+ }
+
+ @Test
+ public void testCertificatePushOptionsNullTreatedAsEmpty() throws Exception {
+ ReceiveCommand cmd = new ReceiveCommand(
+ ObjectId.fromString("0000000000000000000000000000000000000000"),
+ ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+ "refs/heads/master");
+
+ List<ReceiveCommand> commands = Collections.singletonList(cmd);
+
+ ReceivePack.validateCertificatePushOptions(Collections.emptyList(),
+ null, commands);
+
+ assertEquals(Result.NOT_ATTEMPTED, cmd.getResult());
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/InterruptTimerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/InterruptTimerTest.java
new file mode 100644
index 0000000..68de7d6
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/InterruptTimerTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2025, NVIDIA CORPORATION
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.util.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class InterruptTimerTest {
+ private static final int MULTIPLIER = 1; // Increase if tests get flaky
+ private static final int BUFFER = 5; // Increase if tests get flaky
+ private static final int REPEATS = 100; // Increase to stress test more
+
+ private static final int TOO_LONG = 3 * MULTIPLIER + BUFFER;
+ private static final int SHORT_ENOUGH = 1 * MULTIPLIER;
+ private static final int TIMEOUT_LONG_ENOUGH = TOO_LONG;
+ private static final int TIMEOUT_TOO_SHORT = SHORT_ENOUGH;
+
+ private InterruptTimer timer;
+
+ @Before
+ public void setUp() {
+ timer = new InterruptTimer();
+ }
+
+ @After
+ public void tearDown() {
+ timer.terminate();
+ for (Thread t : active())
+ assertFalse(t instanceof InterruptTimer.AlarmThread);
+ }
+
+ @Test
+ public void testShortEnough() {
+ int interrupted = 0;
+ try {
+ timer.begin(TIMEOUT_LONG_ENOUGH);
+ Thread.sleep(SHORT_ENOUGH);
+ timer.end();
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ assertEquals("Was Not Interrupted", interrupted, 0);
+ }
+
+ @Test
+ public void testTooLong() {
+ int interrupted = 0;
+ try {
+ timer.begin(TIMEOUT_TOO_SHORT);
+ Thread.sleep(TOO_LONG);
+ timer.end();
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ assertEquals("Was Interrupted", interrupted, 1);
+ }
+
+ @Test
+ public void testNotInterruptedAfterEnd() {
+ int interrupted = 0;
+ try {
+ timer.begin(TIMEOUT_LONG_ENOUGH);
+ Thread.sleep(SHORT_ENOUGH);
+ timer.end();
+ Thread.sleep(TIMEOUT_LONG_ENOUGH * 3);
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ assertEquals("Was Not Interrupted Even After End", interrupted, 0);
+ }
+
+ @Test
+ public void testRestartBeforeTimeout() {
+ int interrupted = 0;
+ try {
+ timer.begin(TIMEOUT_LONG_ENOUGH * 2);
+ Thread.sleep(SHORT_ENOUGH);
+ timer.end();
+ timer.begin(TIMEOUT_LONG_ENOUGH);
+ Thread.sleep(SHORT_ENOUGH);
+ timer.end();
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ assertEquals("Was Not Interrupted Even When Restarted Before Timeout", interrupted, 0);
+ }
+
+ @Test
+ public void testSecondExpiresBeforeFirst() {
+ int interrupted = 0;
+ try {
+ timer.begin(TIMEOUT_LONG_ENOUGH * 3);
+ Thread.sleep(SHORT_ENOUGH);
+ timer.end();
+ timer.begin(TIMEOUT_TOO_SHORT);
+ Thread.sleep(TOO_LONG);
+ timer.end();
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ assertEquals("Was Interrupted Even When Second Timeout Expired Before First", interrupted, 1);
+ }
+
+ @Test
+ public void testRepeatedShortEnough() {
+ int interrupted = 0;
+ for (int i = 0; i < REPEATS; i++) {
+ try {
+ timer.begin(TIMEOUT_LONG_ENOUGH);
+ Thread.sleep(SHORT_ENOUGH);
+ timer.end();
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ }
+ assertEquals("Was Never Interrupted", interrupted, 0);
+ }
+
+ @Test
+ public void testRepeatedTooLong() {
+ int interrupted = 0;
+ for (int i = 0; i < REPEATS; i++) {
+ try {
+ timer.begin(TIMEOUT_TOO_SHORT);
+ Thread.sleep(TOO_LONG);
+ timer.end();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ interrupted++;
+ }
+ }
+ assertEquals("Was always Interrupted", interrupted, REPEATS);
+ }
+
+ @Test
+ public void testRepeatedShortThanTooLong() {
+ int interrupted = 0;
+ for (int i = 0; i < REPEATS; i++) {
+ try {
+ timer.begin(TIMEOUT_LONG_ENOUGH);
+ Thread.sleep(SHORT_ENOUGH);
+ timer.end();
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ }
+ assertEquals("Was Not Interrupted Early", interrupted, 0);
+ try {
+ timer.begin(TIMEOUT_TOO_SHORT);
+ Thread.sleep(TOO_LONG);
+ timer.end();
+ } catch (InterruptedException e) {
+ interrupted++;
+ }
+ assertEquals("Was Interrupted On Long", interrupted, 1);
+ }
+
+ private static List<Thread> active() {
+ Thread[] all = new Thread[16];
+ int n = Thread.currentThread().getThreadGroup().enumerate(all);
+ while (n == all.length) {
+ all = new Thread[all.length * 2];
+ n = Thread.currentThread().getThreadGroup().enumerate(all);
+ }
+ return Arrays.asList(all).subList(0, n);
+ }
+}
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index f0cf71d..d760003 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -103,9 +103,12 @@
org.eclipse.jgit.junit.http,
org.eclipse.jgit.http.server,
org.eclipse.jgit.lfs,
+ org.eclipse.jgit.lfs.test,
org.eclipse.jgit.pgm,
org.eclipse.jgit.pgm.test,
- org.eclipse.jgit.ssh.apache",
+ org.eclipse.jgit.ssh.apache,
+ org.eclipse.jgit.ssh.apache.test,
+ org.eclipse.jgit.ssh.jsch.test",
org.eclipse.jgit.internal.storage.io;version="7.5.0";
x-friends:="org.eclipse.jgit.junit,
org.eclipse.jgit.test,
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 e24cba6..6158032 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -638,6 +638,7 @@
pushCertificateInvalidFieldValue=Push certificate has missing or invalid value for {0}: {1}
pushCertificateInvalidHeader=Push certificate has invalid header format
pushCertificateInvalidSignature=Push certificate has invalid signature format
+pushCertificateInconsistentPushOptions=Push certificate push options do not match command push options
pushDefaultNothing=No refspec given and push.default=nothing; no upstream branch can be determined
pushDefaultNoUpstream=No upstream branch found for local branch ''{0}''
pushDefaultSimple=push.default=simple requires local branch name ''{0}'' to be equal to upstream tracked branch name ''{1}''
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 8928f47..9bd99ed 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -669,6 +669,7 @@ public static JGitText get() {
/***/ public String pushCertificateInvalidFieldValue;
/***/ public String pushCertificateInvalidHeader;
/***/ public String pushCertificateInvalidSignature;
+ /***/ public String pushCertificateInconsistentPushOptions;
/***/ public String pushDefaultNothing;
/***/ public String pushDefaultNoUpstream;
/***/ public String pushDefaultSimple;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java
index 199481c..78d65b5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java
@@ -18,6 +18,7 @@
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.UNREACHABLE_GARBAGE;
import static org.eclipse.jgit.internal.storage.dfs.DfsPackCompactor.configureReftable;
import static org.eclipse.jgit.internal.storage.pack.PackExt.COMMIT_GRAPH;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.OBJECT_SIZE_INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;
@@ -25,6 +26,7 @@
import java.io.IOException;
import java.time.Instant;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -33,6 +35,7 @@
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
+import java.util.Queue;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -95,6 +98,8 @@ public class DfsGarbageCollector {
private List<DfsReftable> reftablesBefore;
private List<DfsPackFile> expiredGarbagePacks;
+ private List<DfsPackFileMidx> existingMidxs;
+
private Collection<Ref> refsBefore;
private Set<ObjectId> allHeadsAndTags;
private Set<ObjectId> allTags;
@@ -431,9 +436,11 @@ private Collection<Ref> getAllRefs() throws IOException {
}
private void readPacksBefore() throws IOException {
- DfsPackFile[] packs = objdb.getPacks();
- packsBefore = new ArrayList<>(packs.length);
- expiredGarbagePacks = new ArrayList<>(packs.length);
+ DfsPackFile[] rawPacks = objdb.getPacks();
+ List<DfsPackFile> packs = getPlainPacks(rawPacks);
+ existingMidxs = getMidxPacks(rawPacks);
+ packsBefore = new ArrayList<>(packs.size());
+ expiredGarbagePacks = new ArrayList<>(packs.size());
long now = SystemReader.getInstance().now().toEpochMilli();
for (DfsPackFile p : packs) {
@@ -448,6 +455,41 @@ private void readPacksBefore() throws IOException {
}
}
+ private static List<DfsPackFile> getPlainPacks(DfsPackFile[] packs) {
+ List<DfsPackFile> plainPacks = new ArrayList<>();
+ Queue<DfsPackFile> pending = new ArrayDeque<>(
+ Arrays.stream(packs).toList());
+ while (!pending.isEmpty()) {
+ DfsPackFile pack = pending.poll();
+ if (pack instanceof DfsPackFileMidx midxPack) {
+ plainPacks.addAll(midxPack.getCoveredPacks());
+ if (midxPack.getMultipackIndexBase() != null) {
+ pending.add(midxPack.getMultipackIndexBase());
+ }
+ } else {
+ plainPacks.add(pack);
+ }
+ }
+ return plainPacks;
+ }
+
+ private static List<DfsPackFileMidx> getMidxPacks(DfsPackFile[] packs) {
+ List<DfsPackFileMidx> topLevelMidxs = Arrays.stream(packs).filter(
+ p -> p.getPackDescription().hasFileExt(MULTI_PACK_INDEX))
+ .map(p -> (DfsPackFileMidx) p).toList();
+
+ List<DfsPackFileMidx> midxPacks = new ArrayList<>();
+ Queue<DfsPackFileMidx> pending = new ArrayDeque<>(topLevelMidxs);
+ while (!pending.isEmpty()) {
+ DfsPackFileMidx midx = pending.poll();
+ midxPacks.add(midx);
+ if (midx.getMultipackIndexBase() != null) {
+ pending.add(midx.getMultipackIndexBase());
+ }
+ }
+ return midxPacks;
+ }
+
private void readReftablesBefore() throws IOException {
DfsReftable[] tables = objdb.getReftables();
reftablesBefore = new ArrayList<>(Arrays.asList(tables));
@@ -568,6 +610,11 @@ private Set<DfsPackDescription> toPrune() {
for (DfsPackFile pack : expiredGarbagePacks) {
toPrune.add(pack.getPackDescription());
}
+
+ for (DfsPackFileMidx pack : existingMidxs) {
+ toPrune.add(pack.getPackDescription());
+ }
+
return toPrune;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriter.java
new file mode 100644
index 0000000..28ef98d
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsMidxWriter.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndexWriter;
+import org.eclipse.jgit.lib.ProgressMonitor;
+
+/**
+ * Create a pack with a multipack index, setting the required fields in the
+ * description.
+ */
+public class DfsMidxWriter {
+
+ private DfsMidxWriter() {
+ }
+
+ /**
+ * Create a pack with the multipack index
+ *
+ * @param pm
+ * a progress monitor
+ * @param objdb
+ * an object database
+ * @param packs
+ * the packs to cover
+ * @param base
+ * parent of this midx in the chain (if any).
+ * @return a pack (uncommitted) with the multipack index of the packs passed
+ * as parameter.
+ * @throws IOException
+ * an error opening the packs or writing the stream.
+ */
+ public static DfsPackDescription writeMidx(ProgressMonitor pm,
+ DfsObjDatabase objdb, List<DfsPackFile> packs,
+ @Nullable DfsPackDescription base) throws IOException {
+ LinkedHashMap<String, PackIndex> inputs = new LinkedHashMap<>(
+ packs.size());
+ try (DfsReader ctx = objdb.newReader()) {
+ for (DfsPackFile pack : packs) {
+ inputs.put(pack.getPackDescription().getPackName(),
+ pack.getPackIndex(ctx));
+ }
+ }
+
+ DfsPackDescription midxPackDesc = objdb.newPack(GC);
+ try (DfsOutputStream out = objdb.writeFile(midxPackDesc,
+ MULTI_PACK_INDEX)) {
+ MultiPackIndexWriter w = new MultiPackIndexWriter();
+ MultiPackIndexWriter.Result result = w.write(pm, out, inputs);
+ midxPackDesc.addFileExt(MULTI_PACK_INDEX);
+ midxPackDesc.setObjectCount(result.objectCount());
+
+ Map<String, DfsPackDescription> byName = packs.stream()
+ .map(DfsPackFile::getPackDescription)
+ .collect(toMap(DfsPackDescription::getPackName,
+ Function.identity()));
+ List<DfsPackDescription> coveredPacks = result.packNames().stream()
+ .map(byName::get).collect(toList());
+ midxPackDesc.setCoveredPacks(coveredPacks);
+ if (base != null) {
+ midxPackDesc.setMultiPackIndexBase(base);
+ }
+ }
+
+ return midxPackDesc;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java
index 1a873d1..7b7a378 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java
@@ -13,13 +13,14 @@
import static java.util.stream.Collectors.joining;
import static org.eclipse.jgit.internal.storage.pack.PackExt.BITMAP_INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.INDEX;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@@ -27,13 +28,15 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
import org.eclipse.jgit.internal.storage.file.BasePackIndexWriter;
import org.eclipse.jgit.internal.storage.file.PackBitmapIndexWriterV1;
-import org.eclipse.jgit.internal.storage.pack.PackIndexWriter;
import org.eclipse.jgit.internal.storage.pack.PackBitmapIndexWriter;
import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.eclipse.jgit.internal.storage.pack.PackIndexWriter;
import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.ObjectDatabase;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
@@ -198,6 +201,8 @@ public String toString() {
private Comparator<DfsPackDescription> packComparator;
+ private boolean useMultipackIndex;
+
/**
* Initialize an object database for our repository.
*
@@ -212,6 +217,9 @@ protected DfsObjDatabase(DfsRepository repository,
this.packList = new AtomicReference<>(NO_PACKS);
this.readerOptions = options;
this.packComparator = DfsPackDescription.objectLookupComparator();
+ this.useMultipackIndex = repository.getConfig().getBoolean(
+ ConfigConstants.CONFIG_CORE_SECTION,
+ ConfigConstants.CONFIG_KEY_MULTIPACKINDEX, false);
}
/**
@@ -249,6 +257,28 @@ public ObjectInserter newInserter() {
}
/**
+ * Whether to use multipack indexes in the list of packs
+ * <p>
+ * This overrides the value in the core.multiPackIndex config key read at
+ * construction time.
+ *
+ * @param value
+ * value to set in the flag
+ */
+ public void setUseMultipackIndex(boolean value) {
+ this.useMultipackIndex = value;
+ }
+
+ /**
+ * Should this object db return multipack indexes
+ *
+ * @return current value of the flag
+ */
+ protected boolean useMultipackIndex() {
+ return this.useMultipackIndex;
+ }
+
+ /**
* Scan and list all available pack files in the repository.
*
* @return list of available packs. The returned array is shared with the
@@ -455,6 +485,11 @@ protected abstract void commitPackImpl(Collection<DfsPackDescription> desc,
* The returned list must support random access and must be mutable by the
* caller. It is sorted in place using the natural sorting of the returned
* DfsPackDescription objects.
+ * <p>
+ * With multipack index enabled, this method returns the descriptions of the
+ * multipack index(es) (which include descriptions of covered packs) and of
+ * packs not covered by the midxs. With multipack index disabled, it returns
+ * only regular packs (the midx is just ignored).
*
* @return available packs. May be empty if there are no packs.
* @throws java.io.IOException
@@ -579,10 +614,10 @@ private PackList scanPacksImpl(PackList old) throws IOException {
Map<DfsPackDescription, DfsReftable> reftables = reftableMap(old);
List<DfsPackDescription> scanned = listPacks();
- Collections.sort(scanned, packComparator);
+ scanned.sort(packComparator);
List<DfsPackFile> newPacks = new ArrayList<>(scanned.size());
- List<DfsReftable> newReftables = new ArrayList<>(scanned.size());
+ List<DfsPackDescription> packsWithReftables = new ArrayList<>();
boolean foundNew = false;
for (DfsPackDescription dsc : scanned) {
DfsPackFile oldPack = packs.remove(dsc);
@@ -591,8 +626,20 @@ private PackList scanPacksImpl(PackList old) throws IOException {
} else if (dsc.hasFileExt(PackExt.PACK)) {
newPacks.add(createDfsPackFile(cache, dsc));
foundNew = true;
+ } else if (dsc.hasFileExt(MULTI_PACK_INDEX)) {
+ newPacks.add(
+ createDfsPackFileMidx(cache, dsc, packsWithReftables));
+ foundNew = true;
}
+ if (dsc.hasFileExt(REFTABLE)) {
+ packsWithReftables.add(dsc);
+ }
+ }
+
+ List<DfsReftable> newReftables = new ArrayList<>(
+ packsWithReftables.size());
+ for (DfsPackDescription dsc : packsWithReftables) {
DfsReftable oldReftable = reftables.remove(dsc);
if (oldReftable != null) {
newReftables.add(oldReftable);
@@ -607,7 +654,7 @@ private PackList scanPacksImpl(PackList old) throws IOException {
if (!foundNew) {
return old;
}
- Collections.sort(newReftables, reftableComparator());
+ newReftables.sort(reftableComparator());
return new PackList(
newPacks.toArray(new DfsPackFile[0]),
newReftables.toArray(new DfsReftable[0]));
@@ -615,7 +662,7 @@ private PackList scanPacksImpl(PackList old) throws IOException {
/**
* Create instances of DfsPackFile
- *
+ * <p>
* Implementors can decide to construct or wrap DfsPackFile in different
* ways.
*
@@ -630,6 +677,38 @@ protected DfsPackFile createDfsPackFile(DfsBlockCache cache,
return new DfsPackFile(cache, dsc);
}
+ /**
+ * Create instances of DfsPackFileMidx
+ *
+ * @param cache
+ * block cache
+ * @param dsc
+ * pack description
+ * @param containsReftables
+ * used to return packs inside this midx that also have reftables
+ *
+ * @return the dfs packfile
+ */
+ protected DfsPackFileMidx createDfsPackFileMidx(DfsBlockCache cache,
+ DfsPackDescription dsc,
+ List<DfsPackDescription> containsReftables) {
+ DfsPackFileMidx base = null;
+ if (dsc.getMultiPackIndexBase() != null) {
+ // The base is always a multipack index
+ base = createDfsPackFileMidx(cache, dsc.getMultiPackIndexBase(),
+ containsReftables);
+ }
+ // A pack shouldn't be in the pack list and inside a multipack index
+ // at the same time. In that case, we will have it under two
+ // different DfsPackFile instances.
+ List<DfsPackFile> coveredPacks = dsc.getCoveredPacks().stream()
+ .map(desc -> createDfsPackFile(cache, desc))
+ .collect(Collectors.toUnmodifiableList());
+ dsc.getCoveredPacks().stream().filter(d -> d.hasFileExt(REFTABLE))
+ .forEach(containsReftables::add);
+ return DfsPackFileMidx.create(cache, dsc, coveredPacks, base);
+ }
+
private static Map<DfsPackDescription, DfsPackFile> packMap(PackList old) {
Map<DfsPackDescription, DfsPackFile> forReuse = new HashMap<>();
for (DfsPackFile p : old.packs) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
index 6339b03..8860cce 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java
@@ -11,7 +11,6 @@
package org.eclipse.jgit.internal.storage.dfs;
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.COMPACT;
-import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
import static org.eclipse.jgit.internal.storage.pack.PackExt.OBJECT_SIZE_INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;
@@ -68,10 +67,11 @@ public class DfsPackCompactor {
private final List<DfsReftable> srcReftables;
private final List<ObjectIdSet> exclude;
+ private final List<DfsPackDescription> prune;
+
private PackStatistics newStats;
private DfsPackDescription outDesc;
- private int autoAddSize;
private ReftableConfig reftableConfig;
private RevWalk rw;
@@ -86,10 +86,10 @@ public class DfsPackCompactor {
*/
public DfsPackCompactor(DfsRepository repository) {
repo = repository;
- autoAddSize = 5 * 1024 * 1024; // 5 MiB
srcPacks = new ArrayList<>();
srcReftables = new ArrayList<>();
exclude = new ArrayList<>(4);
+ prune = new ArrayList<>();
}
/**
@@ -135,38 +135,6 @@ public DfsPackCompactor add(DfsReftable table) {
}
/**
- * Automatically select pack and reftables to be included, and add them.
- * <p>
- * Packs are selected based on size, smaller packs get included while bigger
- * ones are omitted.
- *
- * @return {@code this}
- * @throws java.io.IOException
- * existing packs cannot be read.
- */
- public DfsPackCompactor autoAdd() throws IOException {
- DfsObjDatabase objdb = repo.getObjectDatabase();
- for (DfsPackFile pack : objdb.getPacks()) {
- DfsPackDescription d = pack.getPackDescription();
- if (d.getFileSize(PACK) < autoAddSize)
- add(pack);
- else
- exclude(pack);
- }
-
- if (reftableConfig != null) {
- for (DfsReftable table : objdb.getReftables()) {
- DfsPackDescription d = table.getPackDescription();
- if (d.getPackSource() != GC
- && d.getFileSize(REFTABLE) < autoAddSize) {
- add(table);
- }
- }
- }
- return this;
- }
-
- /**
* Exclude objects from the compacted pack.
*
* @param set
@@ -188,11 +156,23 @@ public DfsPackCompactor exclude(ObjectIdSet set) {
* pack index cannot be loaded.
*/
public DfsPackCompactor exclude(DfsPackFile pack) throws IOException {
- final PackIndex idx;
+ final ObjectIdSet objectIdSet;
try (DfsReader ctx = (DfsReader) repo.newObjectReader()) {
- idx = pack.getPackIndex(ctx);
+ objectIdSet = pack.asObjectIdSet(ctx);
}
- return exclude(idx);
+ return exclude(objectIdSet);
+ }
+
+ /**
+ * Delete also this pack when writing to the db the compacted packs
+ *
+ * @param pack
+ * a pack to delete
+ * @return {@code this}
+ */
+ public DfsPackCompactor prune(DfsPackFile pack) {
+ prune.add(pack.getPackDescription());
+ return this;
}
/**
@@ -367,6 +347,7 @@ private Collection<DfsPackDescription> toPrune() {
Set<DfsPackDescription> toPrune = new HashSet<>();
toPrune.addAll(packs);
toPrune.addAll(reftables);
+ toPrune.addAll(prune);
return toPrune;
}
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 3aacdc2..ecc97e9 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
@@ -37,6 +37,7 @@
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
+import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
@@ -57,9 +58,11 @@
import org.eclipse.jgit.internal.storage.pack.StoredObjectRepresentation;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.BitmapIndex;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdSet;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
@@ -251,6 +254,22 @@ public PackIndex getPackIndex(DfsReader ctx) throws IOException {
return idx(ctx);
}
+ /**
+ * Get a view of this packfile as a set of objects
+ * <p>
+ * To use when the caller only needs to check inclusion (without specific
+ * order or getting offsets).
+ *
+ * @param ctx
+ * reader context
+ * @return a view of this packfile as a set of objects
+ * @throws IOException
+ * cannot load the backing data from storage
+ */
+ public ObjectIdSet asObjectIdSet(DfsReader ctx) throws IOException {
+ return idx(ctx);
+ }
+
private PackIndex idx(DfsReader ctx) throws IOException {
if (index != null) {
return index;
@@ -1204,6 +1223,34 @@ long getIndexedObjectSize(DfsReader ctx, int idxPosition)
}
/**
+ * Return pack(s) with all its objects included in the bitmap.
+ * <p>
+ * The bitmap is modified removing the objects in the returned packs.
+ * <p>
+ * The list could contain more than one pack in the multipack-index case.
+ *
+ * @param ctx
+ * a reader
+ * @param need
+ * bitmap with the required objects. It can be modified in this
+ * call. The objects from the returned packs are removed from the
+ * bitmap.
+ * @return list of packs with ALL their objects in the bitmap.
+ * @throws IOException
+ * error reading the bitmap index.
+ */
+ @NonNull
+ List<DfsPackFile> fullyIncludedIn(DfsReader ctx,
+ BitmapIndex.BitmapBuilder need) throws IOException {
+ PackBitmapIndex bi = this.getBitmapIndex(ctx);
+ if (bi != null && need.removeAllOrNone(bi)) {
+ return Collections.singletonList(this);
+ }
+
+ return Collections.emptyList();
+ }
+
+ /**
* Populates the representation object with the details of how the object at
* "pos" is stored in this pack (e.g. whole or deltified, its packed
* length).
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
index acdbd7e..742fe6c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
@@ -14,6 +14,7 @@
import java.io.IOException;
import java.nio.channels.Channels;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -35,7 +36,9 @@
import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.BitmapIndex;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdSet;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.util.BlockList;
@@ -45,7 +48,7 @@
* <p>
* It uses the position in the multipack index of the objects as their "offset".
*/
-final class DfsPackFileMidx extends DfsPackFile {
+public final class DfsPackFileMidx extends DfsPackFile {
private static final int REF_POSITION = 0;
@@ -146,18 +149,54 @@ public PackIndex getPackIndex(DfsReader ctx) {
}
@Override
+ public ObjectIdSet asObjectIdSet(DfsReader ctx) throws IOException {
+ MultiPackIndex multiPackIndex = midx(ctx);
+ return objectId -> multiPackIndex.hasObject(objectId);
+ }
+
+ @Override
public PackReverseIndex getReverseIdx(DfsReader ctx) {
throw new IllegalStateException(
"Shouldn't use multipack index if the reverse index is needed"); //$NON-NLS-1$
}
@Override
- public PackBitmapIndex getBitmapIndex(DfsReader ctx) {
- // TODO(ifrade): Implement this
+ public PackBitmapIndex getBitmapIndex(DfsReader ctx) throws IOException {
+ // TODO(ifrade): at some point we will have bitmaps over the multipack
+ // index
+ // At the moment bitmap is in GC, at the end of the chain
+ if (base != null) {
+ return base.getBitmapIndex(ctx);
+ }
+
+ for (DfsPackFile pack : packsInIdOrder) {
+ PackBitmapIndex bitmapIndex = pack.getBitmapIndex(ctx);
+ if (bitmapIndex != null) {
+ return bitmapIndex;
+ }
+ }
return null;
}
@Override
+ List<DfsPackFile> fullyIncludedIn(DfsReader ctx,
+ BitmapIndex.BitmapBuilder need) throws IOException {
+ List<DfsPackFile> fullyIncluded = new ArrayList<>();
+ for (DfsPackFile pack : packs) {
+ List<DfsPackFile> includedPacks = pack.fullyIncludedIn(ctx, need);
+ if (!includedPacks.isEmpty()) {
+ fullyIncluded.addAll(includedPacks);
+ }
+ }
+
+ if (base != null) {
+ fullyIncluded.addAll(base.fullyIncludedIn(ctx, need));
+ }
+
+ return fullyIncluded;
+ }
+
+ @Override
public CommitGraph getCommitGraph(DfsReader ctx) throws IOException {
for (DfsPackFile pack : packs) {
CommitGraph cg = pack.getCommitGraph(ctx);
@@ -193,6 +232,25 @@ public List<DfsPackFile> getCoveredPacks() {
}
/**
+ * All packs indexed by this multipack index and its chain
+ * <p>
+ * This does not include the inner multipack indexes themselves, only their
+ * covered packs.
+ *
+ * @return packs indexed by this multipack index and its parents.
+ */
+ public List<DfsPackFile> getAllCoveredPacks() {
+ List<DfsPackFile> coveredPacks = new ArrayList<>(packs);
+ DfsPackFileMidx base = getMultipackIndexBase();
+ while (base != null) {
+ coveredPacks.addAll(base.getCoveredPacks());
+ base = base.getMultipackIndexBase();
+ }
+
+ return coveredPacks;
+ }
+
+ /**
* Base of this multipack index
* <p>
* If this midx is part of a chain, this is its parent
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
index f50cd59..2272cc5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java
@@ -24,6 +24,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
@@ -149,10 +150,12 @@ public Optional<CommitGraph> getCommitGraph() throws IOException {
public Collection<CachedPack> getCachedPacksAndUpdate(
BitmapBuilder needBitmap) throws IOException {
for (DfsPackFile pack : db.getPacks()) {
- PackBitmapIndex bitmapIndex = pack.getBitmapIndex(this);
- if (needBitmap.removeAllOrNone(bitmapIndex))
- return Collections.<CachedPack> singletonList(
- new DfsCachedPack(pack));
+ // p != pack in the multipack index case
+ List<DfsPackFile> p = pack.fullyIncludedIn(this, needBitmap);
+ if (!p.isEmpty()) {
+ return p.stream().map(DfsCachedPack::new)
+ .collect(Collectors.toUnmodifiableList());
+ }
}
return Collections.emptyList();
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
index fe8dc17..ddf6f39 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java
@@ -133,7 +133,8 @@ public void setReadableChannelBlockSizeForTest(int blockSize) {
@Override
protected synchronized List<DfsPackDescription> listPacks() {
- return packs;
+ return useMultipackIndex() ? MidxPackFilter.useMidx(packs)
+ : MidxPackFilter.skipMidxs(packs);
}
@Override
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackFilter.java
new file mode 100644
index 0000000..50de974
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackFilter.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Format a flat list of packs and midxs into a valid list of packs.
+ * <p>
+ * A valid list of packs is either:
+ * <ul>
+ * <li>A list with midxs and uncovered packs</li>
+ * <li>A list of packs (without any midx)</li>
+ * </ul>
+ */
+public class MidxPackFilter {
+
+ private MidxPackFilter() {
+ }
+
+ /**
+ * Reorganize the flat list of packs removing the midxs
+ *
+ * @param packs
+ * flat list of all packs in the repo, may include midx. Packs
+ * covered by the midx appear also on their own.
+ * @return a list of packs without midxs
+ */
+ public static List<DfsPackDescription> skipMidxs(
+ List<DfsPackDescription> packs) {
+ // Covered packs appear also on their own in the list, so we can just
+ // take the midx out.
+ return packs.stream()
+ .filter(desc -> !desc.hasFileExt(PackExt.MULTI_PACK_INDEX))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Remove from the list any packs covered by midxs.
+ * <p>
+ * This verifies that all referenced packs by the midxs exist.
+ *
+ * @param packs
+ * list of packs with maybe some midxs
+ * @return midxs and uncovered packs. All the input packs if no midx. Ignore
+ * midxs with missing covered packs.
+ */
+ public static List<DfsPackDescription> useMidx(
+ List<DfsPackDescription> packs) {
+ // Take the packs covered by the midxs out of the list
+ List<DfsPackDescription> midxs = packs.stream()
+ .filter(desc -> desc.hasFileExt(PackExt.MULTI_PACK_INDEX))
+ .toList();
+ if (midxs.isEmpty()) {
+ return packs;
+ }
+
+ Set<DfsPackDescription> inputPacks = new HashSet<>(packs);
+ Set<DfsPackDescription> allCoveredPacks = new HashSet<>();
+ for (DfsPackDescription midx : midxs) {
+ Set<DfsPackDescription> coveredPacks = new HashSet<>();
+ findCoveredPacks(midx, coveredPacks);
+ if (!inputPacks.containsAll(coveredPacks)) {
+ // This midx references packs not in the pack db.
+ // It could be part of a chain, so we just ignore all midxs
+ return skipMidxs(packs);
+ }
+ allCoveredPacks.addAll(coveredPacks);
+ }
+
+ return packs.stream().filter(d -> !allCoveredPacks.contains(d))
+ .collect(Collectors.toList());
+ }
+
+ private static void findCoveredPacks(DfsPackDescription midx,
+ Set<DfsPackDescription> covered) {
+ if (!midx.getCoveredPacks().isEmpty()) {
+ covered.addAll(midx.getCoveredPacks());
+ }
+
+ if (midx.getMultiPackIndexBase() != null) {
+ findCoveredPacks(midx.getMultiPackIndexBase(), covered);
+ covered.add(midx.getMultiPackIndexBase());
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackList.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackList.java
new file mode 100644
index 0000000..d26b157
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/MidxPackList.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2025, Google LLC.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.dfs;
+
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Helper class to manipulate a list of packs with (maybe) midxs.
+ **/
+public final class MidxPackList {
+
+ private static final Comparator<DfsPackFile> PACK_NAME_COMPARATOR = Comparator
+ .comparing(pack -> pack.getPackDescription().getPackName());
+
+ /**
+ * Wrap the packs list into a MidxPackList
+ * <p>
+ * The input list is well-formed, doesn't have duplicated packs/midxs.
+ *
+ * @param packs
+ * list of packs (regular or tip midxs)
+ * @return a MidxPackList instance
+ */
+ public static MidxPackList create(DfsPackFile[] packs) {
+ return new MidxPackList(packs);
+ }
+
+ private final List<DfsPackFile> packs;
+
+ private MidxPackList(DfsPackFile[] packs) {
+ this.packs = Arrays.asList(packs);
+ }
+
+ /**
+ * Get all plain packs in the list, either top-level or inside midxs
+ *
+ * @return a list of all "real" packs in this pack list, either top level or
+ * inside midxs.
+ **/
+ public List<DfsPackFile> getAllPlainPacks() {
+ List<DfsPackFile> plainPacks = new ArrayList<>();
+ Queue<DfsPackFile> pending = new ArrayDeque<>(packs);
+ while (!pending.isEmpty()) {
+ DfsPackFile pack = pending.poll();
+ if (pack instanceof DfsPackFileMidx midxPack) {
+ plainPacks.addAll(midxPack.getCoveredPacks());
+ if (midxPack.getMultipackIndexBase() != null) {
+ pending.add(midxPack.getMultipackIndexBase());
+ }
+ } else {
+ plainPacks.add(pack);
+ }
+ }
+ return plainPacks;
+ }
+
+ /**
+ * Get all midx in the list, either top-level or inside other midxs
+ *
+ * @return a list of all midxs in thist list, either top level or nested
+ * inside other midxs.
+ **/
+ public List<DfsPackFileMidx> getAllMidxPacks() {
+ List<DfsPackFileMidx> topLevelMidxs = packs.stream().filter(
+ p -> p.getPackDescription().hasFileExt(MULTI_PACK_INDEX))
+ .map(p -> (DfsPackFileMidx) p).toList();
+
+ List<DfsPackFileMidx> midxPacks = new ArrayList<>();
+ Queue<DfsPackFileMidx> pending = new ArrayDeque<>(topLevelMidxs);
+ while (!pending.isEmpty()) {
+ DfsPackFileMidx midx = pending.poll();
+ midxPacks.add(midx);
+ if (midx.getMultipackIndexBase() != null) {
+ pending.add(midx.getMultipackIndexBase());
+ }
+ }
+ return midxPacks;
+ }
+
+ /**
+ * Alias for {@link #findAllCoveringMidxs(List)}, as convenience for tests
+ *
+ * @param pack
+ * a single pack
+ * @return all the midxs that include (directly or indirectly) the pack
+ */
+ Set<DfsPackFileMidx> findAllCoveringMidxs(DfsPackFile pack) {
+ return findAllCoveringMidxs(List.of(pack));
+ }
+
+ /**
+ * Return all the midxs that cover (directoy or indirectly) a set of packs
+ * <p>
+ * In a chain like midx3(p6, p5) -> midx2(p4, p3) -> midx1(p2, p1), if we
+ * check for p3, midx3 and midx2 are covering it and midx1 is not.
+ *
+ * @param queryPacks
+ * subset of packs we are checking for coverage
+ * @return set of midxs from the packlist that should also be removed
+ */
+ public Set<DfsPackFileMidx> findAllCoveringMidxs(
+ List<DfsPackFile> queryPacks) {
+ if (queryPacks.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ List<DfsPackFileMidx> topLevelMidxs = packs.stream().filter(
+ p -> p.getPackDescription().hasFileExt(MULTI_PACK_INDEX))
+ .map(p -> (DfsPackFileMidx) p).toList();
+
+ if (topLevelMidxs.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ // TODO(ifrade): Delete from queryPacks as we find them and stop if we
+ // are done
+ Set<DfsPackFileMidx> impactedMidxs = asSet(List.of());
+ for (DfsPackFileMidx midx : topLevelMidxs) {
+ List<DfsPackFileMidx> visitedMidxs = new ArrayList<>();
+ DfsPackFileMidx current = midx;
+ while (current != null) {
+ visitedMidxs.add(current);
+ if (containsAny(current.getCoveredPacks(), queryPacks)) {
+ // Anything above in the chain is also covering this pack
+ impactedMidxs.addAll(visitedMidxs);
+ // Reset the list and keep going, maybe something
+ // deeper in the chain is also affected
+ visitedMidxs.clear();
+ }
+ current = current.getMultipackIndexBase();
+ }
+ visitedMidxs.clear();
+ }
+
+ return impactedMidxs;
+ }
+
+ private static boolean containsAny(List<DfsPackFile> inMidx,
+ List<DfsPackFile> queryPacks) {
+ Set<DfsPackFile> inMidxSet = asSet(inMidx);
+ return queryPacks.stream().anyMatch(inMidxSet::contains);
+ }
+
+ private static <T extends DfsPackFile> TreeSet<T> asSet(
+ List<T> initialValues) {
+ TreeSet<T> theSet = new TreeSet<>(PACK_NAME_COMPARATOR);
+ theSet.addAll(initialValues);
+ return theSet;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java
index 81577a8..fd040b9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java
@@ -14,7 +14,6 @@
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
-import java.util.stream.Collectors;
import org.eclipse.jgit.internal.storage.file.PackIndex;
import org.eclipse.jgit.lib.AnyObjectId;
@@ -93,12 +92,17 @@ private void fill(int packId, PackIndex.MutableEntry other) {
private final int uniqueObjectCount;
+ /**
+ * Build a common view of these pack indexes
+ * <p>
+ * Order matters: in case of duplicates, the first pack with the object wins
+ *
+ * @param packs
+ * map of pack names to indexes, ordered.
+ */
PackIndexMerger(Map<String, PackIndex> packs) {
- this.packNames = packs.keySet().stream().sorted()
- .collect(Collectors.toUnmodifiableList());
-
- this.indexes = packNames.stream().map(packs::get)
- .collect(Collectors.toUnmodifiableList());
+ this.packNames = packs.keySet().stream().toList();
+ this.indexes = packs.values().stream().toList();
// Iterate for duplicates
int objectCount = 0;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificate.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificate.java
index 437abb0..b95d094 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificate.java
@@ -53,11 +53,12 @@ public enum NonceStatus {
private final String nonce;
private final NonceStatus nonceStatus;
private final List<ReceiveCommand> commands;
+ private final List<String> pushOptions;
private final String signature;
PushCertificate(String version, PushCertificateIdent pusher, String pushee,
String nonce, NonceStatus nonceStatus, List<ReceiveCommand> commands,
- String signature) {
+ List<String> pushOptions, String signature) {
if (version == null || version.isEmpty()) {
throw new IllegalArgumentException(MessageFormat.format(
JGitText.get().pushCertificateInvalidField, VERSION));
@@ -95,6 +96,7 @@ public enum NonceStatus {
this.nonce = nonce;
this.nonceStatus = nonceStatus;
this.commands = commands;
+ this.pushOptions = pushOptions;
this.signature = signature;
}
@@ -171,6 +173,16 @@ public List<ReceiveCommand> getCommands() {
}
/**
+ * Get the list of push options that were included in the push certificate.
+ *
+ * @return the push options, or an empty list if none.
+ * @since 7.5
+ */
+ public List<String> getPushOptions() {
+ return pushOptions;
+ }
+
+ /**
* Get the raw signature
*
* @return the raw signature, consisting of the lines received between the
@@ -212,8 +224,12 @@ private StringBuilder toStringBuilder() {
if (pushee != null) {
sb.append(PUSHEE).append(' ').append(pushee).append('\n');
}
- sb.append(NONCE).append(' ').append(nonce).append('\n')
- .append('\n');
+ sb.append(NONCE).append(' ').append(nonce).append('\n');
+ for (String option : pushOptions) {
+ sb.append(PushCertificateParser.PUSH_OPTION).append(' ')
+ .append(option).append('\n');
+ }
+ sb.append('\n');
for (ReceiveCommand cmd : commands) {
sb.append(cmd.getOldId().name())
.append(' ').append(cmd.getNewId().name())
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateParser.java
index 463d053..c9f0dec 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateParser.java
@@ -47,6 +47,8 @@ public class PushCertificateParser {
static final String NONCE = "nonce"; //$NON-NLS-1$
+ static final String PUSH_OPTION = "push-option"; //$NON-NLS-1$
+
static final String END_CERT = "push-cert-end"; //$NON-NLS-1$
private static final String VERSION_0_1 = "0.1"; //$NON-NLS-1$
@@ -173,6 +175,7 @@ public static PushCertificate fromString(String str)
private final boolean enabled;
private final NonceGenerator nonceGenerator;
private final List<ReceiveCommand> commands = new ArrayList<>();
+ private final List<String> pushOptions = new ArrayList<>();
/**
* <p>Constructor for PushCertificateParser.</p>
@@ -251,7 +254,8 @@ public PushCertificate build() throws IOException {
}
try {
return new PushCertificate(version, pusher, pushee, receivedNonce,
- nonceStatus, Collections.unmodifiableList(commands), signature);
+ nonceStatus, Collections.unmodifiableList(commands),
+ Collections.unmodifiableList(pushOptions), signature);
} catch (IllegalArgumentException e) {
throw new IOException(e.getMessage(), e);
}
@@ -368,10 +372,16 @@ private void receiveHeader(StringReader reader, boolean stateless)
? nonceGenerator.verify(
receivedNonce, sentNonce(), db, stateless, nonceSlopLimit)
: NonceStatus.UNSOLICITED;
- // An empty line.
- if (!reader.read().isEmpty()) {
- throw new PackProtocolException(
- JGitText.get().pushCertificateInvalidHeader);
+ // Read push-option lines (if any) before the empty line separator
+ String line;
+ while (!(line = reader.read()).isEmpty()) {
+ if (line.startsWith(PUSH_OPTION + " ")) {
+ pushOptions.add(parseHeader(line, PUSH_OPTION));
+ } else {
+ // Not a push-option, should be empty line
+ throw new PackProtocolException(
+ JGitText.get().pushCertificateInvalidHeader);
+ }
}
} catch (EOFException eof) {
throw new PackProtocolException(
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
index 6f211e0..3d9c81c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
@@ -40,6 +40,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@@ -1375,6 +1376,11 @@ private void recvCommands() throws IOException {
if (hasCommands()) {
readPostCommands(pck);
}
+ // Verify that push options in the certificate match the post-command ones.
+ if (pushCert != null) {
+ validateCertificatePushOptions(pushCert.getPushOptions(),
+ pushOptions, commands);
+ }
} catch (Throwable t) {
discardCommands();
throw t;
@@ -1406,6 +1412,35 @@ private void parseShallow(String idStr) throws PackProtocolException {
}
/**
+ * Validates that push options in the certificate match the post-command
+ * push options. If they don't match, marks all commands as rejected.
+ * <p>
+ * This prevents tampering with signed push certificates by ensuring the
+ * options that were signed match exactly the options sent after the
+ * commands.
+ *
+ * @param certPushOptions
+ * the push options from the certificate
+ * @param postCommandPushOptions
+ * the push options sent after commands (may be null)
+ * @param commands
+ * the list of commands to reject if validation fails
+ */
+ static void validateCertificatePushOptions(List<String> certPushOptions,
+ List<String> postCommandPushOptions, List<ReceiveCommand> commands) {
+ List<String> postOptions = postCommandPushOptions == null
+ ? Collections.emptyList()
+ : postCommandPushOptions;
+ if (!Objects.equals(certPushOptions, postOptions)) {
+ // Mark all commands as rejected like in C Git.
+ for (ReceiveCommand cmd : commands) {
+ cmd.setResult(Result.REJECTED_OTHER_REASON,
+ JGitText.get().pushCertificateInconsistentPushOptions);
+ }
+ }
+ }
+
+ /**
* @param in
* request stream.
* @throws IOException
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java
index 888b8fb..e717412 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/InterruptTimer.java
@@ -151,6 +151,7 @@ protected void finalize() throws Throwable {
static final class AlarmState implements Runnable {
private Thread callingThread;
+ private int lastTimeout;
private long deadline;
private boolean terminated;
@@ -163,7 +164,7 @@ static final class AlarmState implements Runnable {
public synchronized void run() {
while (!terminated && callingThread.isAlive()) {
try {
- if (0 < deadline) {
+ if (deadline > 0) {
final long delay = deadline - now();
if (delay <= 0) {
deadline = 0;
@@ -172,7 +173,9 @@ public synchronized void run() {
wait(delay);
}
} else {
- wait(1000);
+ // When the timer is not running, avoid waking up more than once a second
+ wait(lastTimeout == 0 ? 1000 : lastTimeout);
+ lastTimeout = 0;
}
} catch (InterruptedException e) {
// Treat an interrupt as notice to examine state.
@@ -185,15 +188,21 @@ synchronized void begin(int timeout) {
throw new IllegalStateException(JGitText.get().timerAlreadyTerminated);
callingThread = Thread.currentThread();
deadline = now() + timeout;
- notifyAll();
+ if (lastTimeout != timeout) {
+ boolean isNotify = lastTimeout == 0 || lastTimeout > timeout;
+ lastTimeout = timeout;
+ if (isNotify) {
+ notifyAll();
+ } // else avoid the expensive notify when the runloop will already timeout in time
+ }
}
synchronized void end() {
- if (0 == deadline)
+ if (0 == deadline) {
Thread.interrupted();
- else
+ } else {
deadline = 0;
- notifyAll();
+ }
}
synchronized void terminate() {
diff --git a/pom.xml b/pom.xml
index a75f6f4..038b067 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,25 +130,25 @@
<commons-compress-version>1.28.0</commons-compress-version>
<osgi-core-version>6.0.0</osgi-core-version>
<servlet-api-version>6.1.0</servlet-api-version>
- <jetty-version>12.1.1</jetty-version>
- <japicmp-version>0.23.1</japicmp-version>
+ <jetty-version>12.1.3</jetty-version>
+ <japicmp-version>0.24.1</japicmp-version>
<httpclient-version>4.5.14</httpclient-version>
<httpcore-version>4.4.16</httpcore-version>
- <slf4j-version>1.7.36</slf4j-version>
- <maven-javadoc-plugin-version>3.11.2</maven-javadoc-plugin-version>
+ <slf4j-version>2.0.17</slf4j-version>
+ <maven-javadoc-plugin-version>3.12.0</maven-javadoc-plugin-version>
<gson-version>2.13.2</gson-version>
<bouncycastle-version>1.82</bouncycastle-version>
- <spotbugs-maven-plugin-version>4.9.3.0</spotbugs-maven-plugin-version>
+ <spotbugs-maven-plugin-version>4.9.6.0</spotbugs-maven-plugin-version>
<maven-project-info-reports-plugin-version>3.9.0</maven-project-info-reports-plugin-version>
<maven-jxr-plugin-version>3.6.0</maven-jxr-plugin-version>
- <maven-surefire-plugin-version>3.5.3</maven-surefire-plugin-version>
+ <maven-surefire-plugin-version>3.5.4</maven-surefire-plugin-version>
<maven-surefire-report-plugin-version>${maven-surefire-plugin-version}</maven-surefire-report-plugin-version>
- <maven-compiler-plugin-version>3.14.0</maven-compiler-plugin-version>
+ <maven-compiler-plugin-version>3.14.1</maven-compiler-plugin-version>
<plexus-compiler-version>2.13.0</plexus-compiler-version>
- <hamcrest-version>2.2</hamcrest-version>
+ <hamcrest-version>3.0</hamcrest-version>
<assertj-version>3.27.6</assertj-version>
<jna-version>5.18.1</jna-version>
- <byte-buddy-version>1.17.7</byte-buddy-version>
+ <byte-buddy-version>1.17.8</byte-buddy-version>
<!-- Properties to enable jacoco code coverage analysis -->
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
@@ -208,13 +208,13 @@
<plugin>
<artifactId>maven-clean-plugin</artifactId>
- <version>3.4.1</version>
+ <version>3.5.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
- <version>3.6.0</version>
+ <version>3.6.1</version>
</plugin>
<plugin>
@@ -226,7 +226,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
- <version>3.8.1</version>
+ <version>3.9.0</version>
</plugin>
<plugin>
@@ -255,7 +255,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
- <version>3.6.0</version>
+ <version>3.6.1</version>
</plugin>
<plugin>
@@ -277,7 +277,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
- <version>3.26.0</version>
+ <version>3.27.0</version>
<configuration>
<inputEncoding>${project.build.sourceEncoding}</inputEncoding>
<minimumTokens>100</minimumTokens>
@@ -372,7 +372,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-artifact-plugin</artifactId>
- <version>3.6.0</version>
+ <version>3.6.1</version>
<configuration>
<ignore>**/*cyclonedx.json</ignore>
<reproducible>true</reproducible>
@@ -381,7 +381,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
- <version>3.5.0</version>
+ <version>3.6.2</version>
</plugin>
</plugins>
</pluginManagement>
@@ -655,7 +655,7 @@
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
- <version>4.2.0</version>
+ <version>4.2.1</version>
<dependencies>
<dependency>
<groupId>org.apache.groovy</groupId>
diff --git a/tools/maven-central/README.md b/tools/maven-central/README.md
index 04f115e..40156a5 100644
--- a/tools/maven-central/README.md
+++ b/tools/maven-central/README.md
@@ -75,6 +75,8 @@
```
- check in the [Maven Central Portal](https://central.sonatype.com/publishing/deployments)
if the release looks good. You can download uploaded artifacts from there.
+ How to manually test a staged release is explained
+ [here](https://central.sonatype.org/publish/publish-portal-api/#manually-testing-a-deployment-bundle)
- publish the new release
- by clicking "Publish" on the [portal deployment page](https://central.sonatype.com/publishing/deployments)
- or by running