aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.bazelrc5
-rw-r--r--.bazelversion2
-rw-r--r--Documentation/config-options.md17
-rw-r--r--MODULE.bazel103
-rw-r--r--MODULE.bazel.lock221
-rw-r--r--WORKSPACE329
-rw-r--r--lib/BUILD107
-rw-r--r--lib/jmh/BUILD8
-rw-r--r--org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF10
-rw-r--r--org.eclipse.jgit.ant.test/pom.xml2
-rw-r--r--org.eclipse.jgit.ant/META-INF/MANIFEST.MF8
-rw-r--r--org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.ant/pom.xml2
-rw-r--r--org.eclipse.jgit.archive/META-INF/MANIFEST.MF16
-rw-r--r--org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.archive/pom.xml2
-rw-r--r--org.eclipse.jgit.benchmarks/BUILD1
-rw-r--r--org.eclipse.jgit.benchmarks/pom.xml7
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java38
-rw-r--r--org.eclipse.jgit.coverage/pom.xml36
-rw-r--r--org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF20
-rw-r--r--org.eclipse.jgit.gpg.bc.test/pom.xml2
-rw-r--r--org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF42
-rw-r--r--org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.gpg.bc/pom.xml2
-rw-r--r--org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF12
-rw-r--r--org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.http.apache/pom.xml2
-rw-r--r--org.eclipse.jgit.http.server/META-INF/MANIFEST.MF30
-rw-r--r--org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.http.server/pom.xml2
-rw-r--r--org.eclipse.jgit.http.test/META-INF/MANIFEST.MF42
-rw-r--r--org.eclipse.jgit.http.test/pom.xml2
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java3
-rw-r--r--org.eclipse.jgit.junit.http/BUILD2
-rw-r--r--org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF20
-rw-r--r--org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.junit.http/pom.xml2
-rw-r--r--org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF72
-rw-r--r--org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.junit.ssh/pom.xml2
-rw-r--r--org.eclipse.jgit.junit/.settings/.api_filters11
-rw-r--r--org.eclipse.jgit.junit/BUILD2
-rw-r--r--org.eclipse.jgit.junit/META-INF/MANIFEST.MF42
-rw-r--r--org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.junit/pom.xml2
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/FakeIndexFactory.java243
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java64
-rw-r--r--org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java8
-rw-r--r--org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF38
-rw-r--r--org.eclipse.jgit.lfs.server.test/pom.xml2
-rw-r--r--org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF32
-rw-r--r--org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.lfs.server/pom.xml2
-rw-r--r--org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF36
-rw-r--r--org.eclipse.jgit.lfs.test/pom.xml2
-rw-r--r--org.eclipse.jgit.lfs/META-INF/MANIFEST.MF48
-rw-r--r--org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.lfs/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml8
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml6
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml4
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.32.target52
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.33.target52
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.34.target52
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target288
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.tpd8
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target288
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.tpd8
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/maven/dependencies.tpd48
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20200831200620-2020-09.tpd66
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20201130205003-2020-12.tpd66
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210223232630-2021-03.tpd66
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210602031627-2021-06.tpd66
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210825222808-2021-09.tpd73
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211122181901-2021-12.tpd71
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211213173813-2021-12.tpd69
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220302172233-2022-03.tpd69
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220531185310-2022-06.tpd69
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220830213456-2022-09.tpd69
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20221123021534-2022-12.tpd69
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230302014618-2023-03.tpd27
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230531010532-2023-06.tpd25
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.29.tpd27
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.33.tpd2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.34.tpd2
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd (renamed from org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd)18
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.36.tpd (renamed from org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.30.tpd)18
-rw-r--r--org.eclipse.jgit.packaging/pom.xml14
-rw-r--r--org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF40
-rw-r--r--org.eclipse.jgit.pgm.test/pom.xml2
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java55
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java14
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java20
-rw-r--r--org.eclipse.jgit.pgm/META-INF/MANIFEST.MF87
-rw-r--r--org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin1
-rw-r--r--org.eclipse.jgit.pgm/jgit.sh4
-rw-r--r--org.eclipse.jgit.pgm/pom.xml2
-rw-r--r--org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties7
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java23
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java20
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java12
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java4
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java107
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java30
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/BenchmarkReftable.java5
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java5
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java7
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java3
-rw-r--r--org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF12
-rw-r--r--org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.ssh.apache.agent/pom.xml2
-rw-r--r--org.eclipse.jgit.ssh.apache.test/BUILD4
-rw-r--r--org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF65
-rw-r--r--org.eclipse.jgit.ssh.apache.test/pom.xml2
-rw-r--r--org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java10
-rw-r--r--org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReaderTest.java29
-rw-r--r--org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java586
-rw-r--r--org.eclipse.jgit.ssh.apache/BUILD5
-rw-r--r--org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF147
-rw-r--r--org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.ssh.apache/pom.xml9
-rw-r--r--org.eclipse.jgit.ssh.apache/resources/org/eclipse/jgit/internal/transport/sshd/SshdText.properties1
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java20
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java7
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java200
-rw-r--r--org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/SshdText.java1
-rw-r--r--org.eclipse.jgit.ssh.apache/src/sun/security/x509/README.md3
-rw-r--r--org.eclipse.jgit.ssh.jsch.test/BUILD4
-rw-r--r--org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF18
-rw-r--r--org.eclipse.jgit.ssh.jsch.test/pom.xml2
-rw-r--r--org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF20
-rw-r--r--org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.ssh.jsch/pom.xml2
-rw-r--r--org.eclipse.jgit.test/BUILD5
-rw-r--r--org.eclipse.jgit.test/META-INF/MANIFEST.MF121
-rw-r--r--org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java2
-rw-r--r--org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java219
-rw-r--r--org.eclipse.jgit.test/pom.xml2
-rw-r--r--org.eclipse.jgit.test/tests.bzl24
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/multi-pack-index.v1bin0 -> 8632 bytes
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java18
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java7
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java11
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java34
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java22
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java17
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java161
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java66
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java24
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java53
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java29
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java20
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java36
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java9
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java8
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameGeneratorCacheTest.java552
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameRegionMergerTest.java320
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java33
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollectorTest.java48
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java12
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableStackTest.java10
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java197
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcSinceBitmapStatisticsTest.java31
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java32
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java83
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java166
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java30
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java4
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexBuilderTest.java107
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java90
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java345
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java179
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java239
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java71
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java96
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java38
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java10
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java41
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java16
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java5
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java38
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java5
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java5
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java25
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java376
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java210
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java6
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java9
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java37
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java56
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilterTest.java122
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java46
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefMapTest.java2
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java19
-rw-r--r--org.eclipse.jgit.ui/META-INF/MANIFEST.MF18
-rw-r--r--org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit.ui/pom.xml2
-rw-r--r--org.eclipse.jgit/.settings/.api_filters63
-rw-r--r--org.eclipse.jgit/META-INF/MANIFEST.MF147
-rw-r--r--org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit/pom.xml2
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java89
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java59
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java28
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java91
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java145
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameRegionMerger.java158
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/BlameCache.java46
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/CacheRegion.java125
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java22
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java81
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java16
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsObjDatabase.java54
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java138
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java139
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java109
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java65
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java30
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java103
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java54
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java99
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java71
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java36
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java103
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java103
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexConstants.java58
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java350
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexPrettyPrinter.java156
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java289
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java428
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java337
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockWriter.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java59
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java265
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java52
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java196
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java101
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java34
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java57
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java140
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FollowFilter.java25
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java56
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java32
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/AndTreeFilter.java17
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilter.java135
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/OrTreeFilter.java17
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java62
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java86
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java35
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java38
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java36
-rw-r--r--pom.xml56
-rw-r--r--tools/BUILD2
-rw-r--r--tools/bazlets.bzl18
325 files changed, 11792 insertions, 3568 deletions
diff --git a/.bazelrc b/.bazelrc
index 74601dc7d0..0006880b93 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,7 +1,3 @@
-# TODO(davido): Migrate all dependencies from WORKSPACE to MODULE.bazel
-# https://issues.gerritcodereview.com/issues/303819949
-common --noenable_bzlmod
-
build --workspace_status_command="python3 ./tools/workspace_status.py"
build --repository_cache=~/.gerritcodereview/bazel-cache/repository
build --incompatible_strict_action_env
@@ -37,5 +33,6 @@ build:remote21 --config=remote
test --build_tests_only
test --test_output=errors
test --flaky_test_attempts=3
+test --test_tag_filters=-ext
import %workspace%/tools/remote-bazelrc
diff --git a/.bazelversion b/.bazelversion
index 21c8c7b46b..2b0aa21219 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1 +1 @@
-7.1.1
+8.2.1
diff --git a/Documentation/config-options.md b/Documentation/config-options.md
index eeb78ff550..4dde8f8c15 100644
--- a/Documentation/config-options.md
+++ b/Documentation/config-options.md
@@ -55,9 +55,13 @@ For details on native git options see also the official [git config documentatio
| `core.streamFileThreshold` | `50 MiB` | ⃞ | The size threshold beyond which objects must be streamed. |
| `core.supportsAtomicFileCreation` | `true` | ⃞ | Whether the filesystem supports atomic file creation. |
| `core.symlinks` | Auto detect if filesystem supports symlinks| ✅ | If false, symbolic links are checked out as small plain files that contain the link text. |
-| `core.trustFolderStat` | `true` | ⃞ | Whether to trust the pack folder's, packed-refs file's and loose-objects folder's file attributes (Java equivalent of stat command on *nix). When looking for pack files, if `false` JGit will always scan the `.git/objects/pack` folder and if set to `true` it assumes that pack files are unchanged if the file attributes of the pack folder are unchanged. When getting the list of packed refs, if `false` JGit will always read the packed-refs file and if set to `true` it uses the file attributes of the packed-refs file and will only read it if a file attribute has changed. When looking for loose objects, if `false` and if a loose object is not found, JGit will open and close a stream to `.git/objects` folder (which can refresh its directory listing, at least on some NFS clients) and retry looking for that loose object. Setting this option to `false` can help to workaround caching issues on NFS, but reduces performance. |
-| `core.trustPackedRefsStat` | `unset` | ⃞ | Whether to trust the file attributes (Java equivalent of stat command on *nix) of the packed-refs file. If `never` JGit will ignore the file attributes of the packed-refs file and always read it. If `always` JGit will trust the file attributes of the packed-refs file and will only read it if a file attribute has changed. `after_open` behaves the same as `always`, except that the packed-refs file is opened and closed before its file attributes are considered. An open/close of the packed-refs file is known to refresh its file attributes, at least on some NFS clients. If `unset`, JGit will use the behavior described in `trustFolderStat`. |
-| `core.trustLooseRefStat` | `always` | ⃞ | Whether to trust the file attributes (Java equivalent of stat command on *nix) of the loose ref. If `always` JGit will trust the file attributes of the loose ref and its parent directories. `after_open` behaves similar to `always`, except that all parent directories of the loose ref up to the repository root are opened and closed before its file attributes are considered. An open/close of these parent directories is known to refresh the file attributes, at least on some NFS clients. |
+| ~~`core.trustFolderStat`~~ | `true` | ⃞ | __Deprecated__, use `core.trustStat` instead. If set to `true` translated to `core.trustStat=always`, if `false` translated to `core.trustStat=never`, see below. If both `core.trustFolderStat` and `core.trustStat` are configured then `trustStat` takes precedence and `trustFolderStat` is ignored. |
+| `core.trustLooseRefStat` | `inherit` | ⃞ | Whether to trust the file attributes of loose refs and its fan-out parent directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `trustStat`. |
+| `core.trustPackedRefsStat` | `inherit` | ⃞ | Whether to trust the file attributes of the packed-refs file. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. |
+| `core.trustTablesListStat` | `inherit` | ⃞ | Whether to trust the file attributes of the `tables.list` file used by the reftable ref storage backend to store the list of reftable filenames. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. The reftable backend is used if `extensions.refStorage = reftable`. |
+| `core.trustLooseObjectStat` | `inherit` | ⃞ | Whether to trust the file attributes of the loose object file and its fan-out parent directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. |
+| `core.trustPackStat` | `inherit` | ⃞ | Whether to trust the file attributes of the `objects/pack` directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. |
+| `core.trustStat` | `always` | ⃞ | Global option to configure whether to trust file attributes (Java equivalent of stat command on Unix) of files storing git objects. Can be overridden for specific files by configuring `core.trustLooseRefStat, core.trustPackedRefsStat, core.trustLooseObjectStat, core.trustPackStat,core.trustTablesListStat`. If `never` JGit will ignore the file attributes of the file and always read it. If `always` JGit will trust the file attributes and will only read it if a file attribute has changed. `after_open` behaves the same as `always`, but file attributes are only considered *after* the file itself and any transient parent directories have been opened and closed. An open/close of the file/directory is known to refresh its file attributes, at least on some NFS clients. |
| `core.worktree` | Root directory of the working tree if it is not the parent directory of the `.git` directory | ✅ | The path to the root of the working tree. |
## __fetch__ options
@@ -131,6 +135,13 @@ Proxy configuration uses the standard Java mechanisms via class `java.net.ProxyS
| `pack.window` | `10` | ✅ | Number of objects to try when looking for a delta base per thread searching for deltas. |
| `pack.windowMemory` | `0` (unlimited) | ✅ | Maximum number of bytes to put into the delta search window. |
+## reftable options
+
+| option | default | git option | description |
+|---------|---------|------------|-------------|
+| `reftable.autoRefresh` | `false` | ⃞ | Whether to auto-refresh the reftable stack if it is out of date. |
+
+
## __repack__ options
| option | default | git option | description |
diff --git a/MODULE.bazel b/MODULE.bazel
index 0b932b8d8c..5fbe2c2ed4 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -1,2 +1,101 @@
-# TODO(davido): Migrate all dependencies from WORKSPACE to MODULE.bazel
-# https://issues.gerritcodereview.com/issues/303819949
+module(name = "jgit")
+
+bazel_dep(name = "rules_java", version = "8.11.0")
+bazel_dep(name = "rules_jvm_external", version = "6.7")
+
+register_toolchains("//tools:error_prone_warnings_toolchain_java17_definition")
+
+register_toolchains("//tools:error_prone_warnings_toolchain_java21_definition")
+
+git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
+git_repository(
+ name = "com_googlesource_gerrit_bazlets",
+ commit = "f9c119e45d9a241bee720b7fbd6c7fdbc952da5f",
+ remote = "https://gerrit.googlesource.com/bazlets",
+)
+
+http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+ name = "ubuntu2204_jdk17",
+ sha256 = "8ea82b81c9707e535ff93ef5349d11e55b2a23c62bcc3b0faaec052144aed87d",
+ strip_prefix = "rbe_autoconfig-5.1.0",
+ urls = [
+ "https://gerrit-bazel.storage.googleapis.com/rbe_autoconfig/v5.1.0.tar.gz",
+ "https://github.com/davido/rbe_autoconfig/releases/download/v5.1.0/v5.1.0.tar.gz",
+ ],
+)
+
+BOUNCYCASTLE_VERSION = "1.81"
+
+BYTE_BUDDY_VERSION = "1.17.5"
+
+JETTY_VERSION = "12.0.22"
+
+JMH_VERSION = "1.37"
+
+JNA_VERSION = "5.17.0"
+
+SLF4J_VERSION = "1.7.36"
+
+SSHD_VERSION = "2.15.0"
+
+maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
+maven.install(
+ name = "jgit_deps",
+ artifacts = [
+ "args4j:args4j:2.37",
+ "com.google.code.gson:gson:2.13.1",
+ "com.google.errorprone:error_prone_type_annotations:2.38.0",
+ "com.googlecode.javaewah:JavaEWAH:1.2.3",
+ "com.jcraft:jsch:0.1.55",
+ "com.jcraft:jzlib:1.1.3",
+ "commons-codec:commons-codec:1.18.0",
+ "commons-io:commons-io:2.19.0",
+ "commons-logging:commons-logging:1.3.5",
+ "jakarta.servlet:jakarta.servlet-api:6.1.0",
+ "junit:junit:4.13.2",
+ "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
+ "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
+ "net.java.dev.jna:jna-platform:" + JNA_VERSION,
+ "net.java.dev.jna:jna:" + JNA_VERSION,
+ "net.sf.jopt-simple:jopt-simple:5.0.4",
+ "org.apache.commons:commons-compress:1.27.1",
+ "org.apache.commons:commons-lang3:3.17.0",
+ "org.apache.commons:commons-math3:3.6.1",
+ "org.apache.httpcomponents:httpclient:4.5.14",
+ "org.apache.httpcomponents:httpcore:4.4.16",
+ "org.apache.sshd:sshd-osgi:" + SSHD_VERSION,
+ "org.apache.sshd:sshd-sftp:" + SSHD_VERSION,
+ "org.assertj:assertj-core:3.27.3",
+ "org.bouncycastle:bcpg-jdk18on:" + BOUNCYCASTLE_VERSION,
+ "org.bouncycastle:bcpkix-jdk18on:" + BOUNCYCASTLE_VERSION,
+ "org.bouncycastle:bcprov-jdk18on:" + BOUNCYCASTLE_VERSION,
+ "org.bouncycastle:bcutil-jdk18on:" + BOUNCYCASTLE_VERSION,
+ "org.eclipse.jetty.ee10:jetty-ee10-servlet:" + JETTY_VERSION,
+ "org.eclipse.jetty:jetty-http:" + JETTY_VERSION,
+ "org.eclipse.jetty:jetty-io:" + JETTY_VERSION,
+ "org.eclipse.jetty:jetty-security:" + JETTY_VERSION,
+ "org.eclipse.jetty:jetty-server:" + JETTY_VERSION,
+ "org.eclipse.jetty:jetty-session:" + JETTY_VERSION,
+ "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VERSION,
+ "org.eclipse.jetty:jetty-util:" + JETTY_VERSION,
+ "org.hamcrest:hamcrest:2.2",
+ "org.mockito:mockito-core:5.18.0",
+ "org.objenesis:objenesis:3.4",
+ "org.openjdk.jmh:jmh-core:" + JMH_VERSION,
+ "org.openjdk.jmh:jmh-generator-annprocess:" + JMH_VERSION,
+ "org.slf4j:slf4j-api:" + SLF4J_VERSION,
+ "org.slf4j:slf4j-simple:" + SLF4J_VERSION,
+ "org.tukaani:xz:1.10",
+ ],
+ duplicate_version_warning = "error",
+ fail_on_missing_checksum = True,
+ fetch_sources = True,
+ repositories = [
+ "https://repo1.maven.org/maven2",
+ ],
+ strict_visibility = True,
+)
+use_repo(maven, "jgit_deps")
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
new file mode 100644
index 0000000000..bdc8104794
--- /dev/null
+++ b/MODULE.bazel.lock
@@ -0,0 +1,221 @@
+{
+ "lockFileVersion": 18,
+ "registryFileHashes": {
+ "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
+ "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
+ "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
+ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
+ "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
+ "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
+ "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
+ "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
+ "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
+ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
+ "https://bcr.bazel.build/modules/bazel_features/1.21.0/source.json": "3e8379efaaef53ce35b7b8ba419df829315a880cb0a030e5bb45c96d6d5ecb5f",
+ "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
+ "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
+ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
+ "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
+ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
+ "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
+ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
+ "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
+ "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
+ "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
+ "https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5",
+ "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
+ "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
+ "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
+ "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
+ "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
+ "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
+ "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
+ "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
+ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
+ "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
+ "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
+ "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
+ "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
+ "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
+ "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
+ "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
+ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
+ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
+ "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
+ "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
+ "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
+ "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
+ "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
+ "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
+ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
+ "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
+ "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
+ "https://bcr.bazel.build/modules/rules_java/8.11.0/MODULE.bazel": "c3d280bc5ff1038dcb3bacb95d3f6b83da8dd27bba57820ec89ea4085da767ad",
+ "https://bcr.bazel.build/modules/rules_java/8.11.0/source.json": "302b52a39259a85aa06ca3addb9787864ca3e03b432a5f964ea68244397e7544",
+ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
+ "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd",
+ "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
+ "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
+ "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
+ "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
+ "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
+ "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
+ "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
+ "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
+ "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
+ "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
+ "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
+ "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
+ "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
+ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
+ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
+ "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
+ "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
+ "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
+ "https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320",
+ "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
+ "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
+ "https://bcr.bazel.build/modules/rules_shell/0.3.0/source.json": "c55ed591aa5009401ddf80ded9762ac32c358d2517ee7820be981e2de9756cf3",
+ "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
+ "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
+ "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
+ "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
+ "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
+ "https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01",
+ "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
+ "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d",
+ "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
+ },
+ "selectedYankedVersions": {},
+ "moduleExtensions": {
+ "@@platforms//host:extension.bzl%host_platform": {
+ "general": {
+ "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
+ "usagesDigest": "SeQiIN/f8/Qt9vYQk7qcXp4I4wJeEC0RnQDiaaJ4tb8=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "host_platform": {
+ "repoRuleId": "@@platforms//host:extension.bzl%host_platform_repo",
+ "attributes": {}
+ }
+ },
+ "recordedRepoMappingEntries": []
+ }
+ },
+ "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
+ "general": {
+ "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=",
+ "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
+ "recordedFileInputs": {},
+ "recordedDirentsInputs": {},
+ "envVariables": {},
+ "generatedRepoSpecs": {
+ "com_github_jetbrains_kotlin_git": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
+ ],
+ "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
+ }
+ },
+ "com_github_jetbrains_kotlin": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
+ "attributes": {
+ "git_repository_name": "com_github_jetbrains_kotlin_git",
+ "compiler_version": "1.9.23"
+ }
+ },
+ "com_github_google_ksp": {
+ "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
+ "attributes": {
+ "urls": [
+ "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
+ ],
+ "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
+ "strip_version": "1.9.23-1.0.20"
+ }
+ },
+ "com_github_pinterest_ktlint": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
+ "attributes": {
+ "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
+ "urls": [
+ "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
+ ],
+ "executable": true
+ }
+ },
+ "rules_android": {
+ "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
+ "attributes": {
+ "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
+ "strip_prefix": "rules_android-0.1.1",
+ "urls": [
+ "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
+ ]
+ }
+ }
+ },
+ "recordedRepoMappingEntries": [
+ [
+ "rules_kotlin+",
+ "bazel_tools",
+ "bazel_tools"
+ ]
+ ]
+ }
+ }
+ }
+}
diff --git a/WORKSPACE b/WORKSPACE
index e015895592..6ba4a02382 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,327 +1,2 @@
-workspace(name = "jgit")
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-load("//tools:bazlets.bzl", "load_bazlets")
-
-load_bazlets(commit = "f9c119e45d9a241bee720b7fbd6c7fdbc952da5f")
-
-load(
- "@com_googlesource_gerrit_bazlets//tools:maven_jar.bzl",
- "maven_jar",
-)
-
-http_archive(
- name = "rules_java",
- sha256 = "4da3761f6855ad916568e2bfe86213ba6d2637f56b8360538a7fb6125abf6518",
- urls = [
- "https://github.com/bazelbuild/rules_java/releases/download/7.5.0/rules_java-7.5.0.tar.gz",
- ],
-)
-
-load("@rules_java//java:repositories.bzl", "rules_java_dependencies", "rules_java_toolchains")
-
-rules_java_dependencies()
-
-http_archive(
- name = "ubuntu2204_jdk17",
- sha256 = "8ea82b81c9707e535ff93ef5349d11e55b2a23c62bcc3b0faaec052144aed87d",
- strip_prefix = "rbe_autoconfig-5.1.0",
- urls = [
- "https://gerrit-bazel.storage.googleapis.com/rbe_autoconfig/v5.1.0.tar.gz",
- "https://github.com/davido/rbe_autoconfig/releases/download/v5.1.0/v5.1.0.tar.gz",
- ],
-)
-
-register_toolchains("//tools:error_prone_warnings_toolchain_java17_definition")
-
-register_toolchains("//tools:error_prone_warnings_toolchain_java21_definition")
-
-# Order of registering toolchains matters. rules_java toolchains take precedence
-# over the custom toolchains, so the default jdk21 toolchain gets picked
-# (one without custom package_config). That's why the `rules_java_toolchains()`
-# must be called after the `register_toolchain()` invocation.
-rules_java_toolchains()
-
-JMH_VERS = "1.37"
-
-maven_jar(
- name = "jmh-core",
- artifact = "org.openjdk.jmh:jmh-core:" + JMH_VERS,
- attach_source = False,
- sha1 = "896f27e49105b35ea1964319c83d12082e7a79ef",
-)
-
-maven_jar(
- name = "jmh-annotations",
- artifact = "org.openjdk.jmh:jmh-generator-annprocess:" + JMH_VERS,
- attach_source = False,
- sha1 = "da93888682df163144edf9b13d2b78e54166063a",
-)
-
-maven_jar(
- name = "jopt",
- artifact = "net.sf.jopt-simple:jopt-simple:5.0.4",
- attach_source = False,
- sha1 = "4fdac2fbe92dfad86aa6e9301736f6b4342a3f5c",
-)
-
-maven_jar(
- name = "math3",
- artifact = "org.apache.commons:commons-math3:3.6.1",
- attach_source = False,
- sha1 = "e4ba98f1d4b3c80ec46392f25e094a6a2e58fcbf",
-)
-
-maven_jar(
- name = "eddsa",
- artifact = "net.i2p.crypto:eddsa:0.3.0",
- sha1 = "1901c8d4d8bffb7d79027686cfb91e704217c3e1",
-)
-
-maven_jar(
- name = "jsch",
- artifact = "com.jcraft:jsch:0.1.55",
- sha1 = "bbd40e5aa7aa3cfad5db34965456cee738a42a50",
-)
-
-maven_jar(
- name = "jzlib",
- artifact = "com.jcraft:jzlib:1.1.3",
- sha1 = "c01428efa717624f7aabf4df319939dda9646b2d",
-)
-
-maven_jar(
- name = "javaewah",
- artifact = "com.googlecode.javaewah:JavaEWAH:1.2.3",
- sha1 = "13a27c856e0c8808cee9a64032c58eee11c3adc9",
-)
-
-maven_jar(
- name = "httpclient",
- artifact = "org.apache.httpcomponents:httpclient:4.5.14",
- sha1 = "1194890e6f56ec29177673f2f12d0b8e627dec98",
-)
-
-maven_jar(
- name = "httpcore",
- artifact = "org.apache.httpcomponents:httpcore:4.4.16",
- sha1 = "51cf043c87253c9f58b539c9f7e44c8894223850",
-)
-
-SSHD_VERS = "2.14.0"
-
-maven_jar(
- name = "sshd-osgi",
- artifact = "org.apache.sshd:sshd-osgi:" + SSHD_VERS,
- sha1 = "6ef66228a088f8ac1383b2ff28f3102f80ebc01a",
-)
-
-maven_jar(
- name = "sshd-sftp",
- artifact = "org.apache.sshd:sshd-sftp:" + SSHD_VERS,
- sha1 = "c070ac920e72023ae9ab0a3f3a866bece284b470",
-)
-
-JNA_VERS = "5.15.0"
-
-maven_jar(
- name = "jna",
- artifact = "net.java.dev.jna:jna:" + JNA_VERS,
- sha1 = "01ee1d80ff44f08280188f7c0e740d57207841ac",
-)
-
-maven_jar(
- name = "jna-platform",
- artifact = "net.java.dev.jna:jna-platform:" + JNA_VERS,
- sha1 = "86b502cad57d45da172b5e3231c537b042e296ef",
-)
-
-maven_jar(
- name = "commons-codec",
- artifact = "commons-codec:commons-codec:1.17.1",
- sha1 = "973638b7149d333563584137ebf13a691bb60579",
-)
-
-maven_jar(
- name = "commons-logging",
- artifact = "commons-logging:commons-logging:1.3.4",
- sha1 = "b9fc14968d63a8b8a8a2c1885fe3e90564239708",
-)
-
-maven_jar(
- name = "log-api",
- artifact = "org.slf4j:slf4j-api:1.7.36",
- sha1 = "6c62681a2f655b49963a5983b8b0950a6120ae14",
-)
-
-maven_jar(
- name = "slf4j-simple",
- artifact = "org.slf4j:slf4j-simple:1.7.36",
- sha1 = "a41f9cfe6faafb2eb83a1c7dd2d0dfd844e2a936",
-)
-
-maven_jar(
- name = "servlet-api",
- artifact = "jakarta.servlet:jakarta.servlet-api:6.1.0",
- sha1 = "1169a246913fe3823782af7943e7a103634867c5",
-)
-
-maven_jar(
- name = "commons-compress",
- artifact = "org.apache.commons:commons-compress:1.27.1",
- sha1 = "a19151084758e2fbb6b41eddaa88e7b8ff4e6599",
-)
-
-maven_jar(
- name = "commons-lang3",
- artifact = "org.apache.commons:commons-lang3:3.17.0",
- sha1 = "b17d2136f0460dcc0d2016ceefca8723bdf4ee70",
-)
-
-maven_jar(
- name = "commons-io",
- artifact = "commons-io:commons-io:2.18.0",
- sha1 = "44084ef756763795b31c578403dd028ff4a22950",
-)
-
-maven_jar(
- name = "tukaani-xz",
- artifact = "org.tukaani:xz:1.10",
- sha1 = "1be8166f89e035a56c6bfc67dbc423996fe577e2",
-)
-
-maven_jar(
- name = "args4j",
- artifact = "args4j:args4j:2.37",
- sha1 = "244f60c057d72a785227c0562d3560f42a7ea54b",
-)
-
-maven_jar(
- name = "junit",
- artifact = "junit:junit:4.13.2",
- sha1 = "8ac9e16d933b6fb43bc7f576336b8f4d7eb5ba12",
-)
-
-maven_jar(
- name = "hamcrest",
- artifact = "org.hamcrest:hamcrest:2.2",
- sha1 = "1820c0968dba3a11a1b30669bb1f01978a91dedc",
-)
-
-maven_jar(
- name = "mockito",
- artifact = "org.mockito:mockito-core:5.14.2",
- sha1 = "f7bf936008d7664e2002c3faf0c02071c8d10e7c",
-)
-
-maven_jar(
- name = "assertj-core",
- artifact = "org.assertj:assertj-core:3.27.0",
- sha1 = "a04bf3feaf3dc6ede0770c160a7dc1c214f1a2c9",
-)
-
-BYTE_BUDDY_VERSION = "1.15.11"
-
-maven_jar(
- name = "bytebuddy",
- artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VERSION,
- sha1 = "f61886478e0f9ee4c21d09574736f0ff45e0a46c",
-)
-
-maven_jar(
- name = "bytebuddy-agent",
- artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VERSION,
- sha1 = "a38b16385e867f59a641330f0362ebe742788ed8",
-)
-
-maven_jar(
- name = "objenesis",
- artifact = "org.objenesis:objenesis:3.4",
- sha1 = "675cbe121a68019235d27f6c34b4f0ac30e07418",
-)
-
-maven_jar(
- name = "gson",
- artifact = "com.google.code.gson:gson:2.11.0",
- sha1 = "527175ca6d81050b53bdd4c457a6d6e017626b0e",
-)
-
-JETTY_VER = "12.0.16"
-
-maven_jar(
- name = "jetty-servlet",
- artifact = "org.eclipse.jetty.ee10:jetty-ee10-servlet:" + JETTY_VER,
- sha1 = "022a746c00b1ac5c790fee65a398c707160a46d8",
-)
-
-maven_jar(
- name = "jetty-security",
- artifact = "org.eclipse.jetty:jetty-security:" + JETTY_VER,
- sha1 = "23b1a3abecf9d6f5498064a32d9145ae1d8330f9",
-)
-
-maven_jar(
- name = "jetty-server",
- artifact = "org.eclipse.jetty:jetty-server:" + JETTY_VER,
- sha1 = "3e3638b4bfbee04c27b3ae68e4949fc43b40a042",
-)
-
-maven_jar(
- name = "jetty-session",
- artifact = "org.eclipse.jetty:jetty-session:" + JETTY_VER,
- sha1 = "79cdedc7afebbdba4453f603dfe2f970baa35cc3",
-)
-
-maven_jar(
- name = "jetty-http",
- artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VER,
- sha1 = "68019fa90e8420ae15c109bd8c8611cacbaf43e5",
-)
-
-maven_jar(
- name = "jetty-io",
- artifact = "org.eclipse.jetty:jetty-io:" + JETTY_VER,
- sha1 = "7a162c537a99bbaf35a074fec9a50815e6c81d9d",
-)
-
-maven_jar(
- name = "jetty-util",
- artifact = "org.eclipse.jetty:jetty-util:" + JETTY_VER,
- sha1 = "e262e505363e5925df15618622d9888aefc1b0d0",
-)
-
-maven_jar(
- name = "jetty-util-ajax",
- artifact = "org.eclipse.jetty:jetty-util-ajax:" + JETTY_VER,
- sha1 = "60225034131e3f771b40bc75c15bd9cc4952302b",
-)
-
-BOUNCYCASTLE_VER = "1.79"
-
-maven_jar(
- name = "bcpg",
- artifact = "org.bouncycastle:bcpg-jdk18on:" + BOUNCYCASTLE_VER,
- sha1 = "904dd8a8e1c9f7d58d1ffa7f4ca3fb00736a601f",
- src_sha1 = "9e372826141edb213d5921131ee68dc276dc99ef",
-)
-
-maven_jar(
- name = "bcprov",
- artifact = "org.bouncycastle:bcprov-jdk18on:" + BOUNCYCASTLE_VER,
- sha1 = "4d8e2732bcee15f1db93df266c3f5b70ce5cac21",
- src_sha1 = "8647816d667ee526a8e3a456229ac5f9f96d2315",
-)
-
-maven_jar(
- name = "bcutil",
- artifact = "org.bouncycastle:bcutil-jdk18on:" + BOUNCYCASTLE_VER,
- sha1 = "ecfc5aef97cc7676ea0de5c53c407b9f533f0ad5",
- src_sha1 = "00df03977fb0b80395da655623abca9d7d7dcb66",
-)
-
-maven_jar(
- name = "bcpkix",
- artifact = "org.bouncycastle:bcpkix-jdk18on:" + BOUNCYCASTLE_VER,
- sha1 = "7693cec3b8779b74b35466dcaeeaac7409872954",
- src_sha1 = "57a60d1d9f75320eef70a095dfae679d97ade1c2",
-)
+# This file marks the root of the Bazel workspace.
+# See MODULE.bazel for external dependencies setup.
diff --git a/lib/BUILD b/lib/BUILD
index d26ccae4eb..cd96abd0b8 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -6,7 +6,7 @@ java_library(
"//org.eclipse.jgit.pgm:__pkg__",
"//org.eclipse.jgit.pgm.test:__pkg__",
],
- exports = ["@args4j//jar"],
+ exports = ["@jgit_deps//:args4j_args4j"],
)
java_library(
@@ -16,7 +16,7 @@ java_library(
"//org.eclipse.jgit.pgm.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@commons-compress//jar"],
+ exports = ["@jgit_deps//:org_apache_commons_commons_compress"],
)
java_library(
@@ -26,7 +26,7 @@ java_library(
"//org.eclipse.jgit.pgm.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@commons-lang3//jar"],
+ exports = ["@jgit_deps//:org_apache_commons_commons_lang3"],
)
java_library(
@@ -36,7 +36,7 @@ java_library(
"//org.eclipse.jgit.pgm.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@commons-io//jar"],
+ exports = ["@jgit_deps//:commons_io_commons_io"],
)
java_library(
@@ -45,23 +45,13 @@ java_library(
"//org.eclipse.jgit:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@commons-codec//jar"],
+ exports = ["@jgit_deps//:commons_codec_commons_codec"],
)
java_library(
name = "commons-logging",
visibility = ["//visibility:public"],
- exports = ["@commons-logging//jar"],
-)
-
-java_library(
- name = "eddsa",
- visibility = [
- "//org.eclipse.jgit.ssh.apache:__pkg__",
- "//org.eclipse.jgit.ssh.apache.test:__pkg__",
- "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
- ],
- exports = ["@eddsa//jar"],
+ exports = ["@jgit_deps//:commons_logging_commons_logging"],
)
java_library(
@@ -70,7 +60,7 @@ java_library(
"//org.eclipse.jgit.lfs:__pkg__",
"//org.eclipse.jgit.lfs.server:__pkg__",
],
- exports = ["@gson//jar"],
+ exports = ["@jgit_deps//:com_google_code_gson_gson"],
)
java_library(
@@ -80,7 +70,7 @@ java_library(
"//org.eclipse.jgit.lfs.server.test:__pkg__",
"//org.eclipse.jgit.pgm:__pkg__",
],
- exports = ["@httpclient//jar"],
+ exports = ["@jgit_deps//:org_apache_httpcomponents_httpclient"],
)
java_library(
@@ -92,7 +82,7 @@ java_library(
"//org.eclipse.jgit.lfs.server.test:__pkg__",
"//org.eclipse.jgit.pgm:__pkg__",
],
- exports = ["@httpcore//jar"],
+ exports = ["@jgit_deps//:org_apache_httpcomponents_httpcore"],
)
java_library(
@@ -104,7 +94,7 @@ java_library(
"//org.eclipse.jgit.ssh.apache.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@sshd-osgi//jar"],
+ exports = ["@jgit_deps//:org_apache_sshd_sshd_osgi"],
)
java_library(
@@ -115,7 +105,7 @@ java_library(
"//org.eclipse.jgit.ssh.apache.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@sshd-sftp//jar"],
+ exports = ["@jgit_deps//:org_apache_sshd_sshd_sftp"],
)
java_library(
@@ -123,7 +113,7 @@ java_library(
visibility = [
"//org.eclipse.jgit.ssh.apache.agent:__pkg__",
],
- exports = ["@jna//jar"],
+ exports = ["@jgit_deps//:net_java_dev_jna_jna"],
)
java_library(
@@ -131,20 +121,20 @@ java_library(
visibility = [
"//org.eclipse.jgit.ssh.apache.agent:__pkg__",
],
- exports = ["@jna-platform//jar"],
+ exports = ["@jgit_deps//:net_java_dev_jna_jna_platform"],
)
java_library(
name = "javaewah",
visibility = ["//visibility:public"],
- exports = ["@javaewah//jar"],
+ exports = ["@jgit_deps//:com_googlecode_javaewah_JavaEWAH"],
)
java_library(
name = "jetty-http",
# TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
visibility = ["//visibility:public"],
- exports = ["@jetty-http//jar"],
+ exports = ["@jgit_deps//:org_eclipse_jetty_jetty_http"],
runtime_deps = [":commons-codec"],
)
@@ -152,28 +142,28 @@ java_library(
name = "jetty-io",
# TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
visibility = ["//visibility:public"],
- exports = ["@jetty-io//jar"],
+ exports = ["@jgit_deps//:org_eclipse_jetty_jetty_io"],
)
java_library(
name = "jetty-security",
# TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
visibility = ["//visibility:public"],
- exports = ["@jetty-security//jar"],
+ exports = ["@jgit_deps//:org_eclipse_jetty_jetty_security"],
)
java_library(
name = "jetty-session",
# TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
visibility = ["//visibility:public"],
- exports = ["@jetty-session//jar"],
+ exports = ["@jgit_deps//:org_eclipse_jetty_jetty_session"],
)
java_library(
name = "jetty-server",
# TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
visibility = ["//visibility:public"],
- exports = ["@jetty-server//jar"],
+ exports = ["@jgit_deps//:org_eclipse_jetty_jetty_server"],
)
java_library(
@@ -181,8 +171,8 @@ java_library(
# TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
visibility = ["//visibility:public"],
exports = [
- "@jetty-servlet//jar",
- "@jetty-util-ajax//jar",
+ "@jgit_deps//:org_eclipse_jetty_ee10_jetty_ee10_servlet",
+ "@jgit_deps//:org_eclipse_jetty_jetty_util_ajax",
],
)
@@ -190,7 +180,7 @@ java_library(
name = "jetty-util",
# TODO: This should be testonly but org.eclipse.jgit.pgm depends on it.
visibility = ["//visibility:public"],
- exports = ["@jetty-util//jar"],
+ exports = ["@jgit_deps//:org_eclipse_jetty_jetty_util"],
)
java_library(
@@ -200,7 +190,7 @@ java_library(
"//org.eclipse.jgit.ssh.jsch:__pkg__",
"//org.eclipse.jgit.ssh.jsch.test:__pkg__",
],
- exports = ["@jsch//jar"],
+ exports = ["@jgit_deps//:com_jcraft_jsch"],
)
java_library(
@@ -208,9 +198,11 @@ java_library(
visibility = [
"//org.eclipse.jgit.gpg.bc:__pkg__",
"//org.eclipse.jgit.gpg.bc.test:__pkg__",
+ "//org.eclipse.jgit.ssh.apache:__pkg__",
+ "//org.eclipse.jgit.ssh.apache.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@bcpg//jar"],
+ exports = ["@jgit_deps//:org_bouncycastle_bcpg_jdk18on"],
)
java_library(
@@ -218,9 +210,12 @@ java_library(
visibility = [
"//org.eclipse.jgit.gpg.bc:__pkg__",
"//org.eclipse.jgit.gpg.bc.test:__pkg__",
+ "//org.eclipse.jgit.ssh.apache:__pkg__",
+ "//org.eclipse.jgit.ssh.apache.test:__pkg__",
+ "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@bcprov//jar"],
+ exports = ["@jgit_deps//:org_bouncycastle_bcprov_jdk18on"],
)
java_library(
@@ -228,18 +223,24 @@ java_library(
visibility = [
"//org.eclipse.jgit.gpg.bc:__pkg__",
"//org.eclipse.jgit.gpg.bc.test:__pkg__",
+ "//org.eclipse.jgit.ssh.apache:__pkg__",
+ "//org.eclipse.jgit.ssh.apache.test:__pkg__",
+ "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@bcutil//jar"],
+ exports = ["@jgit_deps//:org_bouncycastle_bcutil_jdk18on"],
)
java_library(
name = "bcpkix",
visibility = [
"//org.eclipse.jgit.gpg.bc:__pkg__",
+ "//org.eclipse.jgit.ssh.apache:__pkg__",
+ "//org.eclipse.jgit.ssh.apache.test:__pkg__",
+ "//org.eclipse.jgit.ssh.jsch.test:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@bcpkix//jar"],
+ exports = ["@jgit_deps//:org_bouncycastle_bcpkix_jdk18on"],
)
java_library(
@@ -248,7 +249,7 @@ java_library(
"//org.eclipse.jgit.ssh.jsch:__pkg__",
"//org.eclipse.jgit.test:__pkg__",
],
- exports = ["@jzlib//jar"],
+ exports = ["@jgit_deps//:com_jcraft_jzlib"],
)
java_library(
@@ -256,12 +257,12 @@ java_library(
testonly = 1,
visibility = ["//visibility:public"],
exports = [
- "@bytebuddy-agent//jar",
- "@bytebuddy//jar",
- "@hamcrest//jar",
- "@junit//jar",
- "@mockito//jar",
- "@objenesis//jar",
+ "@jgit_deps//:net_bytebuddy_byte_buddy_agent",
+ "@jgit_deps//:net_bytebuddy_byte_buddy",
+ "@jgit_deps//:org_hamcrest_hamcrest",
+ "@jgit_deps//:junit_junit",
+ "@jgit_deps//:org_mockito_mockito_core",
+ "@jgit_deps//:org_objenesis_objenesis",
],
)
@@ -270,10 +271,10 @@ java_library(
testonly = 1,
visibility = ["//visibility:public"],
exports = [
- "@bytebuddy-agent//jar",
- "@bytebuddy//jar",
- "@mockito//jar",
- "@objenesis//jar",
+ "@jgit_deps//:net_bytebuddy_byte_buddy_agent",
+ "@jgit_deps//:net_bytebuddy_byte_buddy",
+ "@jgit_deps//:org_mockito_mockito_core",
+ "@jgit_deps//:org_objenesis_objenesis",
],
)
@@ -282,7 +283,7 @@ java_library(
testonly = 1,
visibility = ["//visibility:public"],
exports = [
- "@assertj-core//jar",
+ "@jgit_deps//:org_assertj_assertj_core",
],
)
@@ -297,24 +298,24 @@ java_library(
"//org.eclipse.jgit.lfs.server.test:__pkg__",
"//org.eclipse.jgit.pgm:__pkg__",
],
- exports = ["@servlet-api//jar"],
+ exports = ["@jgit_deps//:jakarta_servlet_jakarta_servlet_api_6_1_0"],
)
java_library(
name = "slf4j-api",
visibility = ["//visibility:public"],
- exports = ["@log-api//jar"],
+ exports = ["@jgit_deps//:org_slf4j_slf4j_api"],
)
java_library(
name = "slf4j-simple",
visibility = ["//visibility:public"],
- exports = ["@slf4j-simple//jar"],
+ exports = ["@jgit_deps//:org_slf4j_slf4j_simple"],
)
java_library(
name = "xz",
testonly = 1,
visibility = ["//visibility:public"],
- exports = ["@tukaani-xz//jar"],
+ exports = ["@jgit_deps//:org_tukaani_xz"],
)
diff --git a/lib/jmh/BUILD b/lib/jmh/BUILD
index b15e66c2b9..1bba1a5cb1 100644
--- a/lib/jmh/BUILD
+++ b/lib/jmh/BUILD
@@ -4,9 +4,9 @@ java_library(
name = "jmh",
visibility = ["//visibility:public"],
exports = [
- "@jmh-annotations//jar",
- "@jmh-core//jar",
- "@jopt//jar",
- "@math3//jar",
+ "@jgit_deps//:org_openjdk_jmh_jmh_generator_annprocess",
+ "@jgit_deps//:org_openjdk_jmh_jmh_core",
+ "@jgit_deps//:net_sf_jopt_simple_jopt_simple",
+ "@jgit_deps//:org_apache_commons_commons_math3",
],
)
diff --git a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
index 0069b09467..c32a912035 100644
--- a/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant.test/META-INF/MANIFEST.MF
@@ -5,13 +5,13 @@ Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.ant.test
Bundle-SymbolicName: org.eclipse.jgit.ant.test
Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.ant.tasks;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.ant.tasks;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
org.hamcrest.core;version="[1.1.0,3.0.0)",
org.junit;version="[4.13,5.0.0)"
diff --git a/org.eclipse.jgit.ant.test/pom.xml b/org.eclipse.jgit.ant.test/pom.xml
index c6c81648ae..56e234ae63 100644
--- a/org.eclipse.jgit.ant.test/pom.xml
+++ b/org.eclipse.jgit.ant.test/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ant.test</artifactId>
diff --git a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
index 3af82e4759..139ce8ea06 100644
--- a/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/MANIFEST.MF
@@ -3,13 +3,13 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.ant
Bundle-SymbolicName: org.eclipse.jgit.ant
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: org.apache.tools.ant,
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)"
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)"
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.ant;version="7.2.0",
- org.eclipse.jgit.ant.tasks;version="7.2.0";
+Export-Package: org.eclipse.jgit.ant;version="7.4.0",
+ org.eclipse.jgit.ant.tasks;version="7.4.0";
uses:="org.apache.tools.ant,
org.apache.tools.ant.types"
diff --git a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
index 89d05be73b..b503bb4039 100644
--- a/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ant/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.ant - Sources
Bundle-SymbolicName: org.eclipse.jgit.ant.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ant;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ant;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ant/pom.xml b/org.eclipse.jgit.ant/pom.xml
index 11806f15c6..5c5e14bdaa 100644
--- a/org.eclipse.jgit.ant/pom.xml
+++ b/org.eclipse.jgit.ant/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ant</artifactId>
diff --git a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
index b142a66a8c..badb0f20eb 100644
--- a/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.archive
Bundle-SymbolicName: org.eclipse.jgit.archive
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -13,18 +13,18 @@ Import-Package: org.apache.commons.compress.archivers;version="[1.4,2.0)",
org.apache.commons.compress.compressors.bzip2;version="[1.4,2.0)",
org.apache.commons.compress.compressors.gzip;version="[1.4,2.0)",
org.apache.commons.compress.compressors.xz;version="[1.4,2.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
org.osgi.framework;version="[1.3.0,2.0.0)",
org.tukaani.xz
Bundle-ActivationPolicy: lazy
Bundle-Activator: org.eclipse.jgit.archive.FormatActivator
-Export-Package: org.eclipse.jgit.archive;version="7.2.0";
+Export-Package: org.eclipse.jgit.archive;version="7.4.0";
uses:="org.apache.commons.compress.archivers,
org.osgi.framework,
org.eclipse.jgit.api,
org.eclipse.jgit.lib",
- org.eclipse.jgit.archive.internal;version="7.2.0";x-internal:=true
+ org.eclipse.jgit.archive.internal;version="7.4.0";x-internal:=true
diff --git a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
index 3ca6590f02..df4f8d0e2c 100644
--- a/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.archive/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.archive - Sources
Bundle-SymbolicName: org.eclipse.jgit.archive.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.archive;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.archive;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.archive/pom.xml b/org.eclipse.jgit.archive/pom.xml
index 27a2bba5a2..6b4e810d59 100644
--- a/org.eclipse.jgit.archive/pom.xml
+++ b/org.eclipse.jgit.archive/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.archive</artifactId>
diff --git a/org.eclipse.jgit.benchmarks/BUILD b/org.eclipse.jgit.benchmarks/BUILD
index 6198e4d0c7..7c311e7994 100644
--- a/org.eclipse.jgit.benchmarks/BUILD
+++ b/org.eclipse.jgit.benchmarks/BUILD
@@ -10,6 +10,7 @@ jmh_java_benchmarks(
testonly = 1,
deps = [
"//lib:javaewah",
+ "//lib:junit",
"//lib:slf4j-api",
"//org.eclipse.jgit:jgit",
"//org.eclipse.jgit.junit:junit",
diff --git a/org.eclipse.jgit.benchmarks/pom.xml b/org.eclipse.jgit.benchmarks/pom.xml
index 3079742c79..da20ef4f33 100644
--- a/org.eclipse.jgit.benchmarks/pom.xml
+++ b/org.eclipse.jgit.benchmarks/pom.xml
@@ -16,7 +16,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.benchmarks</artifactId>
@@ -52,6 +52,10 @@
<artifactId>org.eclipse.jgit.junit</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
</dependencies>
<build>
@@ -79,7 +83,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>${maven-compiler-plugin-version}</version>
<configuration>
<encoding>UTF-8</encoding>
<release>${java.version}</release>
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java
index 52a881bd11..44e862e7c8 100644
--- a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java
@@ -24,10 +24,12 @@ import java.util.stream.IntStream;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.internal.storage.file.FileReftableDatabase;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig.TrustStat;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
@@ -38,8 +40,10 @@ import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
+import org.junit.Assume;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
@@ -66,11 +70,14 @@ public class GetRefsBenchmark {
@Param({ "true", "false" })
boolean useRefTable;
- @Param({ "100", "2500", "10000", "50000" })
+ @Param({ "true", "false" })
+ boolean autoRefresh;
+
+ @Param({ "100", "1000", "10000", "100000" })
int numBranches;
- @Param({ "true", "false" })
- boolean trustFolderStat;
+ @Param({ "ALWAYS", "AFTER_OPEN", "NEVER" })
+ TrustStat trustStat;
List<String> branches = new ArrayList<>(numBranches);
@@ -81,10 +88,13 @@ public class GetRefsBenchmark {
@Setup
@SuppressWarnings("boxing")
public void setupBenchmark() throws IOException, GitAPIException {
+ // if we use RefDirectory skip autoRefresh = false
+ Assume.assumeTrue(useRefTable || autoRefresh);
+
String firstBranch = "firstbranch";
testDir = Files.createDirectory(Paths.get("testrepos"));
- String repoName = "branches-" + numBranches + "-trustFolderStat-"
- + trustFolderStat + "-" + refDatabaseType();
+ String repoName = "branches-" + numBranches + "-trustStat-"
+ + trustStat + "-" + refDatabaseType();
Path workDir = testDir.resolve(repoName);
Path repoPath = workDir.resolve(".git");
Git git = Git.init().setDirectory(workDir.toFile()).call();
@@ -97,10 +107,13 @@ public class GetRefsBenchmark {
((FileRepository) git.getRepository()).convertRefStorage(
ConfigConstants.CONFIG_REF_STORAGE_REFTABLE, false,
false);
+ FileReftableDatabase refdb = (FileReftableDatabase) git
+ .getRepository().getRefDatabase();
+ refdb.setAutoRefresh(autoRefresh);
} else {
- cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT,
- trustFolderStat);
+ cfg.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_TRUST_STAT,
+ trustStat);
}
cfg.setInt(ConfigConstants.CONFIG_RECEIVE_SECTION, null,
"maxCommandBytes", Integer.MAX_VALUE);
@@ -112,7 +125,8 @@ public class GetRefsBenchmark {
System.out.println("Preparing test");
System.out.println("- repository: \t\t" + repoPath);
System.out.println("- refDatabase: \t\t" + refDatabaseType());
- System.out.println("- trustFolderStat: \t" + trustFolderStat);
+ System.out.println("- autoRefresh: \t\t" + autoRefresh);
+ System.out.println("- trustStat: \t" + trustStat);
System.out.println("- branches: \t\t" + numBranches);
BatchRefUpdate u = repo.getRefDatabase().newBatchUpdate();
@@ -152,7 +166,8 @@ public class GetRefsBenchmark {
@BenchmarkMode({ Mode.AverageTime })
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS)
- @Measurement(iterations = 2, time = 10, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(2)
public void testGetExactRef(Blackhole blackhole, BenchmarkState state)
throws IOException {
String branchName = state.branches
@@ -164,7 +179,8 @@ public class GetRefsBenchmark {
@BenchmarkMode({ Mode.AverageTime })
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS)
- @Measurement(iterations = 2, time = 10, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(2)
public void testGetRefsByPrefix(Blackhole blackhole, BenchmarkState state)
throws IOException {
String branchPrefix = "refs/heads/branch/" + branchIndex.nextInt(100)
diff --git a/org.eclipse.jgit.coverage/pom.xml b/org.eclipse.jgit.coverage/pom.xml
index 9493c07dbc..58a9e41fe8 100644
--- a/org.eclipse.jgit.coverage/pom.xml
+++ b/org.eclipse.jgit.coverage/pom.xml
@@ -14,7 +14,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -27,88 +27,88 @@
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ant</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.archive</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.http.apache</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.http.server</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.lfs</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.lfs.server</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.pgm</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ui</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ssh.apache</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.test</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ant.test</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.http.test</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.pgm.test</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.lfs.test</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
</dependencies>
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 35294256e1..6e26c9d8b9 100644
--- a/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc.test/META-INF/MANIFEST.MF
@@ -3,20 +3,20 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.gpg.bc.test
Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
-Import-Package: org.bouncycastle.asn1.cryptlib;version="[1.79.0,2.0.0)",
- org.bouncycastle.jce.provider;version="[1.79.0,2.0.0)",
- org.bouncycastle.openpgp;version="[1.79.0,2.0.0)",
- org.bouncycastle.openpgp.operator;version="[1.79.0,2.0.0)",
- org.bouncycastle.openpgp.operator.jcajce;version="[1.79.0,2.0.0)",
- org.bouncycastle.util.encoders;version="[1.79.0,2.0.0)",
- org.eclipse.jgit.gpg.bc.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.gpg.bc.internal.keys;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.sha1;version="[7.2.0,7.3.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)",
+ org.bouncycastle.openpgp.operator;version="[1.80.0,2.0.0)",
+ org.bouncycastle.openpgp.operator.jcajce;version="[1.80.0,2.0.0)",
+ org.bouncycastle.util.encoders;version="[1.80.0,2.0.0)",
+ org.eclipse.jgit.gpg.bc.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.gpg.bc.internal.keys;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.sha1;version="[7.4.0,7.5.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.gpg.bc.test/pom.xml b/org.eclipse.jgit.gpg.bc.test/pom.xml
index 245ba7e127..cfa732a2e2 100644
--- a/org.eclipse.jgit.gpg.bc.test/pom.xml
+++ b/org.eclipse.jgit.gpg.bc.test/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.gpg.bc.test</artifactId>
diff --git a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
index 2120439e51..cb32155513 100644
--- a/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc/META-INF/MANIFEST.MF
@@ -3,28 +3,28 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.gpg.bc
Bundle-SymbolicName: org.eclipse.jgit.gpg.bc;singleton:=true
-Fragment-Host: org.eclipse.jgit;bundle-version="[7.2.0,7.3.0)"
+Fragment-Host: org.eclipse.jgit;bundle-version="[7.4.0,7.5.0)"
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: OSGI-INF/l10n/gpg_bc
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Import-Package: org.bouncycastle.asn1;version="[1.79.0,2.0.0)",
- org.bouncycastle.asn1.x9;version="[1.79.0,2.0.0)",
- org.bouncycastle.bcpg;version="[1.79.0,2.0.0)",
- org.bouncycastle.bcpg.sig;version="[1.79.0,2.0.0)",
- org.bouncycastle.crypto.ec;version="[1.79.0,2.0.0)",
- org.bouncycastle.gpg;version="[1.79.0,2.0.0)",
- org.bouncycastle.gpg.keybox;version="[1.79.0,2.0.0)",
- org.bouncycastle.gpg.keybox.jcajce;version="[1.79.0,2.0.0)",
- org.bouncycastle.jcajce.interfaces;version="[1.79.0,2.0.0)",
- org.bouncycastle.jcajce.util;version="[1.79.0,2.0.0)",
- org.bouncycastle.math.ec;version="[1.79.0,2.0.0)",
- org.bouncycastle.math.field;version="[1.79.0,2.0.0)",
- org.bouncycastle.openpgp;version="[1.79.0,2.0.0)",
- org.bouncycastle.openpgp.jcajce;version="[1.79.0,2.0.0)",
- org.bouncycastle.openpgp.operator;version="[1.79.0,2.0.0)",
- org.bouncycastle.openpgp.operator.jcajce;version="[1.79.0,2.0.0)",
- org.bouncycastle.util.encoders;version="[1.79.0,2.0.0)",
+Import-Package: org.bouncycastle.asn1;version="[1.80.0,2.0.0)",
+ org.bouncycastle.asn1.x9;version="[1.80.0,2.0.0)",
+ org.bouncycastle.bcpg;version="[1.80.0,2.0.0)",
+ org.bouncycastle.bcpg.sig;version="[1.80.0,2.0.0)",
+ org.bouncycastle.crypto.ec;version="[1.80.0,2.0.0)",
+ org.bouncycastle.gpg;version="[1.80.0,2.0.0)",
+ org.bouncycastle.gpg.keybox;version="[1.80.0,2.0.0)",
+ org.bouncycastle.gpg.keybox.jcajce;version="[1.80.0,2.0.0)",
+ org.bouncycastle.jcajce.interfaces;version="[1.80.0,2.0.0)",
+ org.bouncycastle.jcajce.util;version="[1.80.0,2.0.0)",
+ org.bouncycastle.math.ec;version="[1.80.0,2.0.0)",
+ org.bouncycastle.math.field;version="[1.80.0,2.0.0)",
+ org.bouncycastle.openpgp;version="[1.80.0,2.0.0)",
+ org.bouncycastle.openpgp.jcajce;version="[1.80.0,2.0.0)",
+ org.bouncycastle.openpgp.operator;version="[1.80.0,2.0.0)",
+ org.bouncycastle.openpgp.operator.jcajce;version="[1.80.0,2.0.0)",
+ org.bouncycastle.util.encoders;version="[1.80.0,2.0.0)",
org.slf4j;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.2.0";x-friends:="org.eclipse.jgit.gpg.bc.test",
- org.eclipse.jgit.gpg.bc.internal.keys;version="7.2.0";x-friends:="org.eclipse.jgit.gpg.bc.test"
+Export-Package: org.eclipse.jgit.gpg.bc.internal;version="7.4.0";x-friends:="org.eclipse.jgit.gpg.bc.test",
+ org.eclipse.jgit.gpg.bc.internal.keys;version="7.4.0";x-friends:="org.eclipse.jgit.gpg.bc.test"
diff --git a/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
index 532e749cb2..256f893ea4 100644
--- a/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.gpg.bc/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.gpg.bc - Sources
Bundle-SymbolicName: org.eclipse.jgit.gpg.bc.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.gpg.bc;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.gpg.bc/pom.xml b/org.eclipse.jgit.gpg.bc/pom.xml
index f94e2b27b1..fe15d9892d 100644
--- a/org.eclipse.jgit.gpg.bc/pom.xml
+++ b/org.eclipse.jgit.gpg.bc/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.gpg.bc</artifactId>
diff --git a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
index 7d23d53614..ff35e6f960 100644
--- a/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.http.apache
Bundle-SymbolicName: org.eclipse.jgit.http.apache
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
@@ -26,11 +26,11 @@ Import-Package: javax.net.ssl,
org.apache.http.impl.conn;version="[4.4.0,5.0.0)",
org.apache.http.params;version="[4.3.0,5.0.0)",
org.apache.http.ssl;version="[4.3.0,5.0.0)",
- org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)"
-Export-Package: org.eclipse.jgit.transport.http.apache;version="7.2.0";
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)"
+Export-Package: org.eclipse.jgit.transport.http.apache;version="7.4.0";
uses:="org.apache.http.client,
org.eclipse.jgit.transport.http,
org.apache.http.entity,
diff --git a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
index 679252de34..807bb1868a 100644
--- a/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.http.apache - Sources
Bundle-SymbolicName: org.eclipse.jgit.http.apache.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.http.apache;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.apache/pom.xml b/org.eclipse.jgit.http.apache/pom.xml
index c390d8f5ee..d6d294bc02 100644
--- a/org.eclipse.jgit.http.apache/pom.xml
+++ b/org.eclipse.jgit.http.apache/pom.xml
@@ -15,7 +15,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.http.apache</artifactId>
diff --git a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
index 39dc2ef42a..d67e255e19 100644
--- a/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/MANIFEST.MF
@@ -3,14 +3,14 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.http.server
Bundle-SymbolicName: org.eclipse.jgit.http.server
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.http.server;version="7.2.0",
- org.eclipse.jgit.http.server.glue;version="7.2.0";
+Export-Package: org.eclipse.jgit.http.server;version="7.4.0",
+ org.eclipse.jgit.http.server.glue;version="7.4.0";
uses:="jakarta.servlet,
jakarta.servlet.http",
- org.eclipse.jgit.http.server.resolver;version="7.2.0";
+ org.eclipse.jgit.http.server.resolver;version="7.4.0";
uses:="jakarta.servlet.http
org.eclipse.jgit.transport.resolver,
org.eclipse.jgit.lib,
@@ -19,14 +19,14 @@ Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
jakarta.servlet.http;version="[6.0.0,7.0.0)",
- org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.parser;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.resolver;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)"
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)"
diff --git a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
index e7940bd358..b9f500fd02 100644
--- a/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.http.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.http.server - Sources
Bundle-SymbolicName: org.eclipse.jgit.http.server.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.http.server;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.http.server/pom.xml b/org.eclipse.jgit.http.server/pom.xml
index 3f79f8b82d..3252d7ea92 100644
--- a/org.eclipse.jgit.http.server/pom.xml
+++ b/org.eclipse.jgit.http.server/pom.xml
@@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.http.server</artifactId>
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index 3550501dba..49ab1caadb 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.http.test
Bundle-SymbolicName: org.eclipse.jgit.http.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -29,26 +29,26 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util.thread;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.http.server;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.http.server.glue;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.http.server.resolver;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http.apache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.resolver;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.http.server;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.http.server.glue;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.http.server.resolver;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.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.http.test/pom.xml b/org.eclipse.jgit.http.test/pom.xml
index 2f25191fee..9500978896 100644
--- a/org.eclipse.jgit.http.test/pom.xml
+++ b/org.eclipse.jgit.http.test/pom.xml
@@ -18,7 +18,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.http.test</artifactId>
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index 850e895790..b0d17adb3a 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -1728,7 +1728,8 @@ public class SmartClientSmartServerTest extends AllProtocolsHttpTestCase {
assertEquals(Q, remoteRepository.exactRef(dstName).getObjectId());
fsck(remoteRepository, Q);
- final ReflogReader log = remoteRepository.getReflogReader(dstName);
+ final ReflogReader log = remoteRepository.getRefDatabase()
+ .getReflogReader(dstName);
assertNotNull("has log for " + dstName, log);
final ReflogEntry last = log.getLastEntry();
diff --git a/org.eclipse.jgit.junit.http/BUILD b/org.eclipse.jgit.junit.http/BUILD
index 5ddd0c8d56..66620cea51 100644
--- a/org.eclipse.jgit.junit.http/BUILD
+++ b/org.eclipse.jgit.junit.http/BUILD
@@ -6,7 +6,7 @@ java_library(
name = "junit-http",
testonly = 1,
srcs = glob(["src/**/*.java"]),
- resources = glob(["resources/**"]),
+ resources = glob(["resources/**"], allow_empty=True),
# TODO(davido): we want here provided deps
deps = [
"//lib:jetty-http",
diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index 4ba595901b..7a5a02640d 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.junit.http
Bundle-SymbolicName: org.eclipse.jgit.junit.http
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
@@ -22,17 +22,17 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util.ssl;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.http.server;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.resolver;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.http.server;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.4.0,7.5.0)",
org.junit;version="[4.13,5.0.0)",
org.slf4j.helpers;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.junit.http;version="7.2.0";
+Export-Package: org.eclipse.jgit.junit.http;version="7.4.0";
uses:="org.eclipse.jgit.transport,
jakarta.servlet,
jakarta.servlet.http,
diff --git a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
index 5abd7d6d51..a9ba3992f0 100644
--- a/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.junit.http - Sources
Bundle-SymbolicName: org.eclipse.jgit.junit.http.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit.http;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.http/pom.xml b/org.eclipse.jgit.junit.http/pom.xml
index ea38ae31ba..9f405f350c 100644
--- a/org.eclipse.jgit.junit.http/pom.xml
+++ b/org.eclipse.jgit.junit.http/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.junit.http</artifactId>
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
index bcd9fbfc81..6775b6fb24 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/MANIFEST.MF
@@ -3,46 +3,46 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.junit.ssh
Bundle-SymbolicName: org.eclipse.jgit.junit.ssh
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Import-Package: org.apache.sshd.common;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.config.keys;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.file.virtualfs;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.helpers;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.io;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.kex;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.keyprovider;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.session;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.signature;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.buffer;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.logging;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.security;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.threads;version="[2.14.0,2.15.0)",
- org.apache.sshd.core;version="[2.14.0,2.15.0)",
- org.apache.sshd.server;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.auth;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.auth.gss;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.auth.keyboard;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.auth.password;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.command;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.session;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.shell;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.subsystem;version="[2.14.0,2.15.0)",
- org.apache.sshd.sftp;version="[2.14.0,2.15.0)",
- org.apache.sshd.sftp.server;version="[2.14.0,2.15.0)",
- org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+Import-Package: org.apache.sshd.common;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.config.keys;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.file.virtualfs;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.helpers;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.io;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.kex;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.keyprovider;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.session;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.signature;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.buffer;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.logging;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.security;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.threads;version="[2.15.0,2.16.0)",
+ org.apache.sshd.core;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.auth;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.auth.gss;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.auth.keyboard;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.auth.password;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.command;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.session;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.shell;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.subsystem;version="[2.15.0,2.16.0)",
+ org.apache.sshd.sftp;version="[2.15.0,2.16.0)",
+ org.apache.sshd.sftp.server;version="[2.15.0,2.16.0)",
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.experimental.theories;version="[4.13,5.0.0)",
org.slf4j;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.junit.ssh;version="7.2.0"
+Export-Package: org.eclipse.jgit.junit.ssh;version="7.4.0"
diff --git a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
index b8f22cea5d..a01cf267ae 100644
--- a/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit.ssh/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.junit.ssh - Sources
Bundle-SymbolicName: org.eclipse.jgit.junit.ssh.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit.ssh;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit.ssh/pom.xml b/org.eclipse.jgit.junit.ssh/pom.xml
index f937748212..da5920b5e2 100644
--- a/org.eclipse.jgit.junit.ssh/pom.xml
+++ b/org.eclipse.jgit.junit.ssh/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.junit.ssh</artifactId>
diff --git a/org.eclipse.jgit.junit/.settings/.api_filters b/org.eclipse.jgit.junit/.settings/.api_filters
new file mode 100644
index 0000000000..27815301c2
--- /dev/null
+++ b/org.eclipse.jgit.junit/.settings/.api_filters
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.jgit.junit" version="2">
+ <resource path="src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java" type="org.eclipse.jgit.junit.LocalDiskRepositoryTestCase">
+ <filter id="336658481">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.junit.LocalDiskRepositoryTestCase"/>
+ <message_argument value="testRoot"/>
+ </message_arguments>
+ </filter>
+ </resource>
+</component>
diff --git a/org.eclipse.jgit.junit/BUILD b/org.eclipse.jgit.junit/BUILD
index 623c5beb2d..f4a7165dbb 100644
--- a/org.eclipse.jgit.junit/BUILD
+++ b/org.eclipse.jgit.junit/BUILD
@@ -7,7 +7,7 @@ java_library(
testonly = 1,
srcs = glob(["src/**/*.java"]),
resource_strip_prefix = "org.eclipse.jgit.junit/resources",
- resources = glob(["resources/**"]),
+ resources = glob(["resources/**"], allow_empty=True),
deps = [
"//lib:junit",
# We want these deps to be provided_deps
diff --git a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
index 6488a887fb..92371aec69 100644
--- a/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/MANIFEST.MF
@@ -3,36 +3,36 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.junit
Bundle-SymbolicName: org.eclipse.jgit.junit
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Import-Package: org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.dircache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.pack;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.util;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.merge;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="7.2.0",
- org.eclipse.jgit.treewalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.io;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.time;version="[7.2.0,7.3.0)",
+Import-Package: org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.dircache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.util;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.merge;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="7.4.0",
+ org.eclipse.jgit.treewalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.io;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.time;version="[7.4.0,7.5.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)",
org.junit.runners;version="[4.13,5.0.0)",
org.junit.runners.model;version="[4.13,5.0.0)",
org.slf4j;version="[1.7.0,3.0.0)"
-Export-Package: org.eclipse.jgit.junit;version="7.2.0";
+Export-Package: org.eclipse.jgit.junit;version="7.4.0";
uses:="org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
@@ -45,4 +45,4 @@ Export-Package: org.eclipse.jgit.junit;version="7.2.0";
org.junit.runners.model,
org.junit.runner,
org.eclipse.jgit.util.time",
- org.eclipse.jgit.junit.time;version="7.2.0";uses:="org.eclipse.jgit.util.time"
+ org.eclipse.jgit.junit.time;version="7.4.0";uses:="org.eclipse.jgit.util.time"
diff --git a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
index 9d494cb2e0..5b1590816a 100644
--- a/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.junit/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.junit - Sources
Bundle-SymbolicName: org.eclipse.jgit.junit.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.junit;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.junit;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.junit/pom.xml b/org.eclipse.jgit.junit/pom.xml
index 9f43ced73b..f50b9d8aa2 100644
--- a/org.eclipse.jgit.junit/pom.xml
+++ b/org.eclipse.jgit.junit/pom.xml
@@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.junit</artifactId>
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/FakeIndexFactory.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/FakeIndexFactory.java
new file mode 100644
index 0000000000..eb23bec584
--- /dev/null
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/FakeIndexFactory.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2025, Google Inc.
+ *
+ * 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.junit;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toUnmodifiableList;
+
+import java.io.IOException;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.file.PackIndex.EntriesIterator;
+import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * Create indexes with predefined data
+ *
+ * @since 7.2
+ */
+public class FakeIndexFactory {
+
+ /**
+ * An object for the fake index
+ *
+ * @param name
+ * a sha1
+ * @param offset
+ * the (fake) position of the object in the pack
+ */
+ public record IndexObject(String name, long offset) {
+ /**
+ * Name (sha1) as an objectId
+ *
+ * @return name (a sha1) as an objectId.
+ */
+ public ObjectId getObjectId() {
+ return ObjectId.fromString(name);
+ }
+ }
+
+ /**
+ * Return an index populated with these objects
+ *
+ * @param objs
+ * objects to be indexed
+ * @return a PackIndex implementation
+ */
+ public static PackIndex indexOf(List<IndexObject> objs) {
+ return new FakePackIndex(objs);
+ }
+
+ /**
+ * Return a reverse pack index with these objects
+ *
+ * @param objs
+ * objects to be indexed
+ * @return a PackReverseIndex implementation
+ */
+ public static PackReverseIndex reverseIndexOf(List<IndexObject> objs) {
+ return new FakeReverseIndex(objs);
+ }
+
+ private FakeIndexFactory() {
+ }
+
+ private static class FakePackIndex implements PackIndex {
+ private static final Comparator<IndexObject> SHA1_COMPARATOR = (o1,
+ o2) -> String.CASE_INSENSITIVE_ORDER.compare(o1.name(),
+ o2.name());
+
+ private final Map<String, IndexObject> idx;
+
+ private final List<IndexObject> sha1Ordered;
+
+ private final long offset64count;
+
+ FakePackIndex(List<IndexObject> objs) {
+ sha1Ordered = objs.stream().sorted(SHA1_COMPARATOR)
+ .collect(toUnmodifiableList());
+ idx = objs.stream().collect(toMap(IndexObject::name, identity()));
+ offset64count = objs.stream()
+ .filter(o -> o.offset > Integer.MAX_VALUE).count();
+ }
+
+ @Override
+ public Iterator<MutableEntry> iterator() {
+ return new FakeEntriesIterator(sha1Ordered);
+ }
+
+ @Override
+ public long getObjectCount() {
+ return sha1Ordered.size();
+ }
+
+ @Override
+ public long getOffset64Count() {
+ return offset64count;
+ }
+
+ @Override
+ public ObjectId getObjectId(long nthPosition) {
+ return ObjectId
+ .fromString(sha1Ordered.get((int) nthPosition).name());
+ }
+
+ @Override
+ public long getOffset(long nthPosition) {
+ return sha1Ordered.get((int) nthPosition).offset();
+ }
+
+ @Override
+ public long findOffset(AnyObjectId objId) {
+ IndexObject o = idx.get(objId.name());
+ if (o == null) {
+ return -1;
+ }
+ return o.offset();
+ }
+
+ @Override
+ public int findPosition(AnyObjectId objId) {
+ IndexObject o = idx.get(objId.name());
+ if (o == null) {
+ return -1;
+ }
+ return sha1Ordered.indexOf(o);
+ }
+
+ @Override
+ public long findCRC32(AnyObjectId objId) throws MissingObjectException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasCRC32Support() {
+ return false;
+ }
+
+ @Override
+ public void resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
+ int matchLimit) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] getChecksum() {
+ return new byte[0];
+ }
+ }
+
+ private static class FakeReverseIndex implements PackReverseIndex {
+ private static final Comparator<IndexObject> OFFSET_COMPARATOR = Comparator
+ .comparingLong(IndexObject::offset);
+
+ private final List<IndexObject> byOffset;
+
+ private final Map<Long, IndexObject> ridx;
+
+ FakeReverseIndex(List<IndexObject> objs) {
+ byOffset = objs.stream().sorted(OFFSET_COMPARATOR)
+ .collect(toUnmodifiableList());
+ ridx = byOffset.stream()
+ .collect(toMap(IndexObject::offset, identity()));
+ }
+
+ @Override
+ public void verifyPackChecksum(String packFilePath) {
+ // Do nothing
+ }
+
+ @Override
+ public ObjectId findObject(long offset) {
+ IndexObject indexObject = ridx.get(offset);
+ if (indexObject == null) {
+ return null;
+ }
+ return ObjectId.fromString(indexObject.name());
+ }
+
+ @Override
+ public long findNextOffset(long offset, long maxOffset)
+ throws CorruptObjectException {
+ IndexObject o = ridx.get(offset);
+ if (o == null) {
+ throw new CorruptObjectException("Invalid offset"); //$NON-NLS-1$
+ }
+ int pos = byOffset.indexOf(o);
+ if (pos == byOffset.size() - 1) {
+ return maxOffset;
+ }
+ return byOffset.get(pos + 1).offset();
+ }
+
+ @Override
+ public int findPosition(long offset) {
+ IndexObject indexObject = ridx.get(offset);
+ return byOffset.indexOf(indexObject);
+ }
+
+ @Override
+ public ObjectId findObjectByPosition(int nthPosition) {
+ return byOffset.get(nthPosition).getObjectId();
+ }
+ }
+
+ private static class FakeEntriesIterator extends EntriesIterator {
+
+ private static final byte[] buffer = new byte[Constants.OBJECT_ID_LENGTH];
+
+ private final Iterator<IndexObject> it;
+
+ FakeEntriesIterator(List<IndexObject> objs) {
+ super(objs.size());
+ it = objs.iterator();
+ }
+
+ @Override
+ protected void readNext() {
+ IndexObject next = it.next();
+ next.getObjectId().copyRawTo(buffer, 0);
+ setIdBuffer(buffer, 0);
+ setOffset(next.offset());
+ }
+ }
+}
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
index c15fc9921e..0d20f6488a 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
@@ -26,14 +26,13 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.internal.util.ShutdownHook;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -48,6 +47,7 @@ import org.eclipse.jgit.util.SystemReader;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestName;
/**
@@ -85,6 +85,16 @@ public abstract class LocalDiskRepositoryTestCase {
protected MockSystemReader mockSystemReader;
private final Set<Repository> toClose = new HashSet<>();
+
+ /**
+ * Temporary test root directory for files created by tests.
+ * @since 7.2
+ */
+ @Rule
+ public TemporaryFolder testRoot = new TemporaryFolder();
+
+ Random rand = new Random();
+
private File tmp;
private File homeDir;
@@ -115,11 +125,8 @@ public abstract class LocalDiskRepositoryTestCase {
*/
@Before
public void setUp() throws Exception {
- tmp = File.createTempFile("jgit_" + getTestName() + '_', "_tmp");
- Cleanup.deleteOnShutdown(tmp);
- if (!tmp.delete() || !tmp.mkdir()) {
- throw new IOException("Cannot create " + tmp);
- }
+ tmp = testRoot.newFolder(getTestName() + rand.nextInt());
+
mockSystemReader = new MockSystemReader();
SystemReader.setInstance(mockSystemReader);
@@ -220,12 +227,6 @@ public abstract class LocalDiskRepositoryTestCase {
System.gc();
}
FS.DETECTED.setUserHome(homeDir);
- if (tmp != null) {
- recursiveDelete(tmp, false, true);
- }
- if (tmp != null && !tmp.exists()) {
- Cleanup.removed(tmp);
- }
SystemReader.setInstance(null);
}
@@ -624,41 +625,4 @@ public abstract class LocalDiskRepositoryTestCase {
private static HashMap<String, String> cloneEnv() {
return new HashMap<>(System.getenv());
}
-
- private static final class Cleanup {
- private static final Cleanup INSTANCE = new Cleanup();
-
- static {
- ShutdownHook.INSTANCE.register(() -> INSTANCE.onShutdown());
- }
-
- private final Set<File> toDelete = ConcurrentHashMap.newKeySet();
-
- private Cleanup() {
- // empty
- }
-
- static void deleteOnShutdown(File tmp) {
- INSTANCE.toDelete.add(tmp);
- }
-
- static void removed(File tmp) {
- INSTANCE.toDelete.remove(tmp);
- }
-
- private void onShutdown() {
- // On windows accidentally open files or memory
- // mapped regions may prevent files from being deleted.
- // Suggesting a GC increases the likelihood that our
- // test repositories actually get removed after the
- // tests, even in the case of failure.
- System.gc();
- synchronized (this) {
- boolean silent = false;
- boolean failOnError = false;
- for (File tmp : toDelete)
- recursiveDelete(tmp, silent, failOnError);
- }
- }
- }
}
diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
index 706930a50f..2d00a850e5 100644
--- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
+++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
@@ -159,8 +159,8 @@ public class TestRepository<R extends Repository> implements AutoCloseable {
this.pool = rw;
this.inserter = db.newObjectInserter();
this.mockSystemReader = reader;
- long now = mockSystemReader.getCurrentTime();
- int tz = mockSystemReader.getTimezone(now);
+ Instant now = mockSystemReader.now();
+ ZoneId tz = mockSystemReader.getTimeZoneAt(now);
defaultAuthor = new PersonIdent(AUTHOR, AUTHOR_EMAIL, now, tz);
defaultCommitter = new PersonIdent(COMMITTER, COMMITTER_EMAIL, now, tz);
}
@@ -201,7 +201,7 @@ public class TestRepository<R extends Repository> implements AutoCloseable {
* @since 4.2
* @deprecated Use {@link #getInstant()} instead.
*/
- @Deprecated
+ @Deprecated(since = "7.2")
public Date getDate() {
return new Date(mockSystemReader.getCurrentTime());
}
@@ -222,7 +222,7 @@ public class TestRepository<R extends Repository> implements AutoCloseable {
* @return timezone used for default identities.
* @deprecated Use {@link #getTimeZoneId()} instead.
*/
- @Deprecated
+ @Deprecated(since = "7.2")
public TimeZone getTimeZone() {
return mockSystemReader.getTimeZone();
}
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 77749c8d89..414cec87ed 100644
--- a/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.lfs.server.test
Bundle-SymbolicName: org.eclipse.jgit.lfs.server.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -26,24 +26,24 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util.security;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util.thread;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.server;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.server.fs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.test;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.server;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.test;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
org.hamcrest.core;version="[1.1.0,3.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.rules;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.lfs.server.test/pom.xml b/org.eclipse.jgit.lfs.server.test/pom.xml
index 98e63b0f1e..5c4b27f857 100644
--- a/org.eclipse.jgit.lfs.server.test/pom.xml
+++ b/org.eclipse.jgit.lfs.server.test/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.lfs.server.test</artifactId>
diff --git a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
index 1973b26477..019c6ec849 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/MANIFEST.MF
@@ -3,19 +3,19 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.lfs.server
Bundle-SymbolicName: org.eclipse.jgit.lfs.server
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.lfs.server;version="7.2.0";
+Export-Package: org.eclipse.jgit.lfs.server;version="7.4.0";
uses:="jakarta.servlet.http,
org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.fs;version="7.2.0";
+ org.eclipse.jgit.lfs.server.fs;version="7.4.0";
uses:="jakarta.servlet,
jakarta.servlet.http,
org.eclipse.jgit.lfs.server,
org.eclipse.jgit.lfs.lib",
- org.eclipse.jgit.lfs.server.internal;version="7.2.0";x-internal:=true,
- org.eclipse.jgit.lfs.server.s3;version="7.2.0";
+ org.eclipse.jgit.lfs.server.internal;version="7.4.0";x-internal:=true,
+ org.eclipse.jgit.lfs.server.s3;version="7.4.0";
uses:="org.eclipse.jgit.lfs.server,
org.eclipse.jgit.lfs.lib"
Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -24,15 +24,15 @@ Import-Package: com.google.gson;version="[2.8.0,3.0.0)",
jakarta.servlet.annotation;version="[6.0.0,7.0.0)",
jakarta.servlet.http;version="[6.0.0,7.0.0)",
org.apache.http;version="[4.3.0,5.0.0)",
- org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http.apache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
org.slf4j;version="[1.7.0,3.0.0)"
diff --git a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
index 73f5cab59d..82103de270 100644
--- a/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.server/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.lfs.server - Sources
Bundle-SymbolicName: org.eclipse.jgit.lfs.server.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.lfs.server;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs.server/pom.xml b/org.eclipse.jgit.lfs.server/pom.xml
index 0dd0786050..392fe172dc 100644
--- a/org.eclipse.jgit.lfs.server/pom.xml
+++ b/org.eclipse.jgit.lfs.server/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.lfs.server</artifactId>
diff --git a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
index f27377447c..bbd5dd2f88 100644
--- a/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs.test/META-INF/MANIFEST.MF
@@ -3,28 +3,28 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.lfs.test
Bundle-SymbolicName: org.eclipse.jgit.lfs.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Import-Package: org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.attributes;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.dfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+Import-Package: org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.attributes;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
org.hamcrest.core;version="[1.1.0,3.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)"
-Export-Package: org.eclipse.jgit.lfs.test;version="7.2.0";x-friends:="org.eclipse.jgit.lfs.server.test"
+Export-Package: org.eclipse.jgit.lfs.test;version="7.4.0";x-friends:="org.eclipse.jgit.lfs.server.test"
diff --git a/org.eclipse.jgit.lfs.test/pom.xml b/org.eclipse.jgit.lfs.test/pom.xml
index eff7e0b7eb..01a0c29ab8 100644
--- a/org.eclipse.jgit.lfs.test/pom.xml
+++ b/org.eclipse.jgit.lfs.test/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.lfs.test</artifactId>
diff --git a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
index fb211cc89c..e7f31773d7 100644
--- a/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/MANIFEST.MF
@@ -3,32 +3,32 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.lfs
Bundle-SymbolicName: org.eclipse.jgit.lfs
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
-Export-Package: org.eclipse.jgit.lfs;version="7.2.0",
- org.eclipse.jgit.lfs.errors;version="7.2.0",
- org.eclipse.jgit.lfs.internal;version="7.2.0";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
- org.eclipse.jgit.lfs.lib;version="7.2.0"
+Export-Package: org.eclipse.jgit.lfs;version="7.4.0",
+ org.eclipse.jgit.lfs.errors;version="7.4.0",
+ org.eclipse.jgit.lfs.internal;version="7.4.0";x-friends:="org.eclipse.jgit.lfs.test,org.eclipse.jgit.lfs.server.fs,org.eclipse.jgit.lfs.server",
+ org.eclipse.jgit.lfs.lib;version="7.4.0"
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: com.google.gson;version="[2.8.2,3.0.0)",
com.google.gson.stream;version="[2.8.2,3.0.0)",
- org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)";resolution:=optional,
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.attributes;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.diff;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.dircache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.hooks;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.pack;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.io;version="[7.2.0,7.3.0)"
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)";resolution:=optional,
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.attributes;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.diff;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.dircache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.hooks;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.pack;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.io;version="[7.4.0,7.5.0)"
diff --git a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
index 4ca03a3f72..b1ea912859 100644
--- a/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.lfs/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.lfs - Sources
Bundle-SymbolicName: org.eclipse.jgit.lfs.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.lfs;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.lfs/pom.xml b/org.eclipse.jgit.lfs/pom.xml
index 329740085e..28aa4ea7a2 100644
--- a/org.eclipse.jgit.lfs/pom.xml
+++ b/org.eclipse.jgit.lfs/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.lfs</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
index 43980f06ae..7cda565235 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
index 59345e75f9..7a4331c37e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml
index ae91bd5405..7f67dc305b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.gpg.bc"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
</url>
<requires>
- <import plugin="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
+ <import plugin="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml
index aa88700423..cf06407d1a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.gpg.bc.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
index 57d7d8dd69..97abb2d186 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.http.apache"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
</url>
<requires>
- <import plugin="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
+ <import plugin="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
index 2038cfd58c..40738e38a2 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.http.apache.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
index d9a9db307d..79cd1ba8bf 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.junit"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -24,7 +24,7 @@
<requires>
<import plugin="com.jcraft.jsch"/>
- <import plugin="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
+ <import plugin="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
index d98990c532..9f8496426f 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
index 8f0c532a4a..5c324bd11e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.lfs"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
</url>
<requires>
- <import feature="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
+ <import feature="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
index 7e1b0c8226..1aef24e1d6 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.lfs.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
index 78867c96c0..330ed6eaa5 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.pgm"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -35,9 +35,9 @@
version="0.0.0"/>
<requires>
- <import feature="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
- <import feature="org.eclipse.jgit.lfs" version="7.2.0" match="equivalent"/>
- <import feature="org.eclipse.jgit.ssh.apache" version="7.2.0" match="equivalent"/>
+ <import feature="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
+ <import feature="org.eclipse.jgit.lfs" version="7.4.0" match="equivalent"/>
+ <import feature="org.eclipse.jgit.ssh.apache" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
index 02435b6c08..f0fbe45391 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.pgm.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
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 de5477203e..eef699cfa1 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/category.xml
@@ -123,12 +123,6 @@
<bundle id="org.eclipse.jetty.util.ajax.source">
<category name="JGit-dependency-bundles"/>
</bundle>
- <bundle id="net.i2p.crypto.eddsa">
- <category name="JGit-dependency-bundles"/>
- </bundle>
- <bundle id="net.i2p.crypto.eddsa.source">
- <category name="JGit-dependency-bundles"/>
- </bundle>
<bundle id="org.apache.ant">
<category name="JGit-dependency-bundles"/>
</bundle>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
index d3773f54f3..23c7bd1082 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.repository/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.repository</artifactId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
index b8f402e4f0..aa384a0389 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.source"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
</url>
<requires>
- <import feature="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
+ <import feature="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
index 4eee8255cc..af577afa8c 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.source.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
@@ -30,7 +30,7 @@
<dependency>
<groupId>org.eclipse.jgit.feature</groupId>
<artifactId>org.eclipse.jgit</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</dependency>
</dependencies>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
index 811beafca6..14d12273aa 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.ssh.apache"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
</url>
<requires>
- <import feature="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
+ <import feature="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
index 025844c6b0..4024b2955e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.apache.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml
index a0cd57bcbb..a4a005de9b 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jgit.ssh.jsch"
label="%featureName"
- version="7.2.0.qualifier"
+ version="7.4.0.qualifier"
provider-name="%providerName">
<description url="http://www.eclipse.org/jgit/">
@@ -23,7 +23,7 @@
</url>
<requires>
- <import plugin="org.eclipse.jgit" version="7.2.0" match="equivalent"/>
+ <import plugin="org.eclipse.jgit" version="7.4.0" match="equivalent"/>
</requires>
<plugin
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml
index 81c9651fd9..679fea17a6 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.ssh.jsch.feature/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jgit.feature</groupId>
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
index ff4f0262f1..cbed9191c5 100644
--- 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
@@ -1,15 +1,13 @@
<?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="1734684337">
+<target name="jgit-4.32" sequenceNumber="1749854000">
<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="net.i2p.crypto.eddsa" version="0.3.0"/>
- <unit id="net.i2p.crypto.eddsa.source" version="0.3.0"/>
<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"/>
@@ -63,13 +61,13 @@
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-osgi</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-sftp</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -79,7 +77,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
- <version>5.14.2</version>
+ <version>5.18.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -89,13 +87,13 @@
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
- <version>5.15.0</version>
+ <version>5.17.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
- <version>5.15.0</version>
+ <version>5.17.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -105,49 +103,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
@@ -183,7 +181,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
- <version>2.11.0</version>
+ <version>2.13.1</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -193,13 +191,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.15.11</version>
+ <version>1.17.5</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.15.11</version>
+ <version>1.17.5</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -209,25 +207,25 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcutil-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -237,7 +235,7 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
- <version>3.27.0</version>
+ <version>3.27.3</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -257,7 +255,7 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.17.1</version>
+ <version>1.18.0</version>
<type>jar</type>
</dependency>
<dependency>
@@ -275,13 +273,13 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.18.0</version>
+ <version>2.19.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.3.4</version>
+ <version>1.3.5</version>
<type>jar</type>
</dependency>
</dependencies>
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
index a94fc6c9d4..1a8648a78c 100644
--- 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
@@ -1,15 +1,13 @@
<?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="1734684337">
+<target name="jgit-4.33" sequenceNumber="1749854000">
<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="net.i2p.crypto.eddsa" version="0.3.0"/>
- <unit id="net.i2p.crypto.eddsa.source" version="0.3.0"/>
<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"/>
@@ -63,13 +61,13 @@
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-osgi</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-sftp</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -79,7 +77,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
- <version>5.14.2</version>
+ <version>5.18.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -89,13 +87,13 @@
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
- <version>5.15.0</version>
+ <version>5.17.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
- <version>5.15.0</version>
+ <version>5.17.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -105,49 +103,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
@@ -183,7 +181,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
- <version>2.11.0</version>
+ <version>2.13.1</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -193,13 +191,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.15.11</version>
+ <version>1.17.5</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.15.11</version>
+ <version>1.17.5</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -209,25 +207,25 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcutil-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -237,7 +235,7 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
- <version>3.27.0</version>
+ <version>3.27.3</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -257,7 +255,7 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.17.1</version>
+ <version>1.18.0</version>
<type>jar</type>
</dependency>
<dependency>
@@ -275,13 +273,13 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.18.0</version>
+ <version>2.19.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.3.4</version>
+ <version>1.3.5</version>
<type>jar</type>
</dependency>
</dependencies>
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 c67117ea45..0d636aaae8 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,15 +1,13 @@
<?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="1734684337">
+<target name="jgit-4.34" sequenceNumber="1749854000">
<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="net.i2p.crypto.eddsa" version="0.3.0"/>
- <unit id="net.i2p.crypto.eddsa.source" version="0.3.0"/>
<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.httpcomponents.httpclient" version="4.5.14"/>
@@ -63,13 +61,13 @@
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-osgi</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-sftp</artifactId>
- <version>2.14.0</version>
+ <version>2.15.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -79,7 +77,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
- <version>5.14.2</version>
+ <version>5.18.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -89,13 +87,13 @@
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
- <version>5.15.0</version>
+ <version>5.17.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
- <version>5.15.0</version>
+ <version>5.17.0</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -105,49 +103,49 @@
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-session</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
- <version>12.0.16</version>
+ <version>12.0.22</version>
<type>jar</type>
</dependency>
<dependency>
@@ -183,7 +181,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
- <version>2.11.0</version>
+ <version>2.13.1</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -193,13 +191,13 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
- <version>1.15.11</version>
+ <version>1.17.5</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
- <version>1.15.11</version>
+ <version>1.17.5</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -209,25 +207,25 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcutil-jdk18on</artifactId>
- <version>1.79</version>
+ <version>1.81</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -237,7 +235,7 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
- <version>3.27.0</version>
+ <version>3.27.3</version>
<type>jar</type>
</dependency>
</dependencies>
@@ -257,7 +255,7 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.17.1</version>
+ <version>1.18.0</version>
<type>jar</type>
</dependency>
<dependency>
@@ -275,13 +273,13 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.18.0</version>
+ <version>2.19.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.3.4</version>
+ <version>1.3.5</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
new file mode 100644
index 0000000000..c270c0978c
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.target
@@ -0,0 +1,288 @@
+<?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="1749854000">
+ <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.15.v20240901-1000"/>
+ <unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+ <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.v20240929-1000"/>
+ <unit id="org.junit.source" version="4.13.2.v20240929-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/2025-03"/>
+ </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/2025-03/"/>
+ </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.15.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-sftp</artifactId>
+ <version>2.15.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.18.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.17.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>net.java.dev.jna</groupId>
+ <artifactId>jna-platform</artifactId>
+ <version>5.17.0</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.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-security</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-session</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util-ajax</artifactId>
+ <version>12.0.22</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.1</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.5</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy-agent</artifactId>
+ <version>1.17.5</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.81</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk18on</artifactId>
+ <version>1.81</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk18on</artifactId>
+ <version>1.81</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcutil-jdk18on</artifactId>
+ <version>1.81</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.3</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.18.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>1.27.1</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.17.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.19.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.35.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.tpd
new file mode 100644
index 0000000000..3c0646eb46
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.35.tpd
@@ -0,0 +1,8 @@
+target "jgit-4.35" with source configurePhase
+
+include "orbit/orbit-4.35.tpd"
+include "maven/dependencies.tpd"
+
+location "https://download.eclipse.org/staging/2025-03/" {
+ org.eclipse.osgi lazy
+}
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
new file mode 100644
index 0000000000..8c22b66b5d
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.target
@@ -0,0 +1,288 @@
+<?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="1749854000">
+ <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.15.v20240901-1000"/>
+ <unit id="org.apache.ant.source" version="1.10.15.v20240901-1000"/>
+ <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.v20240929-1000"/>
+ <unit id="org.junit.source" version="4.13.2.v20240929-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/2025-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/2025-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.15.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-sftp</artifactId>
+ <version>2.15.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.18.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.17.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>net.java.dev.jna</groupId>
+ <artifactId>jna-platform</artifactId>
+ <version>5.17.0</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.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-security</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-session</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>12.0.22</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util-ajax</artifactId>
+ <version>12.0.22</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.1</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.5</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy-agent</artifactId>
+ <version>1.17.5</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.81</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk18on</artifactId>
+ <version>1.81</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk18on</artifactId>
+ <version>1.81</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcutil-jdk18on</artifactId>
+ <version>1.81</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.3</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.18.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>1.27.1</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.17.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.19.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.36.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.tpd
new file mode 100644
index 0000000000..053929fb8f
--- /dev/null
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.36.tpd
@@ -0,0 +1,8 @@
+target "jgit-4.36" with source configurePhase
+
+include "orbit/orbit-4.36.tpd"
+include "maven/dependencies.tpd"
+
+location "https://download.eclipse.org/staging/2025-06/" {
+ org.eclipse.osgi lazy
+}
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 bbea833864..b2282796e4 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
@@ -10,7 +10,7 @@ maven apache
dependency {
groupId = "commons-codec"
artifactId = "commons-codec"
- version = "1.17.1"
+ version = "1.18.0"
}
dependency {
groupId = "org.apache.commons"
@@ -25,12 +25,12 @@ maven apache
dependency {
groupId = "commons-io"
artifactId = "commons-io"
- version = "2.18.0"
+ version = "2.19.0"
}
dependency {
groupId = "commons-logging"
artifactId = "commons-logging"
- version = "1.3.4"
+ version = "1.3.5"
}
}
@@ -56,7 +56,7 @@ maven assertj
dependency {
groupId = "org.assertj"
artifactId = "assertj-core"
- version = "3.27.0"
+ version = "3.27.3"
}
}
@@ -69,22 +69,22 @@ maven bouncycastle
dependency {
groupId = "org.bouncycastle"
artifactId = "bcpg-jdk18on"
- version = "1.79"
+ version = "1.81"
}
dependency {
groupId = "org.bouncycastle"
artifactId = "bcprov-jdk18on"
- version = "1.79"
+ version = "1.81"
}
dependency {
groupId = "org.bouncycastle"
artifactId = "bcpkix-jdk18on"
- version = "1.79"
+ version = "1.81"
}
dependency {
groupId = "org.bouncycastle"
artifactId = "bcutil-jdk18on"
- version = "1.79"
+ version = "1.81"
}
}
@@ -97,12 +97,12 @@ maven bytebuddy
dependency {
groupId = "net.bytebuddy"
artifactId = "byte-buddy"
- version = "1.15.11"
+ version = "1.17.5"
}
dependency {
groupId = "net.bytebuddy"
artifactId = "byte-buddy-agent"
- version = "1.15.11"
+ version = "1.17.5"
}
}
@@ -115,7 +115,7 @@ maven gson
dependency {
groupId = "com.google.code.gson"
artifactId = "gson"
- version = "2.11.0"
+ version = "2.13.1"
}
}
@@ -154,42 +154,42 @@ maven jetty
dependency {
groupId = "org.eclipse.jetty.ee10"
artifactId = "jetty-ee10-servlet"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-http"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-io"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-security"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-server"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-session"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-util"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "org.eclipse.jetty"
artifactId = "jetty-util-ajax"
- version = "12.0.16"
+ version = "12.0.22"
}
dependency {
groupId = "jakarta.servlet"
@@ -207,12 +207,12 @@ maven jna
dependency {
groupId = "net.java.dev.jna"
artifactId = "jna"
- version = "5.15.0"
+ version = "5.17.0"
}
dependency {
groupId = "net.java.dev.jna"
artifactId = "jna-platform"
- version = "5.15.0"
+ version = "5.17.0"
}
}
@@ -225,7 +225,7 @@ maven mockito
dependency {
groupId = "org.mockito"
artifactId = "mockito-core"
- version = "5.14.2"
+ version = "5.18.0"
}
}
@@ -238,12 +238,12 @@ maven sshd
dependency {
groupId = "org.apache.sshd"
artifactId = "sshd-osgi"
- version = "2.14.0"
+ version = "2.15.0"
}
dependency {
groupId = "org.apache.sshd"
artifactId = "sshd-sftp"
- version = "2.14.0"
+ version = "2.15.0"
}
}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20200831200620-2020-09.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20200831200620-2020-09.tpd
deleted file mode 100644
index 22e2b01207..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20200831200620-2020-09.tpd
+++ /dev/null
@@ -1,66 +0,0 @@
-target "R20200831200620-2020-09" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20200831200620/repository" {
- com.google.gson [2.8.2.v20180104-1110,2.8.2.v20180104-1110]
- com.google.gson.source [2.8.2.v20180104-1110,2.8.2.v20180104-1110]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800]
- javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- org.apache.ant [1.10.8.v20200515-1239,1.10.8.v20200515-1239]
- org.apache.ant.source [1.10.8.v20200515-1239,1.10.8.v20200515-1239]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.10.v20200830-2311,4.5.10.v20200830-2311]
- org.apache.httpcomponents.httpclient.source [4.5.10.v20200830-2311,4.5.10.v20200830-2311]
- org.apache.httpcomponents.httpcore [4.4.12.v20200108-1212,4.4.12.v20200108-1212]
- org.apache.httpcomponents.httpcore.source [4.4.12.v20200108-1212,4.4.12.v20200108-1212]
- org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.sshd.osgi [2.4.0.v20200318-1614,2.4.0.v20200318-1614]
- org.apache.sshd.osgi.source [2.4.0.v20200318-1614,2.4.0.v20200318-1614]
- org.apache.sshd.sftp [2.4.0.v20200319-1547,2.4.0.v20200319-1547]
- org.apache.sshd.sftp.source [2.4.0.v20200319-1547,2.4.0.v20200319-1547]
- org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.2.v20121108-1250,1.7.2.v20121108-1250]
- org.slf4j.api.source [1.7.2.v20121108-1250,1.7.2.v20121108-1250]
- org.slf4j.impl.log4j12 [1.7.2.v20131105-2200,1.7.2.v20131105-2200]
- org.slf4j.impl.log4j12.source [1.7.2.v20131105-2200,1.7.2.v20131105-2200]
- org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
- org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20201130205003-2020-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20201130205003-2020-12.tpd
deleted file mode 100644
index 08a0846de7..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20201130205003-2020-12.tpd
+++ /dev/null
@@ -1,66 +0,0 @@
-target "R20201130205003-2020-12" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20201130205003/repository" {
- com.google.gson [2.8.2.v20180104-1110,2.8.2.v20180104-1110]
- com.google.gson.source [2.8.2.v20180104-1110,2.8.2.v20180104-1110]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800]
- javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- org.apache.ant [1.10.9.v20201106-1946,1.10.9.v20201106-1946]
- org.apache.ant.source [1.10.9.v20201106-1946,1.10.9.v20201106-1946]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.10.v20200830-2311,4.5.10.v20200830-2311]
- org.apache.httpcomponents.httpclient.source [4.5.10.v20200830-2311,4.5.10.v20200830-2311]
- org.apache.httpcomponents.httpcore [4.4.12.v20200108-1212,4.4.12.v20200108-1212]
- org.apache.httpcomponents.httpcore.source [4.4.12.v20200108-1212,4.4.12.v20200108-1212]
- org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.sshd.osgi [2.4.0.v20200318-1614,2.4.0.v20200318-1614]
- org.apache.sshd.osgi.source [2.4.0.v20200318-1614,2.4.0.v20200318-1614]
- org.apache.sshd.sftp [2.4.0.v20200319-1547,2.4.0.v20200319-1547]
- org.apache.sshd.sftp.source [2.4.0.v20200319-1547,2.4.0.v20200319-1547]
- org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
- org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210223232630-2021-03.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210223232630-2021-03.tpd
deleted file mode 100644
index 605a43bb13..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210223232630-2021-03.tpd
+++ /dev/null
@@ -1,66 +0,0 @@
-target "R20210223232630-2021-03" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20210223232630/repository" {
- com.google.gson [2.8.6.v20201231-1626,2.8.6.v20201231-1626]
- com.google.gson.source [2.8.6.v20201231-1626,2.8.6.v20201231-1626]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800]
- javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- org.apache.ant [1.10.9.v20201106-1946,1.10.9.v20201106-1946]
- org.apache.ant.source [1.10.9.v20201106-1946,1.10.9.v20201106-1946]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.sshd.osgi [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.apache.sshd.osgi.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.apache.sshd.sftp [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.apache.sshd.sftp.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
- org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210602031627-2021-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210602031627-2021-06.tpd
deleted file mode 100644
index 83b5bb3fd2..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210602031627-2021-06.tpd
+++ /dev/null
@@ -1,66 +0,0 @@
-target "R20210602031627-2021-06" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20210602031627/repository" {
- com.google.gson [2.8.6.v20201231-1626,2.8.6.v20201231-1626]
- com.google.gson.source [2.8.6.v20201231-1626,2.8.6.v20201231-1626]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- javaewah [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javaewah.source [1.1.7.v20200107-0831,1.1.7.v20200107-0831]
- javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800]
- javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- org.apache.ant [1.10.10.v20210426-1926,1.10.10.v20210426-1926]
- org.apache.ant.source [1.10.10.v20210426-1926,1.10.10.v20210426-1926]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.compress.source [1.19.0.v20200106-2343,1.19.0.v20200106-2343]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.sshd.osgi [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.apache.sshd.osgi.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.apache.sshd.sftp [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.apache.sshd.sftp.source [2.6.0.v20210201-2003,2.6.0.v20210201-2003]
- org.assertj [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.assertj.source [3.14.0.v20200120-1926,3.14.0.v20200120-1926]
- org.bouncycastle.bcpg [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpg.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcpkix.source [1.65.0.v20200527-1955,1.65.0.v20200527-1955]
- org.bouncycastle.bcprov [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.bouncycastle.bcprov.source [1.65.1.v20200529-1514,1.65.1.v20200529-1514]
- org.hamcrest [1.1.0.v20090501071000,1.1.0.v20090501071000]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.tukaani.xz [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
- org.tukaani.xz.source [1.8.0.v20180207-1613,1.8.0.v20180207-1613]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210825222808-2021-09.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210825222808-2021-09.tpd
deleted file mode 100644
index 99f352011b..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20210825222808-2021-09.tpd
+++ /dev/null
@@ -1,73 +0,0 @@
-target "R20210825222808-2021-09" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20210825222808/repository" {
- com.google.gson [2.8.7.v20210624-1215,2.8.7.v20210624-1215]
- com.google.gson.source [2.8.7.v20210624-1215,2.8.7.v20210624-1215]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- javaewah [1.1.12.v20210622-2206,1.1.12.v20210622-2206]
- javaewah.source [1.1.12.v20210622-2206,1.1.12.v20210622-2206]
- javax.servlet [3.1.0.v201410161800,3.1.0.v201410161800]
- javax.servlet.source [3.1.0.v201410161800,3.1.0.v201410161800]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- net.i2p.crypto.eddsa.source [0.3.0.v20181102-1323,0.3.0.v20181102-1323]
- org.apache.ant [1.10.11.v20210720-1445,1.10.11.v20210720-1445]
- org.apache.ant.source [1.10.11.v20210720-1445,1.10.11.v20210720-1445]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.20.0.v20210713-1928,1.20.0.v20210713-1928]
- org.apache.commons.compress.source [1.20.0.v20210713-1928,1.20.0.v20210713-1928]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.sshd.osgi [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.osgi.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.sftp [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.sftp.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.bouncycastle.bcpg [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpg.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpkix [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpkix.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcprov [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcprov.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcutil [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcutil.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.junit.source [4.13.0.v20200204-1500,4.13.0.v20200204-1500]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
- org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211122181901-2021-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211122181901-2021-12.tpd
deleted file mode 100644
index cd1d1c08fa..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211122181901-2021-12.tpd
+++ /dev/null
@@ -1,71 +0,0 @@
-target "R20211122181901-2021-12" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20211122181901/repository" {
- com.google.gson [2.8.8.v20211029-0838,2.8.8.v20211029-0838]
- com.google.gson.source [2.8.8.v20211029-0838,2.8.8.v20211029-0838]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20210923-1401,0.3.0.v20210923-1401]
- net.i2p.crypto.eddsa.source [0.3.0.v20210923-1401,0.3.0.v20210923-1401]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
- org.apache.sshd.osgi [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.osgi.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.sftp [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.sftp.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.bouncycastle.bcpg [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpg.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpkix [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpkix.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcprov [1.69.0.v20210923-1401,1.69.0.v20210923-1401]
- org.bouncycastle.bcprov.source [1.69.0.v20210923-1401,1.69.0.v20210923-1401]
- org.bouncycastle.bcutil [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcutil.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.log4j12 [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.slf4j.binding.log4j12.source [1.7.30.v20201108-2042,1.7.30.v20201108-2042]
- org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
- org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211213173813-2021-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211213173813-2021-12.tpd
deleted file mode 100644
index 0c7c846738..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20211213173813-2021-12.tpd
+++ /dev/null
@@ -1,69 +0,0 @@
-target "R20211213173813-2021-12" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20211213173813/repository" {
- com.google.gson [2.8.8.v20211029-0838,2.8.8.v20211029-0838]
- com.google.gson.source [2.8.8.v20211029-0838,2.8.8.v20211029-0838]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20210923-1401,0.3.0.v20210923-1401]
- net.i2p.crypto.eddsa.source [0.3.0.v20210923-1401,0.3.0.v20210923-1401]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.httpcomponents.httpcore.source [4.4.14.v20210128-2225,4.4.14.v20210128-2225]
- org.apache.sshd.osgi [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.osgi.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.sftp [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.apache.sshd.sftp.source [2.7.0.v20210623-0618,2.7.0.v20210623-0618]
- org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.bouncycastle.bcpg [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpg.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpkix [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcpkix.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcprov [1.69.0.v20210923-1401,1.69.0.v20210923-1401]
- org.bouncycastle.bcprov.source [1.69.0.v20210923-1401,1.69.0.v20210923-1401]
- org.bouncycastle.bcutil [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.bouncycastle.bcutil.source [1.69.0.v20210713-1924,1.69.0.v20210713-1924]
- org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
- org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220302172233-2022-03.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220302172233-2022-03.tpd
deleted file mode 100644
index fafc689268..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220302172233-2022-03.tpd
+++ /dev/null
@@ -1,69 +0,0 @@
-target "R20220302172233" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20220302172233/repository" {
- com.google.gson [2.8.9.v20220111-1409,2.8.9.v20220111-1409]
- com.google.gson.source [2.8.9.v20220111-1409,2.8.9.v20220111-1409]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
- com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
- com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20210923-1401,0.3.0.v20210923-1401]
- net.i2p.crypto.eddsa.source [0.3.0.v20210923-1401,0.3.0.v20210923-1401]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.sshd.osgi [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.osgi.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.sftp [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.sftp.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.bouncycastle.bcpg [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcpg.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcpkix [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcpkix.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcprov [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcprov.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcutil [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcutil.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
- org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220531185310-2022-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220531185310-2022-06.tpd
deleted file mode 100644
index 3c74497c21..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220531185310-2022-06.tpd
+++ /dev/null
@@ -1,69 +0,0 @@
-target "R20220531185310-2022-06" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20220531185310/repository" {
- com.google.gson [2.8.9.v20220111-1409,2.8.9.v20220111-1409]
- com.google.gson.source [2.8.9.v20220111-1409,2.8.9.v20220111-1409]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.sshd.osgi [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.osgi.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.sftp [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.sftp.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.bouncycastle.bcpg [1.70.0.v20220507-1208,1.70.0.v20220507-1208]
- org.bouncycastle.bcpg.source [1.70.0.v20220507-1208,1.70.0.v20220507-1208]
- org.bouncycastle.bcpkix [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcpkix.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcprov [1.70.0.v20220507-1208,1.70.0.v20220507-1208]
- org.bouncycastle.bcprov.source [1.70.0.v20220507-1208,1.70.0.v20220507-1208]
- org.bouncycastle.bcutil [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.bouncycastle.bcutil.source [1.70.0.v20220105-1522,1.70.0.v20220105-1522]
- org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
- org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220830213456-2022-09.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220830213456-2022-09.tpd
deleted file mode 100644
index 8db1018ffb..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20220830213456-2022-09.tpd
+++ /dev/null
@@ -1,69 +0,0 @@
-target "R20220830213456-2022-09" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20220830213456/repository" {
- com.google.gson [2.8.9.v20220111-1409,2.8.9.v20220111-1409]
- com.google.gson.source [2.8.9.v20220111-1409,2.8.9.v20220111-1409]
- com.jcraft.jsch [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jsch.source [0.1.55.v20190404-1902,0.1.55.v20190404-1902]
- com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.sun.jna [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.source [5.8.0.v20210503-0343,5.8.0.v20210503-0343]
- com.sun.jna.platform [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- com.sun.jna.platform.source [5.8.0.v20210406-1004,5.8.0.v20210406-1004]
- javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- net.bytebuddy.byte-buddy [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.bytebuddy.byte-buddy-agent [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy-agent.source [1.9.0.v20181106-1534,1.9.0.v20181106-1534]
- net.bytebuddy.byte-buddy.source [1.9.0.v20181107-1410,1.9.0.v20181107-1410]
- net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.commons.codec [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.codec.source [1.14.0.v20200818-1422,1.14.0.v20200818-1422]
- org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20210128-2225,4.5.13.v20210128-2225]
- org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.sshd.osgi [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.osgi.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.sftp [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.apache.sshd.sftp.source [2.8.0.v20211227-1750,2.8.0.v20211227-1750]
- org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.bouncycastle.bcpg [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.bouncycastle.bcpg.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.bouncycastle.bcpkix [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.bouncycastle.bcpkix.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.bouncycastle.bcprov [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.bouncycastle.bcprov.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.bouncycastle.bcutil [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.bouncycastle.bcutil.source [1.71.0.v20220723-1943,1.71.0.v20220723-1943]
- org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.mockito.source [2.23.0.v20200310-1642,2.23.0.v20200310-1642]
- org.objenesis [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.objenesis.source [2.6.0.v20180420-1519,2.6.0.v20180420-1519]
- org.slf4j.api [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.api.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.slf4j.binding.simple.source [1.7.30.v20200204-2150,1.7.30.v20200204-2150]
- org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
- org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20221123021534-2022-12.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20221123021534-2022-12.tpd
deleted file mode 100644
index 378b84873f..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20221123021534-2022-12.tpd
+++ /dev/null
@@ -1,69 +0,0 @@
-target "S20230101190934" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20221123021534/repository" {
- com.google.gson [2.9.1.v20220915-1632,2.9.1.v20220915-1632]
- com.google.gson.source [2.9.1.v20220915-1632,2.9.1.v20220915-1632]
- com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.sun.jna [5.12.1.v20221103-2317,5.12.1.v20221103-2317]
- com.sun.jna.source [5.12.1.v20221103-2317,5.12.1.v20221103-2317]
- com.sun.jna.platform [5.12.1.v20221103-2317,5.12.1.v20221103-2317]
- com.sun.jna.platform.source [5.12.1.v20221103-2317,5.12.1.v20221103-2317]
- javaewah [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- javaewah.source [1.1.13.v20211029-0839,1.1.13.v20211029-0839]
- net.bytebuddy.byte-buddy [1.12.18.v20221114-2102,1.12.18.v20221114-2102]
- net.bytebuddy.byte-buddy.source [1.12.18.v20221114-2102,1.12.18.v20221114-2102]
- net.bytebuddy.byte-buddy-agent [1.12.18.v20221114-2102,1.12.18.v20221114-2102]
- net.bytebuddy.byte-buddy-agent.source [1.12.18.v20221114-2102,1.12.18.v20221114-2102]
- net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.commons.codec [1.14.0.v20221112-0806,1.14.0.v20221112-0806]
- org.apache.commons.codec.source [1.14.0.v20221112-0806,1.14.0.v20221112-0806]
- org.apache.commons.compress [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.compress.source [1.21.0.v20211103-2100,1.21.0.v20211103-2100]
- org.apache.commons.logging [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.commons.logging.source [1.2.0.v20180409-1502,1.2.0.v20180409-1502]
- org.apache.httpcomponents.httpclient [4.5.13.v20221112-0806,4.5.13.v20221112-0806]
- org.apache.httpcomponents.httpclient.source [4.5.13.v20221112-0806,4.5.13.v20221112-0806]
- org.apache.httpcomponents.httpcore [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.httpcomponents.httpcore.source [4.4.15.v20220209-2345,4.4.15.v20220209-2345]
- org.apache.sshd.osgi [2.9.2.v20221117-1942,2.9.2.v20221117-1942]
- org.apache.sshd.osgi.source [2.9.2.v20221117-1942,2.9.2.v20221117-1942]
- org.apache.sshd.sftp [2.9.2.v20221117-1942,2.9.2.v20221117-1942]
- org.apache.sshd.sftp.source [2.9.2.v20221117-1942,2.9.2.v20221117-1942]
- org.assertj [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.assertj.source [3.20.2.v20210706-1104,3.20.2.v20210706-1104]
- org.bouncycastle.bcpg [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.bouncycastle.bcpg.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.bouncycastle.bcpkix [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.bouncycastle.bcpkix.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.bouncycastle.bcprov [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.bouncycastle.bcprov.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.bouncycastle.bcutil [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.bouncycastle.bcutil.source [1.72.0.v20221013-1810,1.72.0.v20221013-1810]
- org.hamcrest [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.source [2.2.0.v20210711-0821,2.2.0.v20210711-0821]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.kohsuke.args4j.source [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
- org.mockito.mockito-core [4.8.1.v20221103-2317,4.8.1.v20221103-2317]
- org.mockito.mockito-core.source [4.8.1.v20221103-2317,4.8.1.v20221103-2317]
- org.objenesis [3.3.0.v20221103-2317,3.3.0.v20221103-2317]
- org.objenesis.source [3.3.0.v20221103-2317,3.3.0.v20221103-2317]
- org.slf4j.api [1.7.30.v20221112-0806,1.7.30.v20221112-0806]
- org.slf4j.api.source [1.7.30.v20221112-0806,1.7.30.v20221112-0806]
- org.slf4j.binding.simple [1.7.30.v20221112-0806,1.7.30.v20221112-0806]
- org.slf4j.binding.simple.source [1.7.30.v20221112-0806,1.7.30.v20221112-0806]
- org.tukaani.xz [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
- org.tukaani.xz.source [1.9.0.v20210624-1259,1.9.0.v20210624-1259]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230302014618-2023-03.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230302014618-2023-03.tpd
deleted file mode 100644
index 8578b2cdf5..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230302014618-2023-03.tpd
+++ /dev/null
@@ -1,27 +0,0 @@
-target "R20230302014618-2023-03" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20230302014618/repository" {
- com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.httpcomponents.httpclient [4.5.14.v20221207-1049,4.5.14.v20221207-1049]
- org.apache.httpcomponents.httpclient.source [4.5.14.v20221207-1049,4.5.14.v20221207-1049]
- org.apache.httpcomponents.httpcore [4.4.16.v20221207-1049,4.4.16.v20221207-1049]
- org.apache.httpcomponents.httpcore.source [4.4.16.v20221207-1049,4.4.16.v20221207-1049]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.mockito.mockito-core [4.8.1.v20221103-2317,4.8.1.v20221103-2317]
- org.mockito.mockito-core.source [4.8.1.v20221103-2317,4.8.1.v20221103-2317]
- org.objenesis [3.3.0.v20221103-2317,3.3.0.v20221103-2317]
- org.objenesis.source [3.3.0.v20221103-2317,3.3.0.v20221103-2317]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230531010532-2023-06.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230531010532-2023-06.tpd
deleted file mode 100644
index 46055d3728..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20230531010532-2023-06.tpd
+++ /dev/null
@@ -1,25 +0,0 @@
-target "R20230531010532-2023-06" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/downloads/drops/R20230531010532/repository" {
- com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.httpcomponents.httpclient [4.5.14.v20230516-1249,4.5.14.v20230516-1249]
- org.apache.httpcomponents.httpclient.source [4.5.14.v20230516-1249,4.5.14.v20230516-1249]
- org.apache.httpcomponents.httpcore [4.4.16.v20221207-1049,4.4.16.v20221207-1049]
- org.apache.httpcomponents.httpcore.source [4.4.16.v20221207-1049,4.4.16.v20221207-1049]
- org.hamcrest.core [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.core.source [1.3.0.v20180420-1519,1.3.0.v20180420-1519]
- org.hamcrest.library [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.hamcrest.library.source [1.3.0.v20180524-2246,1.3.0.v20180524-2246]
- org.junit [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.junit.source [4.13.2.v20211018-1956,4.13.2.v20211018-1956]
- org.objenesis [3.3.0.v20221103-2317,3.3.0.v20221103-2317]
- org.objenesis.source [3.3.0.v20221103-2317,3.3.0.v20221103-2317]
-}
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.29.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.29.tpd
deleted file mode 100644
index 70a17a1ddc..0000000000
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.29.tpd
+++ /dev/null
@@ -1,27 +0,0 @@
-target "orbit-4.29" with source configurePhase
-// see https://download.eclipse.org/tools/orbit/downloads/
-
-location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/release/4.29.0" {
- com.jcraft.jsch [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jsch.source [0.1.55.v20221112-0806,0.1.55.v20221112-0806]
- com.jcraft.jzlib [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- com.jcraft.jzlib.source [1.1.3.v20220502-1820,1.1.3.v20220502-1820]
- net.i2p.crypto.eddsa [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- net.i2p.crypto.eddsa.source [0.3.0.v20220506-1020,0.3.0.v20220506-1020]
- org.apache.ant [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- org.apache.ant.source [1.10.12.v20211102-1452,1.10.12.v20211102-1452]
- 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.3,3.3]
- org.objenesis.source [3.3,3.3]
- 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.32.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.32.tpd
index 480e96e2e8..59fcd8745a 100644
--- 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
@@ -6,8 +6,6 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024
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]
- net.i2p.crypto.eddsa [0.3.0,0.3.0]
- net.i2p.crypto.eddsa.source [0.3.0,0.3.0]
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]
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
index 8dca4cb681..2cfa0a8e7c 100644
--- 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
@@ -6,8 +6,6 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024
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]
- net.i2p.crypto.eddsa [0.3.0,0.3.0]
- net.i2p.crypto.eddsa.source [0.3.0,0.3.0]
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]
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 15931db8c7..d3e15bba6d 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
@@ -6,8 +6,6 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2024
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]
- net.i2p.crypto.eddsa [0.3.0,0.3.0]
- net.i2p.crypto.eddsa.source [0.3.0,0.3.0]
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.httpcomponents.httpclient [4.5.14,4.5.14]
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd
index 9d00cb4c4f..ec6996e427 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.31.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.35.tpd
@@ -1,15 +1,13 @@
-target "orbit-4.31" with source configurePhase
+target "orbit-4.35" with source configurePhase
// see https://download.eclipse.org/tools/orbit/downloads/
-location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12" {
+location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2025-03" {
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]
- net.i2p.crypto.eddsa [0.3.0,0.3.0]
- net.i2p.crypto.eddsa.source [0.3.0,0.3.0]
- 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.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.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]
@@ -18,10 +16,10 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023
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.3,3.3]
- org.objenesis.source [3.3,3.3]
+ 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.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.30.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.36.tpd
index 0554a8578c..4f4658328e 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.30.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/orbit-4.36.tpd
@@ -1,15 +1,13 @@
-target "orbit-4.30" with source configurePhase
+target "orbit-4.36" with source configurePhase
// see https://download.eclipse.org/tools/orbit/downloads/
-location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023-12" {
+location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2025-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]
- net.i2p.crypto.eddsa [0.3.0,0.3.0]
- net.i2p.crypto.eddsa.source [0.3.0,0.3.0]
- 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.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.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]
@@ -18,10 +16,10 @@ location "https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/2023
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.3,3.3]
- org.objenesis.source [3.3,3.3]
+ 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.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/pom.xml b/org.eclipse.jgit.packaging/pom.xml
index 5bc67b458e..69b57de3d9 100644
--- a/org.eclipse.jgit.packaging/pom.xml
+++ b/org.eclipse.jgit.packaging/pom.xml
@@ -16,7 +16,7 @@
<groupId>org.eclipse.jgit</groupId>
<artifactId>jgit.tycho.parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>JGit Tycho Parent</name>
@@ -30,7 +30,7 @@
<properties>
<java.version>17</java.version>
- <tycho-version>4.0.10</tycho-version>
+ <tycho-version>4.0.13</tycho-version>
<target-platform>jgit-4.32</target-platform>
<project.build.outputTimestamp>${git.commit.time}</project.build.outputTimestamp>
</properties>
@@ -233,7 +233,7 @@
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
- <version>9.0.1</version>
+ <version>9.0.2</version>
<executions>
<execution>
<id>get-the-git-infos</id>
@@ -390,17 +390,17 @@
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
- <version>3.4.0</version>
+ <version>3.4.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
- <version>3.1.3</version>
+ <version>3.1.4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>3.1.3</version>
+ <version>3.1.4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -410,7 +410,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-artifact-plugin</artifactId>
- <version>3.5.3</version>
+ <version>3.6.0</version>
<configuration>
<ignore>**/*cyclonedx.json</ignore>
<reproducible>true</reproducible>
diff --git a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
index 60a60bb51d..c15c705c22 100644
--- a/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm.test/META-INF/MANIFEST.MF
@@ -3,30 +3,30 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.pgm.test
Bundle-SymbolicName: org.eclipse.jgit.pgm.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Import-Package: org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.diff;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.dircache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.merge;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.pgm;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.pgm.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.pgm.opt;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.io;version="[7.2.0,7.3.0)",
+Import-Package: org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.diff;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.dircache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.merge;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.pgm;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.pgm.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.pgm.opt;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.io;version="[7.4.0,7.5.0)",
org.hamcrest.core;bundle-version="[1.1.0,3.0.0)",
org.junit;version="[4.13,5.0.0)",
org.junit.rules;version="[4.13,5.0.0)",
diff --git a/org.eclipse.jgit.pgm.test/pom.xml b/org.eclipse.jgit.pgm.test/pom.xml
index 9195a369e7..d242156ccb 100644
--- a/org.eclipse.jgit.pgm.test/pom.xml
+++ b/org.eclipse.jgit.pgm.test/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.pgm.test</artifactId>
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java
index 6d6374f172..a48fcbcd5a 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/AddTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Google Inc. and others
+ * Copyright (C) 2012, 2025 Google Inc. 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
@@ -12,7 +12,10 @@ package org.eclipse.jgit.pgm;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.dircache.DirCache;
@@ -32,12 +35,7 @@ public class AddTest extends CLIRepositoryTestCase {
@Test
public void testAddNothing() throws Exception {
- try {
- execute("git add");
- fail("Must die");
- } catch (Die e) {
- // expected, requires argument
- }
+ assertThrows(Die.class, () -> execute("git add"));
}
@Test
@@ -46,6 +44,17 @@ public class AddTest extends CLIRepositoryTestCase {
}
@Test
+ public void testAddInvalidOptionCombinations() throws Exception {
+ writeTrashFile("greeting", "Hello, world!");
+ assertThrows(Die.class, () -> execute("git add -u -A greeting"));
+ assertThrows(Die.class,
+ () -> execute("git add -u --ignore-removed greeting"));
+ // --renormalize implies -u
+ assertThrows(Die.class,
+ () -> execute("git add --renormalize --all greeting"));
+ }
+
+ @Test
public void testAddAFile() throws Exception {
writeTrashFile("greeting", "Hello, world!");
assertArrayEquals(new String[] { "" }, //
@@ -78,4 +87,34 @@ public class AddTest extends CLIRepositoryTestCase {
assertNotNull(cache.getEntry("greeting"));
assertEquals(1, cache.getEntryCount());
}
+
+ @Test
+ public void testAddDeleted() throws Exception {
+ File greeting = writeTrashFile("greeting", "Hello, world!");
+ git.add().addFilepattern("greeting").call();
+ DirCache cache = db.readDirCache();
+ assertNotNull(cache.getEntry("greeting"));
+ assertEquals(1, cache.getEntryCount());
+ assertTrue(greeting.delete());
+ assertArrayEquals(new String[] { "" }, //
+ execute("git add greeting"));
+
+ cache = db.readDirCache();
+ assertEquals(0, cache.getEntryCount());
+ }
+
+ @Test
+ public void testAddDeleted2() throws Exception {
+ File greeting = writeTrashFile("greeting", "Hello, world!");
+ git.add().addFilepattern("greeting").call();
+ DirCache cache = db.readDirCache();
+ assertNotNull(cache.getEntry("greeting"));
+ assertEquals(1, cache.getEntryCount());
+ assertTrue(greeting.delete());
+ assertArrayEquals(new String[] { "" }, //
+ execute("git add -A"));
+
+ cache = db.readDirCache();
+ assertEquals(0, cache.getEntryCount());
+ }
}
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java
index 999bf434ce..d533829d52 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/CheckoutTest.java
@@ -96,6 +96,20 @@ public class CheckoutTest extends CLIRepositoryTestCase {
}
@Test
+ public void testCheckoutWithNoRef() throws Exception {
+ assertStringArrayEquals(
+ "a valid ref is expected",
+ executeExpectingException("git checkout"));
+ }
+
+ @Test
+ public void testCheckoutWithInvalidRef() throws Exception {
+ assertStringArrayEquals(
+ ".feature is not a valid ref name",
+ executeExpectingException("git checkout .feature"));
+ }
+
+ @Test
public void testCheckoutNewBranchThatAlreadyExists() throws Exception {
try (Git git = new Git(db)) {
git.commit().setMessage("initial commit").call();
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
index c78544309b..595767d3a0 100644
--- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
+++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/DescribeTest.java
@@ -123,6 +123,15 @@ public class DescribeTest extends CLIRepositoryTestCase {
}
@Test
+ public void testDescribeExclude() throws Exception {
+ initialCommitAndTag();
+ secondCommit();
+ git.tag().setName("v2.0").call();
+ assertArrayEquals(new String[] { "v1.0-1-g56f6ceb", "" },
+ execute("git describe --exclude v2.*"));
+ }
+
+ @Test
public void testDescribeCommitMultiMatch() throws Exception {
initialCommitAndTag();
secondCommit();
@@ -133,6 +142,17 @@ public class DescribeTest extends CLIRepositoryTestCase {
}
@Test
+ public void testDescribeCommitMultiExclude() throws Exception {
+ initialCommitAndTag();
+ secondCommit();
+ git.tag().setName("v2.0.0").call();
+ git.tag().setName("v2.1.1").call();
+ git.tag().setName("v2.2").call();
+ assertArrayEquals("git yields v2.2", new String[] { "v2.2", "" },
+ execute("git describe --exclude v2.0* --exclude v2.1.*"));
+ }
+
+ @Test
public void testDescribeCommitNoMatch() throws Exception {
initialCommitAndTag();
writeTrashFile("greeting", "Hello, world!");
diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
index fbcab95354..21198afc65 100644
--- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.pgm
Bundle-SymbolicName: org.eclipse.jgit.pgm
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -14,49 +14,50 @@ Import-Package: jakarta.servlet;version="[6.0.0,7.0.0)",
org.eclipse.jetty.server.handler;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util;version="[12.0.0,13.0.0)",
org.eclipse.jetty.util.component;version="[12.0.0,13.0.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.archive;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.awtui;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.blame;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.diff;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.dircache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.gitrepo;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.io;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.pack;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.server;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.server.fs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs.server.s3;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.merge;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.notes;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revplot;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.pack;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http.apache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.resolver;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.ssh.jsch;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.sshd;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.io;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.archive;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.awtui;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.blame;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.diff;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.dircache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.gitrepo;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.io;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.midx;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.server;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.server.fs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs.server.s3;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.merge;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.notes;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revplot;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.pack;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http.apache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.ssh.jsch;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.sshd;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.io;version="[7.4.0,7.5.0)",
org.kohsuke.args4j;version="[2.33.0,3.0.0)",
org.kohsuke.args4j.spi;version="[2.33.0,3.0.0)"
-Export-Package: org.eclipse.jgit.console;version="7.2.0";
+Export-Package: org.eclipse.jgit.console;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.util",
- org.eclipse.jgit.pgm;version="7.2.0";
+ org.eclipse.jgit.pgm;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.util.io,
org.eclipse.jgit.awtui,
@@ -68,14 +69,14 @@ Export-Package: org.eclipse.jgit.console;version="7.2.0";
org.eclipse.jgit.treewalk,
org.eclipse.jgit.api,
javax.swing",
- org.eclipse.jgit.pgm.debug;version="7.2.0";
+ org.eclipse.jgit.pgm.debug;version="7.4.0";
uses:="org.eclipse.jgit.util.io,
org.eclipse.jgit.pgm,
org.eclipse.jetty.servlet",
- org.eclipse.jgit.pgm.internal;version="7.2.0";
+ org.eclipse.jgit.pgm.internal;version="7.4.0";
x-friends:="org.eclipse.jgit.pgm.test,
org.eclipse.jgit.test",
- org.eclipse.jgit.pgm.opt;version="7.2.0";
+ org.eclipse.jgit.pgm.opt;version="7.4.0";
uses:="org.kohsuke.args4j,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
diff --git a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
index 0101464c82..cb3c28e8cf 100644
--- a/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.pgm/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.pgm - Sources
Bundle-SymbolicName: org.eclipse.jgit.pgm.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.pgm;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
index 41b0091b77..6bf88d9aa8 100644
--- a/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
+++ b/org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
@@ -26,6 +26,7 @@ org.eclipse.jgit.pgm.LsTree
org.eclipse.jgit.pgm.Merge
org.eclipse.jgit.pgm.MergeBase
org.eclipse.jgit.pgm.MergeTool
+org.eclipse.jgit.pgm.MultiPackIndex
org.eclipse.jgit.pgm.PackRefs
org.eclipse.jgit.pgm.Push
org.eclipse.jgit.pgm.ReceivePack
diff --git a/org.eclipse.jgit.pgm/jgit.sh b/org.eclipse.jgit.pgm/jgit.sh
index a369220037..3f241e8a7a 100644
--- a/org.eclipse.jgit.pgm/jgit.sh
+++ b/org.eclipse.jgit.pgm/jgit.sh
@@ -110,9 +110,9 @@ then
LESS=${LESS:-FSRX}
export LESS
- "$java" $java_args org.springframework.boot.loader.JarLauncher "$@" | $use_pager
+ "$java" $java_args org.springframework.boot.loader.launch.JarLauncher "$@" | $use_pager
exit
else
- exec "$java" $java_args org.springframework.boot.loader.JarLauncher "$@"
+ exec "$java" $java_args org.springframework.boot.loader.launch.JarLauncher "$@"
exit 1
fi
diff --git a/org.eclipse.jgit.pgm/pom.xml b/org.eclipse.jgit.pgm/pom.xml
index 81efa44cc6..14588dd6df 100644
--- a/org.eclipse.jgit.pgm/pom.xml
+++ b/org.eclipse.jgit.pgm/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.pgm</artifactId>
diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
index d24b639a31..e9630e9499 100644
--- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
+++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
@@ -12,6 +12,7 @@ ARGS=ARGS
# default meta variable defined in the org.kohsuke.args4j.spi.OneArgumentOptionHandler
N=N
+addIncompatibleOptions=--update/-u cannot be combined with --all/-A/--no-ignore-removal or --no-all/--ignore-removal. Note that --renormalize implies --update.
alreadyOnBranch=Already on ''{0}''
alreadyUpToDate=Already up-to-date.
answerNo=n
@@ -255,7 +256,9 @@ unsupportedOperation=Unsupported operation: {0}
untrackedFiles=Untracked files:
updating=Updating {0}..{1}
usage_Abbrev=Instead of using the default number of hexadecimal digits (which will vary according to the number of objects in the repository with a default of 7) of the abbreviated object name, use <n> digits, or as many digits as needed to form a unique object name. An <n> of 0 will suppress long format, only showing the closest tag.
-usage_addRenormalize=Apply the "clean" process freshly to tracked files to forcibly add them again to the index. This implies -u.
+usage_addRenormalize=Apply the "clean" process freshly to tracked files to forcibly add them again to the index. This implies --update/-u.
+usage_addStageDeletions=Add, modify, or remove index entries to match the working tree. Cannot be used with --update/-u.
+usage_addDontStageDeletions=Only add or modify index entries, but do not remove index entries for which there is no file. (Don''t stage deletions.) Cannot be used with --update/-u.
usage_Aggressive=This option will cause gc to more aggressively optimize the repository at the expense of taking much more time
usage_All=Pack all refs, except hidden refs, broken refs, and symbolic refs.
usage_AlwaysFallback=Show uniquely abbreviated commit object as fallback
@@ -279,6 +282,7 @@ usage_CreateAnEmptyGitRepository=Create an empty git repository
usage_Describe=Show the most recent tag that is reachable from a commit
usage_DiffAlgorithms=Test performance of jgit's diff algorithms
usage_DisplayTheVersionOfJgit=Display the version of jgit
+usage_Exclude=Do not consider tags matching the given glob(7) pattern, excluding the "refs/tags/" prefix
usage_Gc=Cleanup unnecessary files and optimize the local repository
usage_Glog=View commit history as a graph
usage_DiffGuiTool=When git-difftool is invoked with the -g or --gui option the default diff tool will be read from the configured diff.guitool variable instead of diff.tool.
@@ -300,6 +304,7 @@ usage_MakeCacheTree=Show the current cache tree structure
usage_Match=Only consider tags matching the given glob(7) pattern or patterns, excluding the "refs/tags/" prefix.
usage_MergeBase=Find as good common ancestors as possible for a merge
usage_MergesTwoDevelopmentHistories=Merges two development histories
+usage_MultiPackIndex=Operations over the multipack index
usage_PackKeptObjects=Include objects in packs locked by a ".keep" file when repacking
usage_PackRefs=Pack heads and tags for efficient repository access
usage_PreserveOldPacks=Preserve old pack files by moving them into the preserved subdirectory instead of deleting them after repacking
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java
index 2ebab5e5d2..dc9d77df35 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Add.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, Sasa Zivkov <sasa.zivkov@sap.com> and others
+ * Copyright (C) 2010, 2025 Sasa Zivkov <sasa.zivkov@sap.com> 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,6 +16,7 @@ import java.util.List;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.pgm.internal.CLIText;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
@@ -28,17 +29,33 @@ class Add extends TextBuiltin {
@Option(name = "--update", aliases = { "-u" }, usage = "usage_onlyMatchAgainstAlreadyTrackedFiles")
private boolean update = false;
- @Argument(required = true, metaVar = "metaVar_filepattern", usage = "usage_filesToAddContentFrom")
+ @Option(name = "--all", aliases = { "-A",
+ "--no-ignore-removal" }, usage = "usage_addStageDeletions")
+ private Boolean all;
+
+ @Option(name = "--no-all", aliases = {
+ "--ignore-removal" }, usage = "usage_addDontStageDeletions")
+ private void noAll(@SuppressWarnings("unused") boolean ignored) {
+ all = Boolean.FALSE;
+ }
+
+ @Argument(metaVar = "metaVar_filepattern", usage = "usage_filesToAddContentFrom")
private List<String> filepatterns = new ArrayList<>();
@Override
protected void run() throws Exception {
try (Git git = new Git(db)) {
- AddCommand addCmd = git.add();
if (renormalize) {
update = true;
}
+ if (update && all != null) {
+ throw die(CLIText.get().addIncompatibleOptions);
+ }
+ AddCommand addCmd = git.add();
addCmd.setUpdate(update).setRenormalize(renormalize);
+ if (all != null) {
+ addCmd.setAll(all.booleanValue());
+ }
for (String p : filepatterns) {
addCmd.addFilepattern(p);
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java
index d2285ae64a..285fe2a96a 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Blame.java
@@ -18,7 +18,7 @@ import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
import java.io.IOException;
import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -91,7 +91,7 @@ class Blame extends TextBuiltin {
private final Map<RevCommit, String> abbreviatedCommits = new HashMap<>();
- private SimpleDateFormat dateFmt;
+ private DateTimeFormatter dateFmt;
private int begin;
@@ -125,9 +125,9 @@ class Blame extends TextBuiltin {
}
if (showRawTimestamp) {
- dateFmt = new SimpleDateFormat("ZZZZ"); //$NON-NLS-1$
+ dateFmt = DateTimeFormatter.ofPattern("ZZ"); //$NON-NLS-1$
} else {
- dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZZ"); //$NON-NLS-1$
+ dateFmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss ZZ"); //$NON-NLS-1$
}
try (ObjectReader reader = db.newObjectReader();
@@ -335,12 +335,14 @@ class Blame extends TextBuiltin {
if (author == null)
return ""; //$NON-NLS-1$
- dateFmt.setTimeZone(author.getTimeZone());
- if (!showRawTimestamp)
- return dateFmt.format(author.getWhen());
+ if (!showRawTimestamp) {
+ return dateFmt.withZone(author.getZoneId())
+ .format(author.getWhenAsInstant());
+ }
return String.format("%d %s", //$NON-NLS-1$
- Long.valueOf(author.getWhen().getTime() / 1000L),
- dateFmt.format(author.getWhen()));
+ Long.valueOf(author.getWhenAsInstant().getEpochSecond()),
+ dateFmt.withZone(author.getZoneId())
+ .format(author.getWhenAsInstant()));
}
private String abbreviate(ObjectReader reader, RevCommit commit)
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java
index 229d54d44f..7a218ec926 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Checkout.java
@@ -18,6 +18,7 @@ import java.util.List;
import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.CheckoutConflictException;
+import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.lib.Constants;
@@ -94,7 +95,16 @@ class Checkout extends TextBuiltin {
outw.println(MessageFormat.format(
CLIText.get().switchedToBranch,
Repository.shortenRefName(ref.getName())));
- } catch (RefNotFoundException e) {
+ } catch (InvalidRefNameException e){
+ if (name == null){
+ throw die(MessageFormat
+ .format("a valid ref is expected",e));
+ } else {
+ throw die(MessageFormat
+ .format(CLIText.get().notAValidRefName, name, e));
+ }
+ }
+ catch (RefNotFoundException e) {
throw die(MessageFormat
.format(CLIText.get().pathspecDidNotMatch, name), e);
} catch (RefAlreadyExistsException e) {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java
index 913d7c790d..2633336e12 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Describe.java
@@ -44,6 +44,9 @@ class Describe extends TextBuiltin {
@Option(name = "--match", usage = "usage_Match", metaVar = "metaVar_pattern")
private List<String> patterns = new ArrayList<>();
+ @Option(name = "--exclude", usage = "usage_Exclude", metaVar = "metaVar_pattern")
+ private List<String> excludes = new ArrayList<>();
+
@Option(name = "--abbrev", usage = "usage_Abbrev")
private Integer abbrev;
@@ -59,6 +62,7 @@ class Describe extends TextBuiltin {
cmd.setTags(useTags);
cmd.setAlways(always);
cmd.setMatch(patterns.toArray(new String[0]));
+ cmd.setExclude(excludes.toArray(new String[0]));
if (abbrev != null) {
cmd.setAbbrev(abbrev.intValue());
}
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
new file mode 100644
index 0000000000..1844223cc9
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MultiPackIndex.java
@@ -0,0 +1,107 @@
+/*
+ * 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.pgm;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
+import org.eclipse.jgit.internal.storage.file.Pack;
+import org.eclipse.jgit.internal.storage.file.PackFile;
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndexPrettyPrinter;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndexWriter;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+
+@Command(common = true, usage = "usage_MultiPackIndex")
+@SuppressWarnings("nls")
+class MultiPackIndex extends TextBuiltin {
+ @Argument(index = 0, required = true, usage = "write, print")
+ private String command;
+
+ @Option(name = "--midx")
+ private String midxPath;
+
+ /** {@inheritDoc} */
+ @Override
+ protected void run() throws IOException {
+ switch (command) {
+ case "print":
+ printMultiPackIndex();
+ break;
+ case "write":
+ writeMultiPackIndex();
+ break;
+ default:
+ outw.println("Unknown command " + command);
+ }
+ }
+
+ private void printMultiPackIndex() {
+ if (midxPath == null || midxPath.isEmpty()) {
+ throw die("'print' requires the path of a multipack "
+ + "index file with --midx option.");
+ }
+
+ try (FileInputStream is = new FileInputStream(midxPath)) {
+ PrintWriter pw = new PrintWriter(outw, true);
+ MultiPackIndexPrettyPrinter.prettyPrint(is.readAllBytes(), pw);
+ } catch (FileNotFoundException e) {
+ throw die(true, e);
+ } catch (IOException e) {
+ throw die(true, e);
+ }
+ }
+
+ private void writeMultiPackIndex() throws IOException {
+ if (!(db.getObjectDatabase() instanceof ObjectDirectory)) {
+ throw die("This repository object db doesn't have packs");
+ }
+
+ File midx;
+ if (midxPath == null || midxPath.isEmpty()) {
+ midx = new File(((ObjectDirectory) db.getObjectDatabase())
+ .getPackDirectory(), "multi-pack-index");
+ } else {
+ midx = new File(midxPath);
+ }
+
+ errw.println("Writing " + midx.getAbsolutePath());
+
+ ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
+
+ Map<String, PackIndex> indexes = new HashMap<>();
+ for (Pack pack : odb.getPacks()) {
+ PackFile packFile = pack.getPackFile().create(PackExt.INDEX);
+ try {
+ indexes.put(packFile.getName(), pack.getIndex());
+ } catch (IOException e) {
+ throw die("Cannot open index in pack", e);
+ }
+ }
+
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ try (FileOutputStream out = new FileOutputStream(midxPath)) {
+ writer.write(NullProgressMonitor.INSTANCE, out, indexes);
+ } catch (IOException e) {
+ throw die("Cannot write midx " + midxPath, e);
+ }
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java
index 1576792234..a3a6782a71 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Show.java
@@ -14,11 +14,10 @@ package org.eclipse.jgit.pgm;
import java.io.BufferedOutputStream;
import java.io.IOException;
-import java.text.DateFormat;
import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.Locale;
-import java.util.TimeZone;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawTextComparator;
@@ -51,9 +50,9 @@ import org.kohsuke.args4j.Option;
@Command(common = true, usage = "usage_show")
class Show extends TextBuiltin {
- private final TimeZone myTZ = TimeZone.getDefault();
+ private final ZoneId myTZ = ZoneId.systemDefault();
- private final DateFormat fmt;
+ private final DateTimeFormatter fmt;
private DiffFormatter diffFmt;
@@ -157,7 +156,8 @@ class Show extends TextBuiltin {
// END -- Options shared with Diff
Show() {
- fmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy ZZZZZ", Locale.US); //$NON-NLS-1$
+ fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy ZZ", //$NON-NLS-1$
+ Locale.US);
}
@Override
@@ -232,15 +232,17 @@ class Show extends TextBuiltin {
outw.print(tag.getTagName());
outw.println();
- final PersonIdent tagger = tag.getTaggerIdent();
+ PersonIdent tagger = tag.getTaggerIdent();
if (tagger != null) {
outw.println(MessageFormat.format(CLIText.get().taggerInfo,
tagger.getName(), tagger.getEmailAddress()));
- final TimeZone taggerTZ = tagger.getTimeZone();
- fmt.setTimeZone(taggerTZ != null ? taggerTZ : myTZ);
+ ZoneId taggerTZ = tagger.getZoneId();
+ String formattedTaggerTime = fmt
+ .withZone(taggerTZ != null ? taggerTZ : myTZ)
+ .format(tagger.getWhenAsInstant());
outw.println(MessageFormat.format(CLIText.get().dateInfo,
- fmt.format(tagger.getWhen())));
+ formattedTaggerTime));
}
outw.println();
@@ -293,10 +295,12 @@ class Show extends TextBuiltin {
outw.println(MessageFormat.format(CLIText.get().authorInfo,
author.getName(), author.getEmailAddress()));
- final TimeZone authorTZ = author.getTimeZone();
- fmt.setTimeZone(authorTZ != null ? authorTZ : myTZ);
+ final ZoneId authorTZ = author.getZoneId();
+ String formattedAuthorTime = fmt
+ .withZone(authorTZ != null ? authorTZ : myTZ)
+ .format(author.getWhenAsInstant());
outw.println(MessageFormat.format(CLIText.get().dateInfo,
- fmt.format(author.getWhen())));
+ formattedAuthorTime));
outw.println();
final String[] lines = c.getFullMessage().split("\n"); //$NON-NLS-1$
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/BenchmarkReftable.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/BenchmarkReftable.java
index f156b8cf4c..b7a7ec2feb 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/BenchmarkReftable.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/BenchmarkReftable.java
@@ -107,13 +107,12 @@ class BenchmarkReftable extends TextBuiltin {
@SuppressWarnings({ "nls", "boxing" })
private void writeStack() throws Exception {
File dir = new File(reftablePath);
- File stackFile = new File(reftablePath + ".stack");
dir.mkdirs();
long start = System.currentTimeMillis();
- try (FileReftableStack stack = new FileReftableStack(stackFile, dir,
- null, () -> new Config())) {
+ try (FileReftableStack stack = new FileReftableStack(dir, null,
+ () -> new Config())) {
List<Ref> refs = readLsRemote().asList();
for (Ref r : refs) {
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
index 2f96ef7d57..22d9e3440a 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
@@ -18,8 +18,8 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.MessageFormat;
+import java.time.Instant;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
@@ -166,7 +166,8 @@ class RebuildCommitGraph extends TextBuiltin {
final CommitBuilder newc = new CommitBuilder();
newc.setTreeId(emptyTree);
- newc.setAuthor(new PersonIdent(me, new Date(t.commitTime)));
+ newc.setAuthor(new PersonIdent(me,
+ Instant.ofEpochSecond(t.commitTime)));
newc.setCommitter(newc.getAuthor());
newc.setParentIds(newParents);
newc.setMessage("ORIGINAL " + t.oldId.name() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java
index faa2bceb74..7aff2dd9cd 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteReftable.java
@@ -24,6 +24,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -209,14 +211,15 @@ class WriteReftable extends TextBuiltin {
}
String ref = m.group(1);
double t = Double.parseDouble(m.group(2));
- long time = ((long) t) * 1000L;
+ Instant time = Instant.ofEpochSecond((long) t);
long index = (long) (t * 1e6);
String user = m.group(3);
ObjectId oldId = parseId(m.group(4));
ObjectId newId = parseId(m.group(5));
String msg = m.group(6);
String email = user + "@gerrit"; //$NON-NLS-1$
- PersonIdent who = new PersonIdent(user, email, time, -480);
+ PersonIdent who = new PersonIdent(user, email, time,
+ ZoneOffset.ofHours(-8));
log.add(new LogEntry(ref, index, who, oldId, newId, msg));
}
}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
index b5bf6d2bc3..bb1e950542 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, 2013 Sasa Zivkov <sasa.zivkov@sap.com>
- * Copyright (C) 2013, 2021 Obeo and others
+ * Copyright (C) 2013, 2025 Obeo 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 class CLIText extends TranslationBundle {
}
// @formatter:off
+ /***/ public String addIncompatibleOptions;
/***/ public String alreadyOnBranch;
/***/ public String alreadyUpToDate;
/***/ public String answerNo;
diff --git a/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
index 6eeb24d6b4..2f516673bb 100644
--- a/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.agent/META-INF/MANIFEST.MF
@@ -2,16 +2,16 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.agent;singleton:=true
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/agent
Bundle-Vendor: %Bundle-Vendor
-Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[7.2.0,7.3.0)"
+Fragment-Host: org.eclipse.jgit.ssh.apache;bundle-version="[7.4.0,7.5.0)"
Bundle-ActivationPolicy: lazy
Automatic-Module-Name: org.eclipse.jgit.ssh.apache.agent
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Import-Package: org.eclipse.jgit.transport.sshd;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)"
+Import-Package: org.eclipse.jgit.transport.sshd;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)"
Require-Bundle: com.sun.jna;bundle-version="[5.8.0,6.0.0)",
com.sun.jna.platform;bundle-version="[5.8.0,6.0.0)"
-Export-Package: org.eclipse.jgit.internal.transport.sshd.agent.connector;version="7.2.0";x-internal:=true
+Export-Package: org.eclipse.jgit.internal.transport.sshd.agent.connector;version="7.4.0";x-internal:=true
diff --git a/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF
index 30437f25ee..0bbb111325 100644
--- a/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.agent/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.ssh.apache.agent - Sources
Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.agent.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache.agent;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.apache.agent/pom.xml b/org.eclipse.jgit.ssh.apache.agent/pom.xml
index feec706a25..c9a5ba0b61 100644
--- a/org.eclipse.jgit.ssh.apache.agent/pom.xml
+++ b/org.eclipse.jgit.ssh.apache.agent/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ssh.apache.agent</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache.test/BUILD b/org.eclipse.jgit.ssh.apache.test/BUILD
index dfc059f0a3..bf796c058e 100644
--- a/org.eclipse.jgit.ssh.apache.test/BUILD
+++ b/org.eclipse.jgit.ssh.apache.test/BUILD
@@ -8,7 +8,9 @@ load(
)
DEPS = [
- "//lib:eddsa",
+ "//lib:bcpkix",
+ "//lib:bcprov",
+ "//lib:bcutil",
"//lib:junit",
"//lib:slf4j-api",
"//lib:sshd-osgi",
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 f266ce106a..aa88c6aa23 100644
--- a/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache.test/META-INF/MANIFEST.MF
@@ -3,42 +3,47 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.ssh.apache.test
Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.hamcrest.core;bundle-version="[1.3.0,2.0.0)"
-Import-Package: org.apache.sshd.client.config.hosts;version="[2.14.0,2.15.0)",
- org.apache.sshd.common;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.auth;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.config.keys;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.helpers;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.kex;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.keyprovider;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.session;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.signature;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.buffer;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.net;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.security;version="[2.14.0,2.15.0)",
- org.apache.sshd.core;version="[2.14.0,2.15.0)",
- org.apache.sshd.server;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.forward;version="[2.14.0,2.15.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.signing.ssh;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.sshd.proxy;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit.ssh;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.sshd;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.sshd.agent;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+Import-Package: org.apache.sshd.certificate;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.config.hosts;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.auth;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.cipher;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.config.keys;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.helpers;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.kex;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.keyprovider;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.session;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.signature;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.buffer;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.net;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.security;version="[2.15.0,2.16.0)",
+ org.apache.sshd.core;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.forward;version="[2.15.0,2.16.0)",
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.signing.ssh;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.sshd;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit.ssh;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.sshd;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.sshd.agent;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.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)",
org.junit.runner;version="[4.13,5.0.0)",
org.junit.runners;version="[4.13.0,5.0.0)",
- org.slf4j;version="[1.7.0,2.0.0)"
+ org.slf4j;version="[1.7.0,3.0.0)"
diff --git a/org.eclipse.jgit.ssh.apache.test/pom.xml b/org.eclipse.jgit.ssh.apache.test/pom.xml
index 2df07f7ea1..7768e95694 100644
--- a/org.eclipse.jgit.ssh.apache.test/pom.xml
+++ b/org.eclipse.jgit.ssh.apache.test/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ssh.apache.test</artifactId>
diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java
index 90fde3fb28..84d8179a3d 100644
--- a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java
+++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/signing/ssh/AllowedSignersParseTest.java
@@ -168,6 +168,14 @@ public class AllowedSignersParseTest {
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO"),
AllowedSigners.parseLine(
"*@a.com,*@b.a.com cert-authority namespaces=\"git\" valid-after=\"20240901\" valid-before=\"202409011200Z\" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO"));
+ assertEquals(new AllowedSigners.AllowedEntry(
+ new String[] { "foo@a.com" },
+ false, new String[] { "git" },
+ Instant.parse("2024-09-01T03:30:00.00Z"),
+ Instant.parse("2024-09-01T12:00:00.00Z"),
+ "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGxkz2AUld8eitmyIYlVV+Sot4jT3CigyBmvFRff0q4cSsKLx4x2TxGQeKKVueJEawtsUC2GNRV9FxXsTCUGcZU="),
+ AllowedSigners.parseLine(
+ "foo@a.com namespaces=\"git\" valid-after=\"20240901\" valid-before=\"202409011200Z\" ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGxkz2AUld8eitmyIYlVV+Sot4jT3CigyBmvFRff0q4cSsKLx4x2TxGQeKKVueJEawtsUC2GNRV9FxXsTCUGcZU="));
}
@Test
@@ -183,6 +191,8 @@ public class AllowedSignersParseTest {
assertThrows(Exception.class, () -> AllowedSigners.parseLine(
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO"));
assertThrows(Exception.class, () -> AllowedSigners.parseLine(
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO foo@bar.com"));
+ assertThrows(Exception.class, () -> AllowedSigners.parseLine(
"AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO"));
assertThrows(Exception.class, () -> AllowedSigners.parseLine(
"a@a.com namespaces=\"\" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGATOZ8PcOKdY978fzIstnZ0+FuefIWKp7wRZynQLdzO"));
diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReaderTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReaderTest.java
new file mode 100644
index 0000000000..d36c38f335
--- /dev/null
+++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReaderTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.transport.sshd;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.sshd.client.config.hosts.KnownHostEntry;
+import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
+import org.junit.Test;
+
+public class KnownHostEntryReaderTest {
+
+ @Test
+ public void testUnsupportedHostKeyLine() {
+ KnownHostEntry entry = KnownHostEntryReader.parseHostEntry(
+ "[localhost]:2222 ssh-unknown AAAAC3NzaC1lZDI1NTE5AAAAIPu6ntmyfSOkqLl3qPxD5XxwW7OONwwSG3KO+TGn+PFu");
+ AuthorizedKeyEntry keyEntry = entry.getKeyEntry();
+ assertNotNull(keyEntry);
+ assertEquals("ssh-unknown", keyEntry.getKeyType());
+ }
+}
diff --git a/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java
new file mode 100644
index 0000000000..6b61821a0f
--- /dev/null
+++ b/org.eclipse.jgit.ssh.apache.test/tst/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabaseTest.java
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.transport.sshd;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.certificate.OpenSshCertificateBuilder;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.config.keys.PublicKeyEntry;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.errors.UnsupportedCredentialItem;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.CredentialsProvider;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.sshd.ServerKeyDatabase;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Tests for {@link OpenSshServerKeyDatabase}.
+ */
+public class OpenSshServerKeyDatabaseTest {
+
+ private static final InetSocketAddress LOCAL = new InetSocketAddress(
+ InetAddress.getLoopbackAddress(), SshConstants.DEFAULT_PORT);
+
+ private static final InetSocketAddress LOCAL_29418 = new InetSocketAddress(
+ InetAddress.getLoopbackAddress(), 29418);
+
+ private static PublicKey rsa1024;
+ private static PublicKey rsa2048;
+ private static PublicKey ec256;
+ private static PublicKey ec384;
+ private static PublicKey caKey;
+ private static PublicKey certificate;
+
+ @BeforeClass
+ public static void initKeys() throws Exception {
+ // Generate a few keys that we can use
+ KeyPairGenerator gen = SecurityUtils.getKeyPairGenerator(KeyUtils.RSA_ALGORITHM);
+ gen.initialize(1024);
+ rsa1024 = gen.generateKeyPair().getPublic();
+ gen.initialize(2048);
+ rsa2048 = gen.generateKeyPair().getPublic();
+ gen = SecurityUtils.getKeyPairGenerator(KeyUtils.EC_ALGORITHM);
+ ECCurves curve = ECCurves.fromCurveSize(256);
+ gen.initialize(curve.getParameters());
+ ec256 = gen.generateKeyPair().getPublic();
+ PublicKey certKey = gen.generateKeyPair().getPublic();
+ curve = ECCurves.fromCurveSize(384);
+ gen.initialize(curve.getParameters());
+ ec384 = gen.generateKeyPair().getPublic();
+ // Generate a certificate for some key
+ gen.initialize(curve.getParameters());
+ KeyPair ca = gen.generateKeyPair();
+ caKey = ca.getPublic();
+ certificate = OpenSshCertificateBuilder
+ .hostCertificate()
+ .serial(System.currentTimeMillis())
+ .publicKey(certKey)
+ .id("test-host-cert")
+ .validBefore(
+ System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1))
+ .principals(List.of("localhost", "127.0.0.1"))
+ .sign(ca, "ecdsa-sha2-nistp384");
+ }
+
+ @Rule
+ public TemporaryFolder tmp = new TemporaryFolder();
+
+ private Path knownHosts;
+ private Path knownHosts2;
+ private ServerKeyDatabase database;
+
+ @Before
+ public void setupDatabase() throws Exception {
+ Path root = tmp.getRoot().toPath();
+ knownHosts = root.resolve("known_hosts");
+ knownHosts2 = root.resolve("known_hosts2");
+ database = new OpenSshServerKeyDatabase(false, List.of(knownHosts, knownHosts2));
+ }
+
+ @Test
+ public void testFindInSecondFile() throws Exception {
+ Files.write(knownHosts,
+ List.of(
+ "some.other.host " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384)));
+ Files.write(knownHosts2,
+ List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048)));
+ assertTrue(database.accept("localhost", LOCAL, ec256,
+ new KnownHostsConfig(), null));
+ assertFalse(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testNoFirstFile() throws Exception {
+ Files.write(knownHosts2,
+ List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048)));
+ assertTrue(database.accept("localhost", LOCAL, ec256,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testFind() throws Exception {
+ Files.write(knownHosts,
+ List.of("localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384)));
+ Files.write(knownHosts2,
+ List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048)));
+ assertTrue(database.accept("localhost", LOCAL, ec256,
+ new KnownHostsConfig(), null));
+ assertTrue(database.accept("localhost:22", LOCAL, ec256,
+ new KnownHostsConfig(), null));
+ assertTrue(database.accept("127.0.0.1", LOCAL, rsa1024,
+ new KnownHostsConfig(), null));
+ assertTrue(database.accept("[127.0.0.1]:22", LOCAL, rsa1024,
+ new KnownHostsConfig(), null));
+ assertFalse(database.accept("localhost:29418", LOCAL_29418, ec256,
+ new KnownHostsConfig(), null));
+ assertFalse(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testFindCertificate() throws Exception {
+ Files.write(knownHosts,
+ List.of("localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384),
+ "@cert-authority localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(caKey)));
+ assertTrue(database.accept("localhost", LOCAL, certificate,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testCaKeyNotConsidered() throws Exception {
+ Files.write(knownHosts,
+ List.of("localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384),
+ "@cert-authority localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(ec256)));
+ assertFalse(database.accept("localhost", LOCAL, ec256,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testkeyPlainAndCa() throws Exception {
+ Files.write(knownHosts, List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384),
+ "@cert-authority localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(ec256),
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256)));
+ // ec256 is a CA key, but also a valid direct host key for localhost
+ assertTrue(database.accept("localhost", LOCAL, ec256,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testLookupCertificate() throws Exception {
+ List<PublicKey> keys = database.lookup("localhost", LOCAL,
+ new KnownHostsConfig());
+ // Certificates or CA keys are not reported via lookup.
+ assertTrue(keys.isEmpty());
+ }
+
+ @Test
+ public void testCertificateNotAdded() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384));
+ Files.write(knownHosts, initialKnownHosts);
+ assertFalse(database.accept("localhost", LOCAL, certificate,
+ new KnownHostsConfig(), null));
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertFalse(
+ database.accept("localhost", LOCAL, certificate,
+ new KnownHostsConfig(
+ KnownHostsConfig.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(0, ui.invocations);
+ assertFile(knownHosts, initialKnownHosts);
+ }
+
+ @Test
+ public void testCertificateNotModified() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "@cert-authority localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(ec384),
+ "some.other.com " + PublicKeyEntry.toString(ec256));
+ Files.write(knownHosts, initialKnownHosts);
+ assertFalse(database.accept("localhost", LOCAL, certificate,
+ new KnownHostsConfig(), null));
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertFalse(
+ database.accept("localhost", LOCAL, certificate,
+ new KnownHostsConfig(
+ KnownHostsConfig.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(0, ui.invocations);
+ assertFile(knownHosts, initialKnownHosts);
+ }
+
+ @Test
+ public void testModifyFile() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "some.other.host " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ assertFalse(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ assertFile(knownHosts, initialKnownHosts);
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertFalse(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ACCEPT_NEW),
+ null));
+ assertFile(knownHosts, initialKnownHosts);
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ACCEPT_ANY),
+ null));
+ assertFile(knownHosts, initialKnownHosts);
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertFalse(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ null));
+ assertFile(knownHosts, initialKnownHosts);
+ assertFile(knownHosts2, initialKnownHosts2);
+
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, false);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ assertFile(knownHosts, initialKnownHosts);
+ assertFile(knownHosts2, initialKnownHosts2);
+
+ ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ assertFile(knownHosts, initialKnownHosts);
+ assertFile(knownHosts2, List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048)));
+ assertTrue(database.accept("127.0.0.1", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testModifyFirstFile() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List.of(
+ "some.other.host " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ assertFile(knownHosts,
+ List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384),
+ "some.other.com " + PublicKeyEntry.toString(ec384)));
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testModifyMatchingKeyType() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, rsa2048,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ assertFile(knownHosts,
+ List.of("localhost,127.0.0.1 "
+ + PublicKeyEntry.toString(rsa2048),
+ "some.other.com " + PublicKeyEntry.toString(ec384)));
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("127.0.0.1:22", LOCAL, rsa2048,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testModifyMatchingKeyType2() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(ec384));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ assertFile(knownHosts,
+ List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384),
+ "some.other.com " + PublicKeyEntry.toString(ec384)));
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testModifySecondFile() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec384));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec256),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ assertFile(knownHosts, initialKnownHosts);
+ assertFile(knownHosts2,
+ List.of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384),
+ "some.other.com " + PublicKeyEntry.toString(rsa2048)));
+ assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testAddNewKey() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "some.other.host " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec256));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List
+ .of("some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ List<String> expected = new ArrayList<>(initialKnownHosts);
+ expected.add("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384));
+ assertFile(knownHosts, expected);
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testCreateNewFile() throws Exception {
+ List<String> initialKnownHosts2 = List
+ .of("some.other.com " + PublicKeyEntry.toString(ec256));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ assertFile(knownHosts, List
+ .of("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384)));
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testAddNewKey2() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "some.other.host " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec256));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List
+ .of("some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("127.0.0.1:29418", LOCAL_29418, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ List<String> expected = new ArrayList<>(initialKnownHosts);
+ expected.add("[127.0.0.1]:29418,[localhost]:29418 "
+ + PublicKeyEntry.toString(ec384));
+ assertFile(knownHosts, expected);
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("localhost:29418", LOCAL_29418, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testAddNewKey3() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "some.other.host " + PublicKeyEntry.toString(rsa1024),
+ "some.other.com " + PublicKeyEntry.toString(ec256));
+ Files.write(knownHosts, initialKnownHosts);
+ List<String> initialKnownHosts2 = List
+ .of("some.other.com " + PublicKeyEntry.toString(rsa2048));
+ Files.write(knownHosts2, initialKnownHosts2);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost:29418", LOCAL_29418, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ List<String> expected = new ArrayList<>(initialKnownHosts);
+ expected.add("[localhost]:29418,[127.0.0.1]:29418 "
+ + PublicKeyEntry.toString(ec384));
+ assertFile(knownHosts, expected);
+ assertFile(knownHosts2, initialKnownHosts2);
+ assertTrue(database.accept("127.0.0.1:29418", LOCAL_29418, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ @Test
+ public void testUnknownKeyType() throws Exception {
+ List<String> initialKnownHosts = List.of(
+ "localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384)
+ .replace("ecdsa", "foo"),
+ "some.other.com " + PublicKeyEntry.toString(ec384));
+ Files.write(knownHosts, initialKnownHosts);
+ TestCredentialsProvider ui = new TestCredentialsProvider(true, true);
+ assertTrue(database.accept("localhost", LOCAL, ec384,
+ new KnownHostsConfig(
+ ServerKeyDatabase.Configuration.StrictHostKeyChecking.ASK),
+ ui));
+ assertEquals(1, ui.invocations);
+ // The "modified key" dialog has two questions; whereas the "add new
+ // key" is just a simple question.
+ assertEquals(2, ui.questions);
+ List<String> expected = new ArrayList<>(initialKnownHosts);
+ expected.add("localhost,127.0.0.1 " + PublicKeyEntry.toString(ec384));
+ assertFile(knownHosts, expected);
+ assertTrue(database.accept("127.0.0.1:22", LOCAL, ec384,
+ new KnownHostsConfig(), null));
+ }
+
+ private void assertFile(Path path, List<String> lines) throws Exception {
+ assertEquals(lines, Files.readAllLines(path).stream()
+ .filter(s -> !s.isBlank()).toList());
+ }
+
+ private static class TestCredentialsProvider extends CredentialsProvider {
+
+ private final boolean[] values;
+
+ int invocations = 0;
+
+ int questions = 0;
+
+ TestCredentialsProvider(boolean accept, boolean store) {
+ values = new boolean[] { accept, store };
+ }
+
+ @Override
+ public boolean isInteractive() {
+ return true;
+ }
+
+ @Override
+ public boolean supports(CredentialItem... items) {
+ return true;
+ }
+
+ @Override
+ public boolean get(URIish uri, CredentialItem... items)
+ throws UnsupportedCredentialItem {
+ invocations++;
+ int i = 0;
+ for (CredentialItem item : items) {
+ if (item instanceof CredentialItem.YesNoType) {
+ ((CredentialItem.YesNoType) item)
+ .setValue(i < values.length && values[i++]);
+ questions++;
+ }
+ }
+ return true;
+ }
+ }
+
+ private static class KnownHostsConfig implements ServerKeyDatabase.Configuration {
+
+ @NonNull
+ private final StrictHostKeyChecking check;
+
+ KnownHostsConfig() {
+ this(StrictHostKeyChecking.REQUIRE_MATCH);
+ }
+
+ KnownHostsConfig(@NonNull StrictHostKeyChecking check) {
+ this.check = check;
+ }
+
+ @Override
+ public List<String> getUserKnownHostsFiles() {
+ return List.of();
+ }
+
+ @Override
+ public List<String> getGlobalKnownHostsFiles() {
+ return List.of();
+ }
+
+ @Override
+ public StrictHostKeyChecking getStrictHostKeyChecking() {
+ return check;
+ }
+
+ @Override
+ public boolean getHashKnownHosts() {
+ return false;
+ }
+
+ @Override
+ public String getUsername() {
+ return "user";
+ }
+
+ }
+}
diff --git a/org.eclipse.jgit.ssh.apache/BUILD b/org.eclipse.jgit.ssh.apache/BUILD
index fd88a8a88a..c32635f7c5 100644
--- a/org.eclipse.jgit.ssh.apache/BUILD
+++ b/org.eclipse.jgit.ssh.apache/BUILD
@@ -12,7 +12,10 @@ java_library(
resource_strip_prefix = "org.eclipse.jgit.ssh.apache/resources",
resources = RESOURCES,
deps = [
- "//lib:eddsa",
+ "//lib:bcpg",
+ "//lib:bcpkix",
+ "//lib:bcprov",
+ "//lib:bcutil",
"//lib:slf4j-api",
"//lib:sshd-osgi",
"//lib:sshd-sftp",
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
index b6b528cec4..92d124d7a5 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/MANIFEST.MF
@@ -6,10 +6,10 @@ Bundle-SymbolicName: org.eclipse.jgit.ssh.apache
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-ActivationPolicy: lazy
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.2.0";x-friends:="org.eclipse.jgit.ssh.apache.test",
- org.eclipse.jgit.internal.transport.sshd;version="7.2.0";x-internal:=true;
+Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.4.0";x-friends:="org.eclipse.jgit.ssh.apache.test",
+ org.eclipse.jgit.internal.transport.sshd;version="7.4.0";x-friends:="org.eclipse.jgit.ssh.apache.test";
uses:="org.apache.sshd.client,
org.apache.sshd.client.auth,
org.apache.sshd.client.auth.keyboard,
@@ -24,81 +24,80 @@ Export-Package: org.eclipse.jgit.internal.signing.ssh;version="7.2.0";x-friends:
org.apache.sshd.common.signature,
org.apache.sshd.common.util.buffer,
org.eclipse.jgit.transport",
- org.eclipse.jgit.internal.transport.sshd.agent;version="7.2.0";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.auth;version="7.2.0";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.pkcs11;version="7.2.0";x-internal:=true,
- org.eclipse.jgit.internal.transport.sshd.proxy;version="7.2.0";x-friends:="org.eclipse.jgit.ssh.apache.test",
- org.eclipse.jgit.signing.ssh;version="7.2.0";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.transport.sshd;version="7.2.0";
+ org.eclipse.jgit.internal.transport.sshd.agent;version="7.4.0";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.auth;version="7.4.0";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.pkcs11;version="7.4.0";x-internal:=true,
+ org.eclipse.jgit.internal.transport.sshd.proxy;version="7.4.0";x-friends:="org.eclipse.jgit.ssh.apache.test",
+ org.eclipse.jgit.signing.ssh;version="7.4.0";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.transport.sshd;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.apache.sshd.client.config.hosts,
org.apache.sshd.common.keyprovider,
org.eclipse.jgit.util,
org.apache.sshd.client.session,
org.apache.sshd.client.keyverifier",
- org.eclipse.jgit.transport.sshd.agent;version="7.2.0",
- sun.security.x509
-Import-Package: net.i2p.crypto.eddsa;version="[0.3.0,0.4.0)",
- org.apache.sshd.agent;version="[2.14.0,2.15.0)",
- org.apache.sshd.client;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.auth;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.auth.keyboard;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.auth.password;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.auth.pubkey;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.channel;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.config.hosts;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.config.keys;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.future;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.keyverifier;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.session;version="[2.14.0,2.15.0)",
- org.apache.sshd.client.session.forward;version="[2.14.0,2.15.0)",
- org.apache.sshd.common;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.auth;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.channel;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.cipher;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.compression;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.config.keys;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.config.keys.loader;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.config.keys.u2f;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.digest;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.forward;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.future;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.helpers;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.io;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.kex;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.kex.extension;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.kex.extension.parser;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.keyprovider;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.mac;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.random;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.session;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.session.helpers;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.signature;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.buffer;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.buffer.keys;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.closeable;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.io;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.io.der;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.io.functors;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.io.resource;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.logging;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.net;version="[2.14.0,2.15.0)",
- org.apache.sshd.common.util.security;version="[2.14.0,2.15.0)",
- org.apache.sshd.core;version="[2.14.0,2.15.0)",
- org.apache.sshd.server.auth;version="[2.14.0,2.15.0)",
- org.apache.sshd.sftp;version="[2.14.0,2.15.0)",
- org.apache.sshd.sftp.client;version="[2.14.0,2.15.0)",
- org.apache.sshd.sftp.common;version="[2.14.0,2.15.0)",
- org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.fnmatch;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.transport.sshd.agent;version="7.4.0"
+Import-Package: org.bouncycastle.jce.provider;version="[1.80.0,2.0.0)",
+ org.apache.sshd.agent;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.auth;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.auth.keyboard;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.auth.password;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.auth.pubkey;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.channel;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.config.hosts;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.config.keys;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.future;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.keyverifier;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.session;version="[2.15.0,2.16.0)",
+ org.apache.sshd.client.session.forward;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.auth;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.channel;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.cipher;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.compression;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.config.keys;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.config.keys.loader;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.config.keys.loader.openssh.kdf;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.config.keys.u2f;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.digest;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.forward;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.future;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.helpers;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.io;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.kex;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.kex.extension;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.kex.extension.parser;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.keyprovider;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.mac;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.random;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.session;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.session.helpers;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.signature;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.buffer;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.buffer.keys;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.closeable;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.io;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.io.der;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.io.functors;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.io.resource;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.logging;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.net;version="[2.15.0,2.16.0)",
+ org.apache.sshd.common.util.security;version="[2.15.0,2.16.0)",
+ org.apache.sshd.core;version="[2.15.0,2.16.0)",
+ org.apache.sshd.server.auth;version="[2.15.0,2.16.0)",
+ org.apache.sshd.sftp;version="[2.15.0,2.16.0)",
+ org.apache.sshd.sftp.client;version="[2.15.0,2.16.0)",
+ org.apache.sshd.sftp.common;version="[2.15.0,2.16.0)",
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.fnmatch;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
org.slf4j;version="[1.7.0,3.0.0)"
diff --git a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
index c19e0aa253..02b4324cd3 100644
--- a/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.apache/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.ssh.apache - Sources
Bundle-SymbolicName: org.eclipse.jgit.ssh.apache.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.apache;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.apache/pom.xml b/org.eclipse.jgit.ssh.apache/pom.xml
index a002290378..2d6cd39ae4 100644
--- a/org.eclipse.jgit.ssh.apache/pom.xml
+++ b/org.eclipse.jgit.ssh.apache/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ssh.apache</artifactId>
@@ -30,7 +30,6 @@
<properties>
<translate-qualifier/>
<source-bundle-manifest>${project.build.directory}/META-INF/SOURCE-MANIFEST.MF</source-bundle-manifest>
- <eddsa-version>0.3.0</eddsa-version>
</properties>
<dependencies>
@@ -63,12 +62,6 @@
</dependency>
<dependency>
- <groupId>net.i2p.crypto</groupId>
- <artifactId>eddsa</artifactId>
- <version>${eddsa-version}</version>
- </dependency>
-
- <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
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 6048239391..773c4b9432 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
@@ -61,6 +61,7 @@ The expected {1} key for host ''{2}'' has the fingerprints:\n\
The {0} key actually received has the fingerprints:\n\
{5}\n\
{6}
+knownHostsRevokedCertificateMsg=Host ''{0}'' sent a certificate with a CA key that is marked as revoked in the known hosts file {1}.
knownHostsRevokedKeyMsg=Host ''{0}'' sent a key that is marked as revoked in the known hosts file {1}.
knownHostsUnknownKeyMsg=The authenticity of host ''{0}'' cannot be established.
knownHostsUnknownKeyPrompt=Accept and store this key, and continue connecting?
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java
index cfbe7a78a7..80b171f216 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/signing/ssh/AllowedSigners.java
@@ -21,6 +21,7 @@ import java.text.MessageFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
@@ -36,8 +37,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -64,8 +63,6 @@ final class AllowedSigners extends ModifiableFileWatcher {
private static final String VALID_BEFORE = "valid-before="; //$NON-NLS-1$
- private static final String SSH_KEY_PREFIX = "ssh-"; //$NON-NLS-1$
-
private static final DateTimeFormatter SSH_DATE_FORMAT = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
@@ -323,8 +320,7 @@ final class AllowedSigners extends ModifiableFileWatcher {
&& Character.isWhitespace(line.charAt(CERT_AUTHORITY.length())))
|| matches(line, NAMESPACES, 0)
|| matches(line, VALID_AFTER, 0)
- || matches(line, VALID_BEFORE, 0)
- || matches(line, SSH_KEY_PREFIX, 0)) {
+ || matches(line, VALID_BEFORE, 0)) {
throw new StreamCorruptedException(
SshdText.get().signAllowedSignersNoIdentities);
}
@@ -449,7 +445,9 @@ final class AllowedSigners extends ModifiableFileWatcher {
s.substring(start)));
}
String keyType = s.substring(start, endOfKeyType);
- if (!keyType.startsWith(SSH_KEY_PREFIX)) {
+ String key = s.substring(startOfKey, i);
+ if (!key.startsWith("AAAA")) { //$NON-NLS-1$
+ // base64 encoded SSH keys always start with four 'A's.
throw new StreamCorruptedException(MessageFormat.format(
SshdText.get().signAllowedSignersPublicKeyParsing,
s.substring(start)));
@@ -482,12 +480,8 @@ final class AllowedSigners extends ModifiableFileWatcher {
if (isUTC) {
return time.atOffset(ZoneOffset.UTC).toInstant();
}
- TimeZone tz = SystemReader.getInstance().getTimeZone();
- // Since there are a few TimeZone IDs that are not recognized by ZoneId,
- // use offsets.
- return time.atOffset(ZoneOffset.ofTotalSeconds(
- (int) TimeUnit.MILLISECONDS.toSeconds(tz.getRawOffset())))
- .toInstant();
+ ZoneId tz = SystemReader.getInstance().getTimeZoneId();
+ return time.atZone(tz).toInstant();
}
// OpenSSH uses the backslash *only* to quote the double-quote.
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java
index 96829b7365..6b2345df1b 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/KnownHostEntryReader.java
@@ -29,6 +29,7 @@ import org.apache.sshd.client.config.hosts.HostPatternsHolder;
import org.apache.sshd.client.config.hosts.KnownHostEntry;
import org.apache.sshd.client.config.hosts.KnownHostHashValue;
import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
+import org.apache.sshd.common.config.keys.PublicKeyEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -97,7 +98,7 @@ public class KnownHostEntryReader {
return i < 0 ? line.trim() : line.substring(0, i).trim();
}
- private static KnownHostEntry parseHostEntry(String line) {
+ static KnownHostEntry parseHostEntry(String line) {
KnownHostEntry entry = new KnownHostEntry();
entry.setConfigLine(line);
String tmp = line;
@@ -135,8 +136,8 @@ public class KnownHostEntryReader {
entry.setPatterns(patterns);
}
tmp = tmp.substring(i + 1).trim();
- AuthorizedKeyEntry key = AuthorizedKeyEntry
- .parseAuthorizedKeyEntry(tmp);
+ AuthorizedKeyEntry key = PublicKeyEntry
+ .parsePublicKeyEntry(new AuthorizedKeyEntry(), tmp);
if (key == null) {
return null;
}
diff --git a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java
index 2b4f7e50ff..acb77c5bb7 100644
--- a/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java
+++ b/org.eclipse.jgit.ssh.apache/src/org/eclipse/jgit/internal/transport/sshd/OpenSshServerKeyDatabase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, 2021 Thomas Wolf <thomas.wolf@paranor.ch> 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
@@ -31,9 +31,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
@@ -45,10 +47,13 @@ import org.apache.sshd.client.config.hosts.KnownHostHashValue;
import org.apache.sshd.client.keyverifier.KnownHostsServerKeyVerifier.HostEntryPair;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.config.keys.OpenSshCertificate;
import org.apache.sshd.common.config.keys.PublicKeyEntry;
import org.apache.sshd.common.config.keys.PublicKeyEntryResolver;
+import org.apache.sshd.common.config.keys.UnsupportedSshPublicKey;
import org.apache.sshd.common.digest.BuiltinDigests;
import org.apache.sshd.common.mac.Mac;
import org.apache.sshd.common.util.io.ModifiableFileWatcher;
@@ -126,6 +131,9 @@ public class OpenSshServerKeyDatabase
/** Can be used to mark revoked known host lines. */
private static final String MARKER_REVOKED = "revoked"; //$NON-NLS-1$
+ /** Marks CA keys used for SSH certificates. */
+ private static final String MARKER_CA = "cert-authority"; //$NON-NLS-1$
+
private final boolean askAboutNewFile;
private final Map<Path, HostKeyFile> knownHostsFiles = new ConcurrentHashMap<>();
@@ -178,7 +186,10 @@ public class OpenSshServerKeyDatabase
for (HostKeyFile file : filesToUse) {
for (HostEntryPair current : file.get()) {
KnownHostEntry entry = current.getHostEntry();
- if (!isRevoked(entry)) {
+ if (current.getServerKey() instanceof UnsupportedSshPublicKey) {
+ continue;
+ }
+ if (!isRevoked(entry) && !isCertificateAuthority(entry)) {
for (SshdSocketAddress host : candidates) {
if (entry.isHostMatch(host.getHostName(),
host.getPort())) {
@@ -204,6 +215,7 @@ public class OpenSshServerKeyDatabase
Collection<SshdSocketAddress> candidates = getCandidates(connectAddress,
remoteAddress);
for (HostKeyFile file : filesToUse) {
+ HostEntryPair lastModified = modified[0];
try {
if (find(candidates, serverKey, file.get(), modified)) {
return true;
@@ -212,24 +224,35 @@ public class OpenSshServerKeyDatabase
ask.revokedKey(remoteAddress, serverKey, file.getPath());
return false;
}
- if (path == null && modified[0] != null) {
+ if (modified[0] != lastModified) {
// Remember the file in which we might need to update the
// entry
path = file.getPath();
}
}
+ if (serverKey instanceof OpenSshCertificate) {
+ return false;
+ }
if (modified[0] != null) {
- // We found an entry, but with a different key
+ // We found an entry, but with a different key.
AskUser.ModifiedKeyHandling toDo = ask.acceptModifiedServerKey(
remoteAddress, modified[0].getServerKey(),
serverKey, path);
if (toDo == AskUser.ModifiedKeyHandling.ALLOW_AND_STORE) {
- try {
- updateModifiedServerKey(serverKey, modified[0], path);
- knownHostsFiles.get(path).resetReloadAttributes();
- } catch (IOException e) {
- LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate,
- path));
+ if (modified[0]
+ .getServerKey() instanceof UnsupportedSshPublicKey) {
+ // Never update a line containing an unknown key type,
+ // always add.
+ addKeyToFile(filesToUse.get(0), candidates, serverKey, ask,
+ config);
+ } else {
+ try {
+ updateModifiedServerKey(serverKey, modified[0], path);
+ knownHostsFiles.get(path).resetReloadAttributes();
+ } catch (IOException e) {
+ LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate,
+ path));
+ }
}
}
if (toDo == AskUser.ModifiedKeyHandling.DENY) {
@@ -242,19 +265,8 @@ public class OpenSshServerKeyDatabase
return true;
} else if (ask.acceptUnknownKey(remoteAddress, serverKey)) {
if (!filesToUse.isEmpty()) {
- HostKeyFile toUpdate = filesToUse.get(0);
- path = toUpdate.getPath();
- try {
- if (Files.exists(path) || !askAboutNewFile
- || ask.createNewFile(path)) {
- updateKnownHostsFile(candidates, serverKey, path,
- config);
- toUpdate.resetReloadAttributes();
- }
- } catch (Exception e) {
- LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate,
- path), e);
- }
+ addKeyToFile(filesToUse.get(0), candidates, serverKey, ask,
+ config);
}
return true;
}
@@ -265,39 +277,90 @@ public class OpenSshServerKeyDatabase
private static final long serialVersionUID = 1L;
}
- private boolean isRevoked(KnownHostEntry entry) {
+ private static boolean isRevoked(KnownHostEntry entry) {
return MARKER_REVOKED.equals(entry.getMarker());
}
+ private static boolean isCertificateAuthority(KnownHostEntry entry) {
+ return MARKER_CA.equals(entry.getMarker());
+ }
+
private boolean find(Collection<SshdSocketAddress> candidates,
PublicKey serverKey, List<HostEntryPair> entries,
HostEntryPair[] modified) throws RevokedKeyException {
+ PublicKey keyToCheck = serverKey;
+ boolean isCert = false;
+ String keyType = KeyUtils.getKeyType(keyToCheck);
+ String modifiedKeyType = null;
+ if (modified[0] != null) {
+ modifiedKeyType = modified[0].getHostEntry().getKeyEntry()
+ .getKeyType();
+ }
+ if (serverKey instanceof OpenSshCertificate) {
+ keyToCheck = ((OpenSshCertificate) serverKey).getCaPubKey();
+ isCert = true;
+ }
for (HostEntryPair current : entries) {
KnownHostEntry entry = current.getHostEntry();
- for (SshdSocketAddress host : candidates) {
- if (entry.isHostMatch(host.getHostName(), host.getPort())) {
- boolean revoked = isRevoked(entry);
- if (KeyUtils.compareKeys(serverKey,
- current.getServerKey())) {
- // Exact match
- if (revoked) {
- throw new RevokedKeyException();
- }
+ if (candidates.stream().anyMatch(host -> entry
+ .isHostMatch(host.getHostName(), host.getPort()))) {
+ boolean revoked = isRevoked(entry);
+ boolean haveCert = isCertificateAuthority(entry);
+ if (KeyUtils.compareKeys(keyToCheck, current.getServerKey())) {
+ // Exact match
+ if (revoked) {
+ throw new RevokedKeyException();
+ }
+ if (haveCert == isCert) {
modified[0] = null;
return true;
- } else if (!revoked) {
- // Server sent a different key
+ }
+ }
+ if (haveCert == isCert && !haveCert && !revoked) {
+ // Server sent a different key.
+ if (modifiedKeyType == null) {
modified[0] = current;
- // Keep going -- maybe there's another entry for this
- // host
+ modifiedKeyType = entry.getKeyEntry().getKeyType();
+ } else if (!keyType.equals(modifiedKeyType)) {
+ String thisKeyType = entry.getKeyEntry().getKeyType();
+ if (isBetterMatch(keyType, thisKeyType,
+ modifiedKeyType)) {
+ // Since we may replace the modified[0] key,
+ // prefer to report a key of the same key type
+ // as having been modified.
+ modified[0] = current;
+ modifiedKeyType = keyType;
+ }
}
- break;
+ // Keep going -- maybe there's another entry for this
+ // host
}
}
}
return false;
}
+ private static boolean isBetterMatch(String keyType, String thisType,
+ String modifiedType) {
+ if (keyType.equals(thisType)) {
+ return true;
+ }
+ // EC keys are a bit special because they encode the curve in the key
+ // type. If we have no exactly matching EC key type in known_hosts, we
+ // still prefer to update an existing EC key type over some other key
+ // type.
+ if (!keyType.startsWith("ecdsa") || !thisType.startsWith("ecdsa")) { //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+ if (!modifiedType.startsWith("ecdsa")) { //$NON-NLS-1$
+ return true;
+ }
+ // All three are EC keys. thisType doesn't match the size of keyType
+ // (otherwise the two would have compared equal above already), so it is
+ // not better than modifiedType.
+ return false;
+ }
+
private List<HostKeyFile> addUserHostKeyFiles(List<String> fileNames) {
if (fileNames == null || fileNames.isEmpty()) {
return Collections.emptyList();
@@ -317,6 +380,21 @@ public class OpenSshServerKeyDatabase
return userFiles;
}
+ private void addKeyToFile(HostKeyFile file,
+ Collection<SshdSocketAddress> candidates, PublicKey serverKey,
+ AskUser ask, Configuration config) {
+ Path path = file.getPath();
+ try {
+ if (Files.exists(path) || !askAboutNewFile
+ || ask.createNewFile(path)) {
+ updateKnownHostsFile(candidates, serverKey, path, config);
+ file.resetReloadAttributes();
+ }
+ } catch (Exception e) {
+ LOG.warn(format(SshdText.get().knownHostsCouldNotUpdate, path), e);
+ }
+ }
+
private void updateKnownHostsFile(Collection<SshdSocketAddress> candidates,
PublicKey serverKey, Path path, Configuration config)
throws Exception {
@@ -453,15 +531,22 @@ public class OpenSshServerKeyDatabase
return;
}
InetSocketAddress remote = (InetSocketAddress) remoteAddress;
+ boolean isCert = serverKey instanceof OpenSshCertificate;
+ PublicKey keyToReport = isCert
+ ? ((OpenSshCertificate) serverKey).getCaPubKey()
+ : serverKey;
URIish uri = JGitUserInteraction.toURI(config.getUsername(),
remote);
String sha256 = KeyUtils.getFingerPrint(BuiltinDigests.sha256,
- serverKey);
- String md5 = KeyUtils.getFingerPrint(BuiltinDigests.md5, serverKey);
- String keyAlgorithm = serverKey.getAlgorithm();
+ keyToReport);
+ String md5 = KeyUtils.getFingerPrint(BuiltinDigests.md5,
+ keyToReport);
+ String keyAlgorithm = keyToReport.getAlgorithm();
+ String msg = isCert
+ ? SshdText.get().knownHostsRevokedCertificateMsg
+ : SshdText.get().knownHostsRevokedKeyMsg;
askUser(provider, uri, null, //
- format(SshdText.get().knownHostsRevokedKeyMsg,
- remote.getHostString(), path),
+ format(msg, remote.getHostString(), path),
format(SshdText.get().knownHostsKeyFingerprints,
keyAlgorithm),
md5, sha256);
@@ -594,7 +679,7 @@ public class OpenSshServerKeyDatabase
}
try {
PublicKey serverKey = keyPart.resolvePublicKey(null,
- PublicKeyEntryResolver.IGNORING);
+ PublicKeyEntryResolver.UNSUPPORTED);
if (serverKey == null) {
LOG.warn(format(
SshdText.get().knownHostsUnknownKeyType,
@@ -625,7 +710,7 @@ public class OpenSshServerKeyDatabase
private SshdSocketAddress toSshdSocketAddress(@NonNull String address) {
String host = null;
- int port = 0;
+ int port = SshConstants.DEFAULT_PORT;
if (HostPatternsHolder.NON_STANDARD_PORT_PATTERN_ENCLOSURE_START_DELIM == address
.charAt(0)) {
int end = address.indexOf(
@@ -665,12 +750,23 @@ public class OpenSshServerKeyDatabase
if (address != null) {
candidates.add(address);
}
- return candidates;
+ List<SshdSocketAddress> result = new ArrayList<>();
+ result.addAll(candidates);
+ if (!remoteAddress.isUnresolved()) {
+ SshdSocketAddress ip = new SshdSocketAddress(
+ remoteAddress.getAddress().getHostAddress(),
+ remoteAddress.getPort());
+ if (candidates.add(ip)) {
+ result.add(ip);
+ }
+ }
+ return result;
}
private String createHostKeyLine(Collection<SshdSocketAddress> patterns,
PublicKey key, Configuration config) throws Exception {
StringBuilder result = new StringBuilder();
+ Set<String> knownNames = new HashSet<>();
if (config.getHashKnownHosts()) {
// SHA1 is the only algorithm for host name hashing known to OpenSSH
// or to Apache MINA sshd.
@@ -680,10 +776,10 @@ public class OpenSshServerKeyDatabase
prng = new SecureRandom();
}
byte[] salt = new byte[mac.getDefaultBlockSize()];
- for (SshdSocketAddress address : patterns) {
- if (result.length() > 0) {
- result.append(',');
- }
+ // For hashed hostnames, only one hashed pattern is allowed per
+ // https://man.openbsd.org/sshd.8#SSH_KNOWN_HOSTS_FILE_FORMAT
+ if (!patterns.isEmpty()) {
+ SshdSocketAddress address = patterns.iterator().next();
prng.nextBytes(salt);
KnownHostHashValue.append(result, digester, salt,
KnownHostHashValue.calculateHashValue(
@@ -692,6 +788,10 @@ public class OpenSshServerKeyDatabase
}
} else {
for (SshdSocketAddress address : patterns) {
+ String tgt = address.getHostName() + ':' + address.getPort();
+ if (!knownNames.add(tgt)) {
+ continue;
+ }
if (result.length() > 0) {
result.append(',');
}
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 0533b651e0..e40137870b 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
@@ -83,6 +83,7 @@ public final class SshdText extends TranslationBundle {
/***/ public String knownHostsModifiedKeyDenyMsg;
/***/ public String knownHostsModifiedKeyStorePrompt;
/***/ public String knownHostsModifiedKeyWarning;
+ /***/ public String knownHostsRevokedCertificateMsg;
/***/ public String knownHostsRevokedKeyMsg;
/***/ public String knownHostsUnknownKeyMsg;
/***/ public String knownHostsUnknownKeyPrompt;
diff --git a/org.eclipse.jgit.ssh.apache/src/sun/security/x509/README.md b/org.eclipse.jgit.ssh.apache/src/sun/security/x509/README.md
deleted file mode 100644
index a84ee37ffb..0000000000
--- a/org.eclipse.jgit.ssh.apache/src/sun/security/x509/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-This dummy package is used to fix the error
-"Missing requirement: net.i2p.crypto.eddsa 0.3.0 requires 'java.package; sun.security.x509 0.0.0'"
-raised since eddsa falsely requires this import \ No newline at end of file
diff --git a/org.eclipse.jgit.ssh.jsch.test/BUILD b/org.eclipse.jgit.ssh.jsch.test/BUILD
index 4a8b92518e..d4e6875ed8 100644
--- a/org.eclipse.jgit.ssh.jsch.test/BUILD
+++ b/org.eclipse.jgit.ssh.jsch.test/BUILD
@@ -8,7 +8,9 @@ junit_tests(
srcs = glob(["tst/**/*.java"]),
tags = ["jsch"],
deps = [
- "//lib:eddsa",
+ "//lib:bcpkix",
+ "//lib:bcprov",
+ "//lib:bcutil",
"//lib:jsch",
"//lib:junit",
"//org.eclipse.jgit:jgit",
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 9cf812ce3b..5c3d39678b 100644
--- a/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch.test/META-INF/MANIFEST.MF
@@ -3,20 +3,20 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.ssh.jsch.test
Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-17
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.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit.ssh;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.ssh.jsch;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit.ssh;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.ssh.jsch;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.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.ssh.jsch.test/pom.xml b/org.eclipse.jgit.ssh.jsch.test/pom.xml
index e84ac4d574..f09249bd8c 100644
--- a/org.eclipse.jgit.ssh.jsch.test/pom.xml
+++ b/org.eclipse.jgit.ssh.jsch.test/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ssh.jsch.test</artifactId>
diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
index ed6115b046..6bcec890ee 100644
--- a/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/MANIFEST.MF
@@ -3,19 +3,19 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.ssh.jsch
Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch;singleton:=true
-Fragment-Host: org.eclipse.jgit;bundle-version="[7.2.0,7.3.0)"
+Fragment-Host: org.eclipse.jgit;bundle-version="[7.4.0,7.5.0)"
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: OSGI-INF/l10n/jsch
Bundle-ActivationPolicy: lazy
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="7.2.0"
+Export-Package: org.eclipse.jgit.transport.ssh.jsch;version="7.4.0"
Import-Package: com.jcraft.jsch;version="[0.1.37,0.2.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.io;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.io;version="[7.4.0,7.5.0)",
org.slf4j;version="[1.7.0,3.0.0)"
diff --git a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
index 4e8da25752..cf10f718ee 100644
--- a/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ssh.jsch/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.ssh.jsch - Sources
Bundle-SymbolicName: org.eclipse.jgit.ssh.jsch.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ssh.jsch;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ssh.jsch/pom.xml b/org.eclipse.jgit.ssh.jsch/pom.xml
index fdc5ffb8b3..4871c4e0c9 100644
--- a/org.eclipse.jgit.ssh.jsch/pom.xml
+++ b/org.eclipse.jgit.ssh.jsch/pom.xml
@@ -17,7 +17,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ssh.jsch</artifactId>
diff --git a/org.eclipse.jgit.test/BUILD b/org.eclipse.jgit.test/BUILD
index 29f5b36149..7755df0499 100644
--- a/org.eclipse.jgit.test/BUILD
+++ b/org.eclipse.jgit.test/BUILD
@@ -53,6 +53,11 @@ tests(tests = glob(
exclude = HELPERS + DATA + EXCLUDED,
))
+
+tests(tests = glob(["exttst/**/*.java"]),
+ srcprefix = "exttst/",
+ extra_tags = ["ext"])
+
# Non abstract base classes used for tests by other test classes
BASE = [
PKG + "internal/storage/file/FileRepositoryBuilderTest.java",
diff --git a/org.eclipse.jgit.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
index c1aaea93b6..8582bcf818 100644
--- a/org.eclipse.jgit.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.test/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.test
Bundle-SymbolicName: org.eclipse.jgit.test
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: plugin
Bundle-Vendor: %Bundle-Vendor
Bundle-RequiredExecutionEnvironment: JavaSE-17
@@ -20,65 +20,68 @@ Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
org.apache.commons.compress.compressors.xz;version="[1.15.0,2.0)",
org.apache.commons.io;version="[2.15.0,3.0.0)",
org.apache.commons.io.output;version="[2.15.0,3.0.0)",
+ org.apache.commons.lang3;version="[3.17.0,4.0.0)",
org.assertj.core.api;version="[3.14.0,4.0.0)",
- org.eclipse.jgit.annotations;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.api.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.archive;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.attributes;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.awtui;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.blame;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.diff;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.dircache;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.events;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.fnmatch;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.gitrepo;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.hooks;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.ignore;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.ignore.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.diff;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.diffmergetool;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.fsck;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.commitgraph;version="7.2.0",
- org.eclipse.jgit.internal.storage.dfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.io;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.memory;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.pack;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.storage.reftable;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.connectivity;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.parser;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.internal.transport.ssh;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.junit.time;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lfs;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.logging;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.merge;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.notes;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.patch;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.pgm;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.pgm.internal;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revplot;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.file;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.storage.pack;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.submodule;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.http;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport.resolver;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.treewalk.filter;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.io;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util.sha1;version="[7.2.0,7.3.0)",
+ org.eclipse.jgit.annotations;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.api.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.archive;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.attributes;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.awtui;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.blame;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.blame.cache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.diff;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.dircache;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.events;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.fnmatch;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.gitrepo;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.hooks;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.ignore;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.ignore.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.diff;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.diffmergetool;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.fsck;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.commitgraph;version="7.4.0",
+ org.eclipse.jgit.internal.storage.dfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.io;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.memory;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.midx;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.pack;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.storage.reftable;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.connectivity;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.parser;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.internal.transport.ssh;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.junit.time;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lfs;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.logging;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.merge;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.notes;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.patch;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.pgm;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.pgm.internal;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revplot;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.file;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.storage.pack;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.submodule;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.http;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport.resolver;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.treewalk.filter;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.io;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util.sha1;version="[7.4.0,7.5.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/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java
index 23a267c8dc..47a410bdee 100644
--- a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java
+++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/ignore/CGitVsJGitRandomIgnorePatternTest.java
@@ -164,7 +164,7 @@ public class CGitVsJGitRandomIgnorePatternTest {
private String readProcessStream(InputStream processStream)
throws IOException {
try (BufferedReader stdOut = new BufferedReader(
- new InputStreamReader(processStream))) {
+ new InputStreamReader(processStream, UTF_8))) {
StringBuilder out = new StringBuilder();
String s;
diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java
new file mode 100644
index 0000000000..334e52b042
--- /dev/null
+++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/internal/storage/midx/CgitMidxCompatibilityTest.java
@@ -0,0 +1,219 @@
+/*
+ * 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.midx;
+
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDLOOKUP;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_PACKNAMES;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.storage.file.Pack;
+import org.eclipse.jgit.internal.storage.file.PackFile;
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
+import org.eclipse.jgit.util.NB;
+import org.junit.Test;
+
+public class CgitMidxCompatibilityTest extends SampleDataRepositoryTestCase {
+
+ @Test
+ public void jgitMidx_verifyByCgit()
+ throws IOException, InterruptedException {
+ byte[] jgitMidxBytes = generateJGitMidx();
+ writeMidx(jgitMidxBytes);
+ assertEquals("cgit exit code", 0, run_cgit_multipackindex_verify());
+ }
+
+ @Test
+ public void compareBasicChunkSizes()
+ throws IOException, InterruptedException {
+ // We cannot compare byte-by-byte because there are optional chunks and
+ // it is not guaranteed what cgit and jgit will generate
+ byte[] jgitMidxBytes = generateJGitMidx();
+ assertEquals("cgit exit code", 0, run_cgit_multipackindex_write());
+ byte[] cgitMidxBytes = readCgitMidx();
+
+ RawMultiPackIndex jgitMidx = new RawMultiPackIndex(jgitMidxBytes);
+ RawMultiPackIndex cgitMidx = new RawMultiPackIndex(cgitMidxBytes);
+
+ // This is a fixed sized chunk
+ assertEquals(256 * 4, cgitMidx.getChunkSize(MIDX_CHUNKID_OIDFANOUT));
+ assertArrayEquals(cgitMidx.getRawChunk(MIDX_CHUNKID_OIDFANOUT),
+ jgitMidx.getRawChunk(MIDX_CHUNKID_OIDFANOUT));
+
+ assertArrayEquals(cgitMidx.getRawChunk(MIDX_CHUNKID_OIDLOOKUP),
+ jgitMidx.getRawChunk(MIDX_CHUNKID_OIDLOOKUP));
+
+ // The spec has changed from padding packnames to a multile of four, to
+ // move the packname chunk to the end of the file.
+ // git 2.48 pads the packs names to a multiple of 4
+ // jgit puts the chunk at the end
+ byte[] cgitPacknames = trimPadding(
+ cgitMidx.getRawChunk(MIDX_CHUNKID_PACKNAMES));
+ assertArrayEquals(cgitPacknames,
+ jgitMidx.getRawChunk(MIDX_CHUNKID_PACKNAMES));
+
+ assertArrayEquals(cgitMidx.getRawChunk(MIDX_CHUNKID_OBJECTOFFSETS),
+ jgitMidx.getRawChunk(MIDX_CHUNKID_OBJECTOFFSETS));
+
+ }
+
+ @Test
+ public void jgit_loadsCgitMidx()
+ throws IOException, InterruptedException {
+ assertEquals("cgit exit code", 0, run_cgit_multipackindex_write());
+ byte[] cgitMidxBytes = readCgitMidx();
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(cgitMidxBytes));
+ assertEquals(7, midx.getPackNames().length);
+ }
+
+ private byte[] generateJGitMidx() throws IOException {
+ Map<String, PackIndex> indexes = new HashMap<>();
+ for (Pack pack : db.getObjectDatabase().getPacks()) {
+ PackFile packFile = pack.getPackFile().create(PackExt.INDEX);
+ indexes.put(packFile.getName(), pack.getIndex());
+ }
+
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, indexes);
+ return out.toByteArray();
+ }
+
+ private int run_cgit_multipackindex_write()
+ throws IOException, InterruptedException {
+ String[] command = new String[] { "git", "multi-pack-index", "write" };
+ Process proc = Runtime.getRuntime().exec(command, new String[0],
+ db.getDirectory());
+ return proc.waitFor();
+ }
+
+ private int run_cgit_multipackindex_verify()
+ throws IOException, InterruptedException {
+ String[] command = new String[] { "git", "multi-pack-index", "verify" };
+ Process proc = Runtime.getRuntime().exec(command, new String[0],
+ db.getDirectory());
+ return proc.waitFor();
+ }
+
+ private byte[] readCgitMidx() throws IOException {
+ File midx = getMIdxStandardLocation();
+ assertTrue("cgit multi-pack-index exists", midx.exists());
+ return Files.readAllBytes(midx.toPath());
+ }
+
+ private void writeMidx(byte[] midx) throws IOException {
+ File midxFile = getMIdxStandardLocation();
+ Files.write(midxFile.toPath(), midx);
+ }
+
+ private File getMIdxStandardLocation() {
+ return new File(db.getObjectDatabase().getPackDirectory(),
+ "multi-pack-index");
+ }
+
+ private byte[] trimPadding(byte[] data) {
+ // Chunk MUST have one \0, we want to remove any extra \0
+ int newEnd = data.length - 1;
+ while (newEnd - 1 >= 0 && data[newEnd - 1] == 0) {
+ newEnd--;
+ }
+
+ if (newEnd == data.length - 1) {
+ return data;
+ }
+ return Arrays.copyOfRange(data, 0, newEnd + 1);
+ }
+
+ private static class RawMultiPackIndex {
+ private final List<ChunkSegment> chunks;
+
+ private final byte[] midx;
+
+ private RawMultiPackIndex(byte[] midx) {
+ this.chunks = readChunks(midx);
+ this.midx = midx;
+ }
+
+ long getChunkSize(int chunkId) {
+ int chunkPos = findChunkPosition(chunks, chunkId);
+ return chunks.get(chunkPos + 1).offset
+ - chunks.get(chunkPos).offset;
+ }
+
+ long getOffset(int chunkId) {
+ return chunks.get(findChunkPosition(chunks, chunkId)).offset;
+ }
+
+ private long getNextOffset(int chunkId) {
+ return chunks.get(findChunkPosition(chunks, chunkId) + 1).offset;
+ }
+
+ byte[] getRawChunk(int chunkId) {
+ int start = (int) getOffset(chunkId);
+ int end = (int) getNextOffset(chunkId);
+ return Arrays.copyOfRange(midx, start, end);
+ }
+
+ private static int findChunkPosition(List<ChunkSegment> chunks,
+ int id) {
+ int chunkPos = -1;
+ for (int i = 0; i < chunks.size(); i++) {
+ if (chunks.get(i).id() == id) {
+ chunkPos = i;
+ break;
+ }
+ }
+ if (chunkPos == -1) {
+ throw new IllegalStateException("Chunk doesn't exist");
+ }
+ return chunkPos;
+ }
+
+ private List<ChunkSegment> readChunks(byte[] midx) {
+ // Read the number of "chunkOffsets" (1 byte)
+ int chunkCount = midx[6];
+ byte[] lookupBuffer = new byte[CHUNK_LOOKUP_WIDTH
+ * (chunkCount + 1)];
+ System.arraycopy(midx, 12, lookupBuffer, 0, lookupBuffer.length);
+
+ List<ChunkSegment> chunks = new ArrayList<>(chunkCount + 1);
+ for (int i = 0; i <= chunkCount; i++) {
+ // chunks[chunkCount] is just a marker, in order to record the
+ // length of the last chunk.
+ int id = NB.decodeInt32(lookupBuffer, i * 12);
+ long offset = NB.decodeInt64(lookupBuffer, i * 12 + 4);
+ chunks.add(new ChunkSegment(id, offset));
+ }
+ return chunks;
+ }
+ }
+
+ private record ChunkSegment(int id, long offset) {
+ }
+}
diff --git a/org.eclipse.jgit.test/pom.xml b/org.eclipse.jgit.test/pom.xml
index c936b09fd7..39d317a136 100644
--- a/org.eclipse.jgit.test/pom.xml
+++ b/org.eclipse.jgit.test/pom.xml
@@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.test</artifactId>
diff --git a/org.eclipse.jgit.test/tests.bzl b/org.eclipse.jgit.test/tests.bzl
index 170bf0c460..41f76d090a 100644
--- a/org.eclipse.jgit.test/tests.bzl
+++ b/org.eclipse.jgit.test/tests.bzl
@@ -1,11 +1,29 @@
+'''
+Expose each test as a bazel target
+'''
load(
"@com_googlesource_gerrit_bazlets//tools:junit.bzl",
"junit_tests",
)
-def tests(tests):
+def tests(tests, srcprefix="tst/", extra_tags=[]):
+ '''
+ Create a target each of the tests
+
+ Each target is the full push (removing srcprefix) replacing directory
+ separators with underscores.
+
+ e.g. a test under tst/a/b/c/A.test will become the target
+ //org.eclipse.jgit.tests:a_b_c_A
+
+ Args:
+ tests: a glob of tests files
+ srcprefix: prefix between org.eclipse.jgit.tests and the package
+ start
+ extra_tags: additional tags to add to the generated targets
+ '''
for src in tests:
- name = src[len("tst/"):len(src) - len(".java")].replace("/", "_")
+ name = src[len(srcprefix):len(src) - len(".java")].replace("/", "_")
labels = []
timeout = "moderate"
if name.startswith("org_eclipse_jgit_"):
@@ -20,6 +38,8 @@ def tests(tests):
if "lib" not in labels:
labels.append("lib")
+ labels.extend(extra_tags)
+
# TODO(http://eclip.se/534285): Make this test pass reliably
# and remove the flaky attribute.
flaky = src.endswith("CrissCrossMergeTest.java")
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/multi-pack-index.v1 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/multi-pack-index.v1
new file mode 100644
index 0000000000..223febeb26
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/multi-pack-index.v1
Binary files differ
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
index 1c2e995bbb..226677229c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/AddCommandTest.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com>
- * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> and others
+ * Copyright (C) 2010, 2025 Christian Halstrick <christian.halstrick@sap.com> 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
@@ -665,11 +665,13 @@ public class AddCommandTest extends RepositoryTestCase {
FileUtils.delete(file);
// is supposed to do nothing
- dc = git.add().addFilepattern("a.txt").call();
+ dc = git.add().addFilepattern("a.txt").setAll(false).call();
assertEquals(oid, dc.getEntry(0).getObjectId());
assertEquals(
"[a.txt, mode:100644, content:content]",
indexState(CONTENT));
+ git.add().addFilepattern("a.txt").call();
+ assertEquals("", indexState(CONTENT));
}
}
@@ -690,11 +692,13 @@ public class AddCommandTest extends RepositoryTestCase {
FileUtils.delete(file);
// is supposed to do nothing
- dc = git.add().addFilepattern("a.txt").call();
+ dc = git.add().addFilepattern("a.txt").setAll(false).call();
assertEquals(oid, dc.getEntry(0).getObjectId());
assertEquals(
"[a.txt, mode:100644, content:content]",
indexState(CONTENT));
+ git.add().addFilepattern("a.txt").call();
+ assertEquals("", indexState(CONTENT));
}
}
@@ -964,7 +968,7 @@ public class AddCommandTest extends RepositoryTestCase {
// file sub/b.txt is deleted
FileUtils.delete(file2);
- git.add().addFilepattern("sub").call();
+ git.add().addFilepattern("sub").setAll(false).call();
// change in sub/a.txt is staged
// deletion of sub/b.txt is not staged
// sub/c.txt is staged
@@ -973,6 +977,12 @@ public class AddCommandTest extends RepositoryTestCase {
"[sub/b.txt, mode:100644, content:content b]" +
"[sub/c.txt, mode:100644, content:content c]",
indexState(CONTENT));
+ git.add().addFilepattern("sub").call();
+ // deletion of sub/b.txt is staged
+ assertEquals(
+ "[sub/a.txt, mode:100644, content:modified content]"
+ + "[sub/c.txt, mode:100644, content:content c]",
+ indexState(CONTENT));
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java
index be3b33a9c5..3f5c5da55a 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java
@@ -34,6 +34,7 @@ import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.merge.ContentMergeStrategy;
@@ -529,10 +530,11 @@ public class CherryPickCommandTest extends RepositoryTestCase {
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
if (reason == null) {
- ReflogReader reader = db.getReflogReader(Constants.HEAD);
+ RefDatabase refDb = db.getRefDatabase();
+ ReflogReader reader = refDb.getReflogReader(Constants.HEAD);
assertTrue(reader.getLastEntry().getComment()
.startsWith("cherry-pick: "));
- reader = db.getReflogReader(db.getBranch());
+ reader = refDb.getReflogReader(db.getFullBranch());
assertTrue(reader.getLastEntry().getComment()
.startsWith("cherry-pick: "));
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java
index db5b27c2ab..661878fa07 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java
@@ -182,7 +182,8 @@ public class CloneCommandTest extends RepositoryTestCase {
private static boolean hasRefLog(Repository repo, Ref ref) {
try {
- return repo.getReflogReader(ref.getName()).getLastEntry() != null;
+ return repo.getRefDatabase().getReflogReader(ref)
+ .getLastEntry() != null;
} catch (IOException ioe) {
throw new IllegalStateException(ioe);
}
@@ -796,7 +797,7 @@ public class CloneCommandTest extends RepositoryTestCase {
assertNull(git2.getRepository().getConfig().getEnum(
BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION, "test",
- ConfigConstants.CONFIG_KEY_REBASE, null));
+ ConfigConstants.CONFIG_KEY_REBASE));
StoredConfig userConfig = SystemReader.getInstance()
.getUserConfig();
@@ -812,7 +813,6 @@ public class CloneCommandTest extends RepositoryTestCase {
addRepoToClose(git2.getRepository());
assertEquals(BranchRebaseMode.REBASE,
git2.getRepository().getConfig().getEnum(
- BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION, "test",
ConfigConstants.CONFIG_KEY_REBASE,
BranchRebaseMode.NONE));
@@ -829,7 +829,6 @@ public class CloneCommandTest extends RepositoryTestCase {
addRepoToClose(git2.getRepository());
assertEquals(BranchRebaseMode.REBASE,
git2.getRepository().getConfig().getEnum(
- BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION, "test",
ConfigConstants.CONFIG_KEY_REBASE,
BranchRebaseMode.NONE));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java
index 57e5d4958f..4e5f44e5a6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitAndLogCommandTest.java
@@ -26,6 +26,7 @@ import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -69,10 +70,11 @@ public class CommitAndLogCommandTest extends RepositoryTestCase {
l--;
}
assertEquals(l, -1);
- ReflogReader reader = db.getReflogReader(Constants.HEAD);
+ RefDatabase refDb = db.getRefDatabase();
+ ReflogReader reader = refDb.getReflogReader(Constants.HEAD);
assertTrue(
reader.getLastEntry().getComment().startsWith("commit:"));
- reader = db.getReflogReader(db.getBranch());
+ reader = refDb.getReflogReader(db.getFullBranch());
assertTrue(
reader.getLastEntry().getComment().startsWith("commit:"));
}
@@ -248,10 +250,11 @@ public class CommitAndLogCommandTest extends RepositoryTestCase {
c++;
}
assertEquals(1, c);
- ReflogReader reader = db.getReflogReader(Constants.HEAD);
+ RefDatabase refDb = db.getRefDatabase();
+ ReflogReader reader = refDb.getReflogReader(Constants.HEAD);
assertTrue(reader.getLastEntry().getComment()
.startsWith("commit (amend):"));
- reader = db.getReflogReader(db.getBranch());
+ reader = refDb.getReflogReader(db.getFullBranch());
assertTrue(reader.getLastEntry().getComment()
.startsWith("commit (amend):"));
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
index e74e234297..21cfcc4e34 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CommitCommandTest.java
@@ -19,9 +19,9 @@ import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import java.io.File;
-import java.util.Date;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.List;
-import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
@@ -435,10 +435,12 @@ public class CommitCommandTest extends RepositoryTestCase {
assertEquals(1, squashedCommit.getParentCount());
assertNull(db.readSquashCommitMsg());
- assertEquals("commit: Squashed commit of the following:", db
- .getReflogReader(Constants.HEAD).getLastEntry().getComment());
- assertEquals("commit: Squashed commit of the following:", db
- .getReflogReader(db.getBranch()).getLastEntry().getComment());
+ assertEquals("commit: Squashed commit of the following:",
+ db.getRefDatabase().getReflogReader(Constants.HEAD)
+ .getLastEntry().getComment());
+ assertEquals("commit: Squashed commit of the following:",
+ db.getRefDatabase().getReflogReader(db.getFullBranch())
+ .getLastEntry().getComment());
}
}
@@ -455,12 +457,15 @@ public class CommitCommandTest extends RepositoryTestCase {
git.commit().setMessage("c3").setAll(true)
.setReflogComment("testRl").call();
- db.getReflogReader(Constants.HEAD).getReverseEntries();
+ db.getRefDatabase().getReflogReader(Constants.HEAD)
+ .getReverseEntries();
assertEquals("testRl;commit (initial): c1;", reflogComments(
- db.getReflogReader(Constants.HEAD).getReverseEntries()));
+ db.getRefDatabase().getReflogReader(Constants.HEAD)
+ .getReverseEntries()));
assertEquals("testRl;commit (initial): c1;", reflogComments(
- db.getReflogReader(db.getBranch()).getReverseEntries()));
+ db.getRefDatabase().getReflogReader(db.getFullBranch())
+ .getReverseEntries()));
}
}
@@ -486,11 +491,11 @@ public class CommitCommandTest extends RepositoryTestCase {
writeTrashFile("file1", "file1");
git.add().addFilepattern("file1").call();
- final String authorName = "First Author";
- final String authorEmail = "author@example.org";
- final Date authorDate = new Date(1349621117000L);
+ String authorName = "First Author";
+ String authorEmail = "author@example.org";
+ Instant authorDate = Instant.ofEpochSecond(1349621117L);
PersonIdent firstAuthor = new PersonIdent(authorName, authorEmail,
- authorDate, TimeZone.getTimeZone("UTC"));
+ authorDate, ZoneOffset.UTC);
git.commit().setMessage("initial commit").setAuthor(firstAuthor).call();
RevCommit amended = git.commit().setAmend(true)
@@ -499,7 +504,8 @@ public class CommitCommandTest extends RepositoryTestCase {
PersonIdent amendedAuthor = amended.getAuthorIdent();
assertEquals(authorName, amendedAuthor.getName());
assertEquals(authorEmail, amendedAuthor.getEmailAddress());
- assertEquals(authorDate.getTime(), amendedAuthor.getWhen().getTime());
+ assertEquals(authorDate.getEpochSecond(),
+ amendedAuthor.getWhenAsInstant().getEpochSecond());
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
index ab87fa9662..060e6d3e84 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
@@ -12,6 +12,7 @@ package org.eclipse.jgit.api;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -87,6 +88,9 @@ public class DescribeCommandTest extends RepositoryTestCase {
assertEquals("alice-t1", describe(c2, "alice*"));
assertEquals("alice-t1", describe(c2, "a*", "b*", "c*"));
+ assertNotEquals("alice-t1", describeExcluding(c2, "alice*"));
+ assertNotEquals("alice-t1", describeCommand(c2).setMatch("*").setExclude("alice*").call());
+
assertEquals("bob-t2", describe(c3));
assertEquals("bob-t2-0-g44579eb", describe(c3, true, false));
assertEquals("alice-t1-1-g44579eb", describe(c3, "alice*"));
@@ -95,6 +99,15 @@ public class DescribeCommandTest extends RepositoryTestCase {
assertEquals("bob-t2", describe(c3, "?ob*"));
assertEquals("bob-t2", describe(c3, "a*", "b*", "c*"));
+ assertNotEquals("alice-t1-1-g44579eb", describeExcluding(c3, "alice*"));
+ assertNotEquals("alice-t1-1-g44579eb", describeCommand(c3).setMatch("*").setExclude("alice*").call());
+ assertNotEquals("alice-t1-1-g44579eb", describeExcluding(c3, "a??c?-t*"));
+ assertNotEquals("alice-t1-1-g44579eb", describeCommand(c3).setMatch("bob*").setExclude("a??c?-t*").call());
+ assertNotEquals("bob-t2", describeExcluding(c3, "bob*"));
+ assertNotEquals("bob-t2", describeCommand(c3).setMatch("alice*").setExclude("bob*"));
+ assertNotEquals("bob-t2", describeExcluding(c3, "?ob*"));
+ assertNotEquals("bob-t2", describeCommand(c3).setMatch("a??c?-t*").setExclude("?ob*"));
+
// the value verified with git-describe(1)
assertEquals("bob-t2-1-g3e563c5", describe(c4));
assertEquals("bob-t2-1-g3e563c5", describe(c4, true, false));
@@ -518,6 +531,15 @@ public class DescribeCommandTest extends RepositoryTestCase {
.setMatch(patterns).call();
}
+ private String describeExcluding(ObjectId c1, String... patterns) throws Exception {
+ return git.describe().setTarget(c1).setTags(describeUseAllTags)
+ .setExclude(patterns).call();
+ }
+
+ private DescribeCommand describeCommand(ObjectId c1) throws Exception {
+ return git.describe().setTarget(c1).setTags(describeUseAllTags);
+ }
+
private static void assertNameStartsWith(ObjectId c4, String prefix) {
assertTrue(c4.name(), c4.name().startsWith(prefix));
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java
index 3ec454cfc3..3731347f11 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java
@@ -92,8 +92,8 @@ public class FetchCommandTest extends RepositoryTestCase {
assertTrue(remoteRef.getName().startsWith(Constants.R_REMOTES));
assertEquals(defaultBranchSha1, remoteRef.getObjectId());
- assertNotNull(git.getRepository().getReflogReader(remoteRef.getName())
- .getLastEntry());
+ assertNotNull(git.getRepository().getRefDatabase()
+ .getReflogReader(remoteRef.getName()).getLastEntry());
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java
index f98db3497b..6090d5efbe 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GarbageCollectCommandTest.java
@@ -11,12 +11,11 @@ package org.eclipse.jgit.api;
import static org.junit.Assert.assertTrue;
-import java.util.Date;
+import java.time.Instant;
import java.util.Properties;
import org.eclipse.jgit.junit.RepositoryTestCase;
-import org.eclipse.jgit.util.GitDateParser;
-import org.eclipse.jgit.util.SystemReader;
+import org.eclipse.jgit.util.GitTimeParser;
import org.junit.Before;
import org.junit.Test;
@@ -36,9 +35,8 @@ public class GarbageCollectCommandTest extends RepositoryTestCase {
@Test
public void testGConeCommit() throws Exception {
- Date expire = GitDateParser.parse("now", null, SystemReader
- .getInstance().getLocale());
- Properties res = git.gc().setExpire(expire).call();
+ Instant expireNow = GitTimeParser.parseInstant("now");
+ Properties res = git.gc().setExpire(expireNow).call();
assertTrue(res.size() == 8);
}
@@ -52,11 +50,8 @@ public class GarbageCollectCommandTest extends RepositoryTestCase {
writeTrashFile("b.txt", "a couple of words for gc to pack more 2");
writeTrashFile("c.txt", "a couple of words for gc to pack more 3");
git.commit().setAll(true).setMessage("commit3").call();
- Properties res = git
- .gc()
- .setExpire(
- GitDateParser.parse("now", null, SystemReader
- .getInstance().getLocale())).call();
+ Instant expireNow = GitTimeParser.parseInstant("now");
+ Properties res = git.gc().setExpire(expireNow).call();
assertTrue(res.size() == 8);
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java
index 76934343da..e847e72415 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java
@@ -14,6 +14,7 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
+import java.time.Instant;
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -100,7 +101,7 @@ public class GitConstructionTest extends RepositoryTestCase {
GitAPIException {
File workTree = db.getWorkTree();
Git git = Git.open(workTree);
- git.gc().setExpire(null).call();
+ git.gc().setExpire((Instant) null).call();
git.checkout().setName(git.getRepository().resolve("HEAD^").getName())
.call();
try {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
index 917b6c3297..1ec506798c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
@@ -21,6 +21,9 @@ import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import java.io.File;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Iterator;
import java.util.regex.Pattern;
@@ -33,6 +36,7 @@ import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.lib.Sets;
@@ -45,6 +49,7 @@ import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.GitDateFormatter;
import org.eclipse.jgit.util.GitDateFormatter.Format;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
@@ -76,12 +81,12 @@ public class MergeCommandTest extends RepositoryTestCase {
assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus());
}
// no reflog entry written by merge
- assertEquals("commit (initial): initial commit",
- db
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals("commit (initial): initial commit", refDb
.getReflogReader(Constants.HEAD).getLastEntry().getComment());
- assertEquals("commit (initial): initial commit",
- db
- .getReflogReader(db.getBranch()).getLastEntry().getComment());
+ assertEquals("commit (initial): initial commit", refDb
+ .getReflogReader(db.getFullBranch()).getLastEntry()
+ .getComment());
}
@Test
@@ -96,10 +101,11 @@ public class MergeCommandTest extends RepositoryTestCase {
assertEquals(second, result.getNewHead());
}
// no reflog entry written by merge
- assertEquals("commit: second commit", db
+ assertEquals("commit: second commit", db.getRefDatabase()
.getReflogReader(Constants.HEAD).getLastEntry().getComment());
- assertEquals("commit: second commit", db
- .getReflogReader(db.getBranch()).getLastEntry().getComment());
+ assertEquals("commit: second commit", db.getRefDatabase()
+ .getReflogReader(db.getFullBranch()).getLastEntry()
+ .getComment());
}
@Test
@@ -117,10 +123,13 @@ public class MergeCommandTest extends RepositoryTestCase {
assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
assertEquals(second, result.getNewHead());
}
+ RefDatabase refDb = db.getRefDatabase();
assertEquals("merge refs/heads/master: Fast-forward",
- db.getReflogReader(Constants.HEAD).getLastEntry().getComment());
+ refDb.getReflogReader(Constants.HEAD)
+ .getLastEntry().getComment());
assertEquals("merge refs/heads/master: Fast-forward",
- db.getReflogReader(db.getBranch()).getLastEntry().getComment());
+ refDb.getReflogReader(db.getFullBranch())
+ .getLastEntry().getComment());
}
@Test
@@ -140,10 +149,12 @@ public class MergeCommandTest extends RepositoryTestCase {
result.getMergeStatus());
assertEquals(second, result.getNewHead());
}
- assertEquals("merge refs/heads/master: Fast-forward", db
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals("merge refs/heads/master: Fast-forward", refDb
.getReflogReader(Constants.HEAD).getLastEntry().getComment());
- assertEquals("merge refs/heads/master: Fast-forward", db
- .getReflogReader(db.getBranch()).getLastEntry().getComment());
+ assertEquals("merge refs/heads/master: Fast-forward", refDb
+ .getReflogReader(db.getFullBranch()).getLastEntry()
+ .getComment());
}
@Test
@@ -171,10 +182,12 @@ public class MergeCommandTest extends RepositoryTestCase {
assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
assertEquals(second, result.getNewHead());
}
- assertEquals("merge refs/heads/master: Fast-forward",
- db.getReflogReader(Constants.HEAD).getLastEntry().getComment());
- assertEquals("merge refs/heads/master: Fast-forward",
- db.getReflogReader(db.getBranch()).getLastEntry().getComment());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals("merge refs/heads/master: Fast-forward", refDb
+ .getReflogReader(Constants.HEAD).getLastEntry().getComment());
+ assertEquals("merge refs/heads/master: Fast-forward", refDb
+ .getReflogReader(db.getFullBranch()).getLastEntry()
+ .getComment());
}
@Test
@@ -229,14 +242,17 @@ public class MergeCommandTest extends RepositoryTestCase {
.include(db.exactRef(R_HEADS + MASTER)).call();
assertEquals(MergeStatus.MERGED, result.getMergeStatus());
}
+ RefDatabase refDb = db.getRefDatabase();
assertEquals(
"merge refs/heads/master: Merge made by "
+ mergeStrategy.getName() + ".",
- db.getReflogReader(Constants.HEAD).getLastEntry().getComment());
+ refDb.getReflogReader(Constants.HEAD).getLastEntry()
+ .getComment());
assertEquals(
"merge refs/heads/master: Merge made by "
+ mergeStrategy.getName() + ".",
- db.getReflogReader(db.getBranch()).getLastEntry().getComment());
+ refDb.getReflogReader(db.getFullBranch()).getLastEntry()
+ .getComment());
}
@Theory
@@ -662,14 +678,17 @@ public class MergeCommandTest extends RepositoryTestCase {
.setStrategy(MergeStrategy.RESOLVE).call();
assertEquals(MergeStatus.MERGED, result.getMergeStatus());
assertEquals("1\nb(1)\n3\n", read(new File(db.getWorkTree(), "b")));
- assertEquals("merge " + secondCommit.getId().getName()
- + ": Merge made by resolve.", db
- .getReflogReader(Constants.HEAD)
- .getLastEntry().getComment());
- assertEquals("merge " + secondCommit.getId().getName()
- + ": Merge made by resolve.", db
- .getReflogReader(db.getBranch())
- .getLastEntry().getComment());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(
+ "merge " + secondCommit.getId().getName()
+ + ": Merge made by resolve.",
+ refDb.getReflogReader(Constants.HEAD).getLastEntry()
+ .getComment());
+ assertEquals(
+ "merge " + secondCommit.getId().getName()
+ + ": Merge made by resolve.",
+ refDb.getReflogReader(db.getFullBranch()).getLastEntry()
+ .getComment());
}
}
@@ -2086,6 +2105,94 @@ public class MergeCommandTest extends RepositoryTestCase {
}
}
+ @Test
+ public void testMergeCaseInsensitiveRename() throws Exception {
+ Assume.assumeTrue(
+ "Test makes only sense on a case-insensitive file system",
+ db.isWorkTreeCaseInsensitive());
+ try (Git git = new Git(db)) {
+ writeTrashFile("a", "aaa");
+ git.add().addFilepattern("a").call();
+ RevCommit initialCommit = git.commit().setMessage("initial").call();
+ // "Rename" "a" to "A"
+ git.rm().addFilepattern("a").call();
+ writeTrashFile("A", "aaa");
+ git.add().addFilepattern("A").call();
+ RevCommit master = git.commit().setMessage("rename to A").call();
+
+ createBranch(initialCommit, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+
+ writeTrashFile("b", "bbb");
+ git.add().addFilepattern("b").call();
+ git.commit().setMessage("side").call();
+
+ // Merge master into side
+ MergeResult result = git.merge().include(master)
+ .setStrategy(MergeStrategy.RECURSIVE).call();
+ assertEquals(MergeStatus.MERGED, result.getMergeStatus());
+ assertTrue(new File(db.getWorkTree(), "A").isFile());
+ // Double check
+ boolean found = true;
+ try (DirectoryStream<Path> dir = Files
+ .newDirectoryStream(db.getWorkTree().toPath())) {
+ for (Path p : dir) {
+ found = "A".equals(p.getFileName().toString());
+ if (found) {
+ break;
+ }
+ }
+ }
+ assertTrue(found);
+ }
+ }
+
+ @Test
+ public void testMergeCaseInsensitiveRenameConflict() throws Exception {
+ Assume.assumeTrue(
+ "Test makes only sense on a case-insensitive file system",
+ db.isWorkTreeCaseInsensitive());
+ try (Git git = new Git(db)) {
+ writeTrashFile("a", "aaa");
+ git.add().addFilepattern("a").call();
+ RevCommit initialCommit = git.commit().setMessage("initial").call();
+ // "Rename" "a" to "A" and change it
+ git.rm().addFilepattern("a").call();
+ writeTrashFile("A", "yyy");
+ git.add().addFilepattern("A").call();
+ RevCommit master = git.commit().setMessage("rename to A").call();
+
+ createBranch(initialCommit, "refs/heads/side");
+ checkoutBranch("refs/heads/side");
+
+ writeTrashFile("a", "xxx");
+ git.add().addFilepattern("a").call();
+ git.commit().setMessage("side").call();
+
+ // Merge master into side
+ MergeResult result = git.merge().include(master)
+ .setStrategy(MergeStrategy.RECURSIVE).call();
+ assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
+ File a = new File(db.getWorkTree(), "A");
+ assertTrue(a.isFile());
+ // Double check
+ boolean found = true;
+ try (DirectoryStream<Path> dir = Files
+ .newDirectoryStream(db.getWorkTree().toPath())) {
+ for (Path p : dir) {
+ found = "A".equals(p.getFileName().toString());
+ if (found) {
+ break;
+ }
+ }
+ }
+ assertTrue(found);
+ assertEquals(1, result.getConflicts().size());
+ assertTrue(result.getConflicts().containsKey("a"));
+ checkFile(a, "yyy");
+ }
+ }
+
private static void setExecutable(Git git, String path, boolean executable) {
FS.DETECTED.setExecute(
new File(git.getRepository().getWorkTree(), path), executable);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java
index 6d5e45c98f..695681de8d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PullCommandTest.java
@@ -480,7 +480,7 @@ public class PullCommandTest extends RepositoryTestCase {
@Test
/** without config it should merge */
public void testPullWithoutConfig() throws Exception {
- Callable<PullResult> setup = target.pull()::call;
+ Callable<PullResult> setup = target.pull();
doTestPullWithRebase(setup, TestPullMode.MERGE);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
index 70e990dedf..d1696d62a8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/PushCommandTest.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.PrintStream;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
+import java.time.Instant;
import java.util.Properties;
import org.eclipse.jgit.api.errors.DetachedHeadException;
@@ -1146,7 +1147,7 @@ public class PushCommandTest extends RepositoryTestCase {
RevCommit commit2 = git2.commit().setMessage("adding a").call();
// run a gc to ensure we have a bitmap index
- Properties res = git1.gc().setExpire(null).call();
+ Properties res = git1.gc().setExpire((Instant) null).call();
assertEquals(8, res.size());
// create another commit so we have something else to push
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
index 02e3a2e06f..4c8cf06a67 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RebaseCommandTest.java
@@ -24,6 +24,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -55,6 +57,7 @@ import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RebaseTodoLine;
import org.eclipse.jgit.lib.RebaseTodoLine.Action;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.RepositoryState;
@@ -131,11 +134,12 @@ public class RebaseCommandTest extends RepositoryTestCase {
checkFile(file2, "file2");
assertEquals(Status.FAST_FORWARD, res.getStatus());
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals("rebase finished: returning to refs/heads/topic", headLog
.get(0).getComment());
@@ -177,11 +181,12 @@ public class RebaseCommandTest extends RepositoryTestCase {
checkFile(file2, "file2 new content");
assertEquals(Status.FAST_FORWARD, res.getStatus());
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals("rebase finished: returning to refs/heads/topic", headLog
.get(0).getComment());
@@ -445,13 +450,14 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(a, rw.next());
}
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> sideLog = db.getReflogReader("refs/heads/side")
+ List<ReflogEntry> sideLog = refDb.getReflogReader("refs/heads/side")
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals("rebase finished: returning to refs/heads/topic", headLog
.get(0).getComment());
@@ -766,9 +772,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult result = git.rebase().setUpstream(parent).call();
assertEquals(Status.UP_TO_DATE, result.getStatus());
- assertEquals(2, db.getReflogReader(Constants.HEAD).getReverseEntries()
- .size());
- assertEquals(2, db.getReflogReader("refs/heads/master")
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(2, refDb.getReflogReader(Constants.HEAD)
+ .getReverseEntries().size());
+ assertEquals(2, refDb.getReflogReader("refs/heads/master")
.getReverseEntries().size());
}
@@ -784,9 +791,10 @@ public class RebaseCommandTest extends RepositoryTestCase {
RebaseResult res = git.rebase().setUpstream(first).call();
assertEquals(Status.UP_TO_DATE, res.getStatus());
- assertEquals(1, db.getReflogReader(Constants.HEAD).getReverseEntries()
- .size());
- assertEquals(1, db.getReflogReader("refs/heads/master")
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(1, refDb.getReflogReader(Constants.HEAD)
+ .getReverseEntries().size());
+ assertEquals(1, refDb.getReflogReader("refs/heads/master")
.getReverseEntries().size());
}
@@ -844,11 +852,12 @@ public class RebaseCommandTest extends RepositoryTestCase {
db.resolve(Constants.HEAD)).getParent(0));
}
assertEquals(origHead, db.readOrigHead());
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> headLog = refDb.getReflogReader(Constants.HEAD)
.getReverseEntries();
- List<ReflogEntry> topicLog = db.getReflogReader("refs/heads/topic")
+ List<ReflogEntry> topicLog = refDb.getReflogReader("refs/heads/topic")
.getReverseEntries();
- List<ReflogEntry> masterLog = db.getReflogReader("refs/heads/master")
+ List<ReflogEntry> masterLog = refDb.getReflogReader("refs/heads/master")
.getReverseEntries();
assertEquals(2, masterLog.size());
assertEquals(3, topicLog.size());
@@ -896,8 +905,8 @@ public class RebaseCommandTest extends RepositoryTestCase {
db.resolve(Constants.HEAD)).getParent(0));
}
- List<ReflogEntry> headLog = db.getReflogReader(Constants.HEAD)
- .getReverseEntries();
+ List<ReflogEntry> headLog = db.getRefDatabase()
+ .getReflogReader(Constants.HEAD).getReverseEntries();
assertEquals(8, headLog.size());
assertEquals("rebase: change file1 in topic", headLog.get(0)
.getComment());
@@ -1603,7 +1612,7 @@ public class RebaseCommandTest extends RepositoryTestCase {
public void testAuthorScriptConverter() throws Exception {
// -1 h timezone offset
PersonIdent ident = new PersonIdent("Author name", "a.mail@some.com",
- 123456789123L, -60);
+ Instant.ofEpochMilli(123456789123L), ZoneOffset.ofHours(-1));
String convertedAuthor = git.rebase().toAuthorScript(ident);
String[] lines = convertedAuthor.split("\n");
assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]);
@@ -1615,12 +1624,14 @@ public class RebaseCommandTest extends RepositoryTestCase {
assertEquals(ident.getName(), parsedIdent.getName());
assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress());
// this is rounded to the last second
- assertEquals(123456789000L, parsedIdent.getWhen().getTime());
- assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset());
+ assertEquals(123456789000L,
+ parsedIdent.getWhenAsInstant().toEpochMilli());
+ assertEquals(ident.getZoneId(), parsedIdent.getZoneId());
// + 9.5h timezone offset
ident = new PersonIdent("Author name", "a.mail@some.com",
- 123456789123L, +570);
+ Instant.ofEpochMilli(123456789123L),
+ ZoneOffset.ofHoursMinutes(9, 30));
convertedAuthor = git.rebase().toAuthorScript(ident);
lines = convertedAuthor.split("\n");
assertEquals("GIT_AUTHOR_NAME='Author name'", lines[0]);
@@ -1631,8 +1642,9 @@ public class RebaseCommandTest extends RepositoryTestCase {
convertedAuthor.getBytes(UTF_8));
assertEquals(ident.getName(), parsedIdent.getName());
assertEquals(ident.getEmailAddress(), parsedIdent.getEmailAddress());
- assertEquals(123456789000L, parsedIdent.getWhen().getTime());
- assertEquals(ident.getTimeZoneOffset(), parsedIdent.getTimeZoneOffset());
+ assertEquals(123456789000L,
+ parsedIdent.getWhenAsInstant().toEpochMilli());
+ assertEquals(ident.getZoneId(), parsedIdent.getZoneId());
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java
index 534ebd9c61..add5886c2d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RenameBranchCommandTest.java
@@ -118,23 +118,21 @@ public class RenameBranchCommandTest extends RepositoryTestCase {
String branch = "b1";
assertEquals(BranchRebaseMode.REBASE,
- config.getEnum(BranchRebaseMode.values(),
- ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER,
- ConfigConstants.CONFIG_KEY_REBASE,
+ config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION,
+ Constants.MASTER, ConfigConstants.CONFIG_KEY_REBASE,
BranchRebaseMode.NONE));
assertNull(config.getEnum(BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION, branch,
- ConfigConstants.CONFIG_KEY_REBASE, null));
+ ConfigConstants.CONFIG_KEY_REBASE));
assertNotNull(git.branchRename().setNewName(branch).call());
config = git.getRepository().getConfig();
assertNull(config.getEnum(BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER,
- ConfigConstants.CONFIG_KEY_REBASE, null));
+ ConfigConstants.CONFIG_KEY_REBASE));
assertEquals(BranchRebaseMode.REBASE,
- config.getEnum(BranchRebaseMode.values(),
- ConfigConstants.CONFIG_BRANCH_SECTION, branch,
+ config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, branch,
ConfigConstants.CONFIG_KEY_REBASE,
BranchRebaseMode.NONE));
}
@@ -170,13 +168,12 @@ public class RenameBranchCommandTest extends RepositoryTestCase {
String branch = "b1";
assertEquals(BranchRebaseMode.REBASE,
- config.getEnum(BranchRebaseMode.values(),
- ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER,
- ConfigConstants.CONFIG_KEY_REBASE,
+ config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION,
+ Constants.MASTER, ConfigConstants.CONFIG_KEY_REBASE,
BranchRebaseMode.NONE));
assertNull(config.getEnum(BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION, branch,
- ConfigConstants.CONFIG_KEY_REBASE, null));
+ ConfigConstants.CONFIG_KEY_REBASE));
assertTrue(config.getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION,
Constants.MASTER, ConfigConstants.CONFIG_KEY_MERGE, true));
assertFalse(config.getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION,
@@ -187,10 +184,9 @@ public class RenameBranchCommandTest extends RepositoryTestCase {
config = git.getRepository().getConfig();
assertNull(config.getEnum(BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION, Constants.MASTER,
- ConfigConstants.CONFIG_KEY_REBASE, null));
+ ConfigConstants.CONFIG_KEY_REBASE));
assertEquals(BranchRebaseMode.REBASE,
- config.getEnum(BranchRebaseMode.values(),
- ConfigConstants.CONFIG_BRANCH_SECTION, branch,
+ config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, branch,
ConfigConstants.CONFIG_KEY_REBASE,
BranchRebaseMode.NONE));
assertFalse(config.getBoolean(ConfigConstants.CONFIG_BRANCH_SECTION,
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
index 8a479a0ca0..99873e1be1 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/ResetCommandTest.java
@@ -36,11 +36,13 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FileUtils;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Test;
public class ResetCommandTest extends RepositoryTestCase {
@@ -554,46 +556,73 @@ public class ResetCommandTest extends RepositoryTestCase {
assertNull(db.resolve(Constants.HEAD));
}
+ @Test
+ public void testHardResetFileMode() throws Exception {
+ Assume.assumeTrue("Test must be able to set executable bit",
+ db.getFS().supportsExecute());
+ git = new Git(db);
+ File a = writeTrashFile("a.txt", "aaa");
+ File b = writeTrashFile("b.txt", "bbb");
+ db.getFS().setExecute(b, true);
+ assertFalse(db.getFS().canExecute(a));
+ assertTrue(db.getFS().canExecute(b));
+ git.add().addFilepattern("a.txt").addFilepattern("b.txt").call();
+ RevCommit commit = git.commit().setMessage("files created").call();
+ db.getFS().setExecute(a, true);
+ db.getFS().setExecute(b, false);
+ assertTrue(db.getFS().canExecute(a));
+ assertFalse(db.getFS().canExecute(b));
+ git.add().addFilepattern("a.txt").addFilepattern("b.txt").call();
+ git.commit().setMessage("change exe bits").call();
+ Ref ref = git.reset().setRef(commit.getName()).setMode(HARD).call();
+ assertSameAsHead(ref);
+ assertEquals(commit.getId(), ref.getObjectId());
+ assertFalse(db.getFS().canExecute(a));
+ assertTrue(db.getFS().canExecute(b));
+ }
+
private void assertReflog(ObjectId prevHead, ObjectId head)
throws IOException {
// Check the reflog for HEAD
- String actualHeadMessage = db.getReflogReader(Constants.HEAD)
+ RefDatabase refDb = db.getRefDatabase();
+ String actualHeadMessage = refDb.getReflogReader(Constants.HEAD)
.getLastEntry().getComment();
String expectedHeadMessage = head.getName() + ": updating HEAD";
assertEquals(expectedHeadMessage, actualHeadMessage);
- assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
+ assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD)
.getLastEntry().getNewId().getName());
- assertEquals(prevHead.getName(), db.getReflogReader(Constants.HEAD)
+ assertEquals(prevHead.getName(), refDb.getReflogReader(Constants.HEAD)
.getLastEntry().getOldId().getName());
// The reflog for master contains the same as the one for HEAD
- String actualMasterMessage = db.getReflogReader("refs/heads/master")
+ String actualMasterMessage = refDb.getReflogReader("refs/heads/master")
.getLastEntry().getComment();
String expectedMasterMessage = head.getName() + ": updating HEAD"; // yes!
assertEquals(expectedMasterMessage, actualMasterMessage);
- assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
+ assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD)
.getLastEntry().getNewId().getName());
- assertEquals(prevHead.getName(), db
- .getReflogReader("refs/heads/master").getLastEntry().getOldId()
- .getName());
+ assertEquals(prevHead.getName(),
+ refDb.getReflogReader("refs/heads/master").getLastEntry()
+ .getOldId().getName());
}
private void assertReflogDisabled(ObjectId head)
throws IOException {
+ RefDatabase refDb = db.getRefDatabase();
// Check the reflog for HEAD
- String actualHeadMessage = db.getReflogReader(Constants.HEAD)
+ String actualHeadMessage = refDb.getReflogReader(Constants.HEAD)
.getLastEntry().getComment();
String expectedHeadMessage = "commit: adding a.txt and dir/b.txt";
assertEquals(expectedHeadMessage, actualHeadMessage);
- assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
+ assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD)
.getLastEntry().getOldId().getName());
// The reflog for master contains the same as the one for HEAD
- String actualMasterMessage = db.getReflogReader("refs/heads/master")
+ String actualMasterMessage = refDb.getReflogReader("refs/heads/master")
.getLastEntry().getComment();
String expectedMasterMessage = "commit: adding a.txt and dir/b.txt";
assertEquals(expectedMasterMessage, actualMasterMessage);
- assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
+ assertEquals(head.getName(), refDb.getReflogReader(Constants.HEAD)
.getLastEntry().getOldId().getName());
}
/**
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
index afd6708d21..89fdb32220 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/RevertCommandTest.java
@@ -29,6 +29,7 @@ import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
@@ -87,10 +88,11 @@ public class RevertCommandTest extends RepositoryTestCase {
assertEquals("create a", history.next().getFullMessage());
assertFalse(history.hasNext());
- ReflogReader reader = db.getReflogReader(Constants.HEAD);
+ RefDatabase refDb = db.getRefDatabase();
+ ReflogReader reader = refDb.getReflogReader(Constants.HEAD);
assertTrue(reader.getLastEntry().getComment()
.startsWith("revert: Revert \""));
- reader = db.getReflogReader(db.getBranch());
+ reader = refDb.getReflogReader(db.getFullBranch());
assertTrue(reader.getLastEntry().getComment()
.startsWith("revert: Revert \""));
}
@@ -170,10 +172,11 @@ public class RevertCommandTest extends RepositoryTestCase {
assertEquals("add first", history.next().getFullMessage());
assertFalse(history.hasNext());
- ReflogReader reader = db.getReflogReader(Constants.HEAD);
+ RefDatabase refDb = db.getRefDatabase();
+ ReflogReader reader = refDb.getReflogReader(Constants.HEAD);
assertTrue(reader.getLastEntry().getComment()
.startsWith("revert: Revert \""));
- reader = db.getReflogReader(db.getBranch());
+ reader = refDb.getReflogReader(db.getFullBranch());
assertTrue(reader.getLastEntry().getComment()
.startsWith("revert: Revert \""));
}
@@ -223,10 +226,11 @@ public class RevertCommandTest extends RepositoryTestCase {
assertEquals("add first", history.next().getFullMessage());
assertFalse(history.hasNext());
- ReflogReader reader = db.getReflogReader(Constants.HEAD);
+ RefDatabase refDb = db.getRefDatabase();
+ ReflogReader reader = refDb.getReflogReader(Constants.HEAD);
assertTrue(reader.getLastEntry().getComment()
.startsWith("revert: Revert \""));
- reader = db.getReflogReader(db.getBranch());
+ reader = refDb.getReflogReader(db.getFullBranch());
assertTrue(reader.getLastEntry().getComment()
.startsWith("revert: Revert \""));
}
@@ -431,12 +435,13 @@ public class RevertCommandTest extends RepositoryTestCase {
assertEquals(RepositoryState.SAFE, db.getRepositoryState());
if (reason == null) {
- ReflogReader reader = db.getReflogReader(Constants.HEAD);
- assertTrue(reader.getLastEntry().getComment()
- .startsWith("revert: "));
- reader = db.getReflogReader(db.getBranch());
- assertTrue(reader.getLastEntry().getComment()
- .startsWith("revert: "));
+ RefDatabase refDb = db.getRefDatabase();
+ ReflogReader reader = refDb.getReflogReader(Constants.HEAD);
+ assertTrue(
+ reader.getLastEntry().getComment().startsWith("revert: "));
+ reader = refDb.getReflogReader(db.getFullBranch());
+ assertTrue(
+ reader.getLastEntry().getComment().startsWith("revert: "));
}
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java
index 5d0ab05174..18cd21a5d7 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashCreateCommandTest.java
@@ -409,8 +409,8 @@ public class StashCreateCommandTest extends RepositoryTestCase {
assertEquals("content", read(committedFile));
validateStashedCommit(stashed);
- ReflogReader reader = git.getRepository().getReflogReader(
- Constants.R_STASH);
+ ReflogReader reader = git.getRepository().getRefDatabase()
+ .getReflogReader(Constants.R_STASH);
ReflogEntry entry = reader.getLastEntry();
assertNotNull(entry);
assertEquals(ObjectId.zeroId(), entry.getOldId());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java
index c81731d746..d937579283 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/StashDropCommandTest.java
@@ -92,8 +92,8 @@ public class StashDropCommandTest extends RepositoryTestCase {
stashRef = git.getRepository().exactRef(Constants.R_STASH);
assertNull(stashRef);
- ReflogReader reader = git.getRepository().getReflogReader(
- Constants.R_STASH);
+ ReflogReader reader = git.getRepository().getRefDatabase()
+ .getReflogReader(Constants.R_STASH);
assertNull(reader);
}
@@ -120,8 +120,8 @@ public class StashDropCommandTest extends RepositoryTestCase {
assertNull(git.stashDrop().setAll(true).call());
assertNull(git.getRepository().exactRef(Constants.R_STASH));
- ReflogReader reader = git.getRepository().getReflogReader(
- Constants.R_STASH);
+ ReflogReader reader = git.getRepository().getRefDatabase()
+ .getReflogReader(Constants.R_STASH);
assertNull(reader);
}
@@ -150,8 +150,8 @@ public class StashDropCommandTest extends RepositoryTestCase {
assertNotNull(stashRef);
assertEquals(firstStash, stashRef.getObjectId());
- ReflogReader reader = git.getRepository().getReflogReader(
- Constants.R_STASH);
+ ReflogReader reader = git.getRepository().getRefDatabase()
+ .getReflogReader(Constants.R_STASH);
List<ReflogEntry> entries = reader.getReverseEntries();
assertEquals(1, entries.size());
assertEquals(ObjectId.zeroId(), entries.get(0).getOldId());
@@ -192,8 +192,8 @@ public class StashDropCommandTest extends RepositoryTestCase {
assertNotNull(stashRef);
assertEquals(thirdStash, stashRef.getObjectId());
- ReflogReader reader = git.getRepository().getReflogReader(
- Constants.R_STASH);
+ ReflogReader reader = git.getRepository().getRefDatabase()
+ .getReflogReader(Constants.R_STASH);
List<ReflogEntry> entries = reader.getReverseEntries();
assertEquals(2, entries.size());
assertEquals(ObjectId.zeroId(), entries.get(1).getOldId());
@@ -250,8 +250,8 @@ public class StashDropCommandTest extends RepositoryTestCase {
assertNotNull(stashRef);
assertEquals(thirdStash, stashRef.getObjectId());
- ReflogReader reader = git.getRepository().getReflogReader(
- Constants.R_STASH);
+ ReflogReader reader = git.getRepository().getRefDatabase()
+ .getReflogReader(Constants.R_STASH);
List<ReflogEntry> entries = reader.getReverseEntries();
assertEquals(2, entries.size());
assertEquals(ObjectId.zeroId(), entries.get(1).getOldId());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java
index f47f447375..c2c06b2477 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/blame/BlameGeneratorTest.java
@@ -23,20 +23,22 @@ import org.junit.Test;
/** Unit tests of {@link BlameGenerator}. */
public class BlameGeneratorTest extends RepositoryTestCase {
+ private static final String FILE = "file.txt";
+
@Test
public void testBoundLineDelete() throws Exception {
try (Git git = new Git(db)) {
String[] content1 = new String[] { "first", "second" };
- writeTrashFile("file.txt", join(content1));
- git.add().addFilepattern("file.txt").call();
+ writeTrashFile(FILE, join(content1));
+ git.add().addFilepattern(FILE).call();
RevCommit c1 = git.commit().setMessage("create file").call();
String[] content2 = new String[] { "third", "first", "second" };
- writeTrashFile("file.txt", join(content2));
- git.add().addFilepattern("file.txt").call();
+ writeTrashFile(FILE, join(content2));
+ git.add().addFilepattern(FILE).call();
RevCommit c2 = git.commit().setMessage("create file").call();
- try (BlameGenerator generator = new BlameGenerator(db, "file.txt")) {
+ try (BlameGenerator generator = new BlameGenerator(db, FILE)) {
generator.push(null, db.resolve(Constants.HEAD));
assertEquals(3, generator.getResultContents().size());
@@ -47,7 +49,7 @@ public class BlameGeneratorTest extends RepositoryTestCase {
assertEquals(1, generator.getResultEnd());
assertEquals(0, generator.getSourceStart());
assertEquals(1, generator.getSourceEnd());
- assertEquals("file.txt", generator.getSourcePath());
+ assertEquals(FILE, generator.getSourcePath());
assertTrue(generator.next());
assertEquals(c1, generator.getSourceCommit());
@@ -56,7 +58,7 @@ public class BlameGeneratorTest extends RepositoryTestCase {
assertEquals(3, generator.getResultEnd());
assertEquals(0, generator.getSourceStart());
assertEquals(2, generator.getSourceEnd());
- assertEquals("file.txt", generator.getSourcePath());
+ assertEquals(FILE, generator.getSourcePath());
assertFalse(generator.next());
}
@@ -87,7 +89,8 @@ public class BlameGeneratorTest extends RepositoryTestCase {
git.add().addFilepattern(FILENAME_2).call();
RevCommit c2 = git.commit().setMessage("change file2").call();
- try (BlameGenerator generator = new BlameGenerator(db, FILENAME_2)) {
+ try (BlameGenerator generator = new BlameGenerator(db,
+ FILENAME_2)) {
generator.push(null, db.resolve(Constants.HEAD));
assertEquals(3, generator.getResultContents().size());
@@ -113,7 +116,8 @@ public class BlameGeneratorTest extends RepositoryTestCase {
}
// and test again with other BlameGenerator API:
- try (BlameGenerator generator = new BlameGenerator(db, FILENAME_2)) {
+ try (BlameGenerator generator = new BlameGenerator(db,
+ FILENAME_2)) {
generator.push(null, db.resolve(Constants.HEAD));
BlameResult result = generator.computeBlameResult();
@@ -136,21 +140,21 @@ public class BlameGeneratorTest extends RepositoryTestCase {
try (Git git = new Git(db)) {
String[] content1 = new String[] { "first", "second", "third" };
- writeTrashFile("file.txt", join(content1));
- git.add().addFilepattern("file.txt").call();
+ writeTrashFile(FILE, join(content1));
+ git.add().addFilepattern(FILE).call();
git.commit().setMessage("create file").call();
String[] content2 = new String[] { "" };
- writeTrashFile("file.txt", join(content2));
- git.add().addFilepattern("file.txt").call();
+ writeTrashFile(FILE, join(content2));
+ git.add().addFilepattern(FILE).call();
git.commit().setMessage("create file").call();
- writeTrashFile("file.txt", join(content1));
- git.add().addFilepattern("file.txt").call();
+ writeTrashFile(FILE, join(content1));
+ git.add().addFilepattern(FILE).call();
RevCommit c3 = git.commit().setMessage("create file").call();
- try (BlameGenerator generator = new BlameGenerator(db, "file.txt")) {
+ try (BlameGenerator generator = new BlameGenerator(db, FILE)) {
generator.push(null, db.resolve(Constants.HEAD));
assertEquals(3, generator.getResultContents().size());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java
index f23469eda0..35b953320e 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeDirCacheIteratorTest.java
@@ -26,6 +26,7 @@ import org.eclipse.jgit.attributes.Attribute.State;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.junit.Before;
import org.junit.Test;
@@ -230,10 +231,10 @@ public class AttributesNodeDirCacheIteratorTest extends RepositoryTestCase {
else {
Attributes entryAttributes = new Attributes();
- new AttributesHandler(walk).mergeAttributes(attributesNode,
- pathName,
- false,
- entryAttributes);
+ new AttributesHandler(walk,
+ () -> walk.getTree(CanonicalTreeParser.class))
+ .mergeAttributes(attributesNode, pathName, false,
+ entryAttributes);
if (nodeAttrs != null && !nodeAttrs.isEmpty()) {
for (Attribute attribute : nodeAttrs) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java
index 1fcfbaf0fa..dbbcb75da9 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeTest.java
@@ -20,6 +20,7 @@ import java.io.InputStream;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.junit.After;
import org.junit.Test;
@@ -156,8 +157,9 @@ public class AttributesNodeTest {
private void assertAttribute(String path, AttributesNode node,
Attributes attrs) throws IOException {
Attributes attributes = new Attributes();
- new AttributesHandler(DUMMY_WALK).mergeAttributes(node, path, false,
- attributes);
+ new AttributesHandler(DUMMY_WALK,
+ () -> DUMMY_WALK.getTree(CanonicalTreeParser.class))
+ .mergeAttributes(node, path, false, attributes);
assertEquals(attrs, attributes);
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java
index 7b573e122e..c6c91386a2 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/attributes/AttributesNodeWorkingTreeIteratorTest.java
@@ -26,6 +26,7 @@ import org.eclipse.jgit.attributes.Attribute.State;
import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
@@ -194,9 +195,10 @@ public class AttributesNodeWorkingTreeIteratorTest extends RepositoryTestCase {
else {
Attributes entryAttributes = new Attributes();
- new AttributesHandler(walk).mergeAttributes(attributesNode,
- pathName, false,
- entryAttributes);
+ new AttributesHandler(walk,
+ () -> walk.getTree(CanonicalTreeParser.class))
+ .mergeAttributes(attributesNode, pathName, false,
+ entryAttributes);
if (nodeAttrs != null && !nodeAttrs.isEmpty()) {
for (Attribute attribute : nodeAttrs) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameGeneratorCacheTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameGeneratorCacheTest.java
new file mode 100644
index 0000000000..3e4ac1f993
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameGeneratorCacheTest.java
@@ -0,0 +1,552 @@
+/*
+ * 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.blame;
+
+import static java.lang.String.join;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.blame.cache.BlameCache;
+import org.eclipse.jgit.blame.cache.CacheRegion;
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+public class BlameGeneratorCacheTest extends RepositoryTestCase {
+ private static final String FILE = "file.txt";
+
+ /**
+ * Simple history:
+ *
+ * <pre>
+ * C1 C2 C3 C4 C4 blame
+ * lines ----------------------------------
+ * L1 | C1 C1 C1 C1 C1
+ * L2 | C1 C1 *C3 *C4 C4
+ * L3 | C1 C1 *C3 C3 C3
+ * L4 | *C2 C2 *C4 C4
+ * </pre>
+ *
+ * @throws Exception
+ * any error
+ */
+ @Test
+ public void blame_simple_correctRegions() throws Exception {
+ RevCommit c1, c2, c3, c4;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = commit(r, lines("L1C1", "L2C1", "L3C1"));
+ c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1);
+ c3 = commit(r, lines("L1C1", "L2C3", "L3C3", "L4C2"), c2);
+ c4 = commit(r, lines("L1C1", "L2C4", "L3C3", "L4C4"), c3);
+ }
+
+ List<EmittedRegion> expectedRegions = Arrays.asList(
+ new EmittedRegion(c1, 0, 1),
+ new EmittedRegion(c4, 1, 2),
+ new EmittedRegion(c3, 2, 3),
+ new EmittedRegion(c4, 3, 4));
+
+ assertRegions(c4, null, expectedRegions, 4);
+ assertRegions(c4, emptyCache(), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c4), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c3), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c2), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c1), expectedRegions, 4);
+ }
+
+ @Test
+ public void blame_simple_cacheUsage() throws Exception {
+ RevCommit c1, c2, c3, c4;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = commit(r, lines("L1C1", "L2C1", "L3C1"));
+ c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1);
+ c3 = commit(r, lines("L1C1", "L2C3", "L3C3", "L4C2"), c2);
+ c4 = commit(r, lines("L1C1", "L2C4", "L3C3", "L4C4"), c3);
+ }
+
+ assertCacheUsage(c4, null, false, 4);
+ assertCacheUsage(c4, emptyCache(), false, 4);
+ assertCacheUsage(c4, blameAndCache(c4), true, 1);
+ assertCacheUsage(c4, blameAndCache(c3), true, 2);
+ assertCacheUsage(c4, blameAndCache(c2), true, 3);
+ // Cache not needed because c1 doesn't have parents
+ assertCacheUsage(c4, blameAndCache(c1), false, 4);
+ }
+
+ @Test
+ public void blame_simple_createdMidHistory_correctRegions() throws Exception {
+ String c1Content = lines("L1C1", "L2C1", "L3C1");
+ String c2Content = lines("L1C1", "L2C1", "L3C1", "L4C2");
+ String c3Content = lines("L1C1", "L2C3", "L3C3", "L4C2");
+ String c4Content = lines("L1C1", "L2C4", "L3C3", "L4C4");
+
+ RevCommit c0, c1, c2, c3, c4;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c0 = r.commit().add("otherfile", "content").create();
+ c1 = r.commit().parent(c0).add(FILE, c1Content).create();
+ c2 = r.commit().parent(c1).add(FILE, c2Content).create();
+ c3 = r.commit().parent(c2).add(FILE, c3Content).create();
+ c4 = r.commit().parent(c3).add(FILE, c4Content).create();
+ }
+
+ List<EmittedRegion> expectedRegions = Arrays.asList(
+ new EmittedRegion(c1, 0, 1),
+ new EmittedRegion(c4, 1, 2),
+ new EmittedRegion(c3, 2, 3),
+ new EmittedRegion(c4, 3, 4));
+
+ assertRegions(c4, null, expectedRegions, 4);
+ assertRegions(c4, emptyCache(), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c4, FILE), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c3, FILE), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c2, FILE), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c1, FILE), expectedRegions, 4);
+ assertRegions(c4, blameAndCache(c0, FILE), expectedRegions, 4);
+ }
+
+ @Test
+ public void blame_simple_createdMidHistory_cacheUsage() throws Exception {
+ String c1Content = lines("L1C1", "L2C1", "L3C1");
+ String c2Content = lines("L1C1", "L2C1", "L3C1", "L4C2");
+ String c3Content = lines("L1C1", "L2C3", "L3C3", "L4C2");
+ String c4Content = lines("L1C1", "L2C4", "L3C3", "L4C4");
+
+ RevCommit c0, c1, c2, c3, c4;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c0 = r.commit().add("otherfile", "content").create();
+ c1 = r.commit().parent(c0).add(FILE, c1Content).create();
+ c2 = r.commit().parent(c1).add(FILE, c2Content).create();
+ c3 = r.commit().parent(c2).add(FILE, c3Content).create();
+ c4 = r.commit().parent(c3).add(FILE, c4Content).create();
+ }
+
+ assertCacheUsage(c4, null, false, 4);
+ assertCacheUsage(c4, emptyCache(), false, 4);
+ assertCacheUsage(c4, blameAndCache(c4, FILE), true, 1);
+ assertCacheUsage(c4, blameAndCache(c3, FILE), true, 2);
+ assertCacheUsage(c4, blameAndCache(c2, FILE), true, 3);
+ // Cache not needed because c1 created the file
+ assertCacheUsage(c4, blameAndCache(c1, FILE), false, 4);
+ }
+
+ /**
+ * Overwrite:
+ *
+ * <pre>
+ * C1 C2 C3 C3 blame
+ * lines ----------------------------------
+ * L1 | C1 C1 *C3 C3
+ * L2 | C1 C1 *C3 C3
+ * L3 | C1 C1 *C3 C3
+ * L4 | *C2
+ * </pre>
+ *
+ * @throws Exception
+ * any error
+ */
+ @Test
+ public void blame_overwrite_correctRegions() throws Exception {
+ RevCommit c1, c2, c3;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = commit(r, lines("L1C1", "L2C1", "L3C1"));
+ c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1);
+ c3 = commit(r, lines("L1C3", "L2C3", "L3C3"), c2);
+ }
+
+ List<EmittedRegion> expectedRegions = Arrays.asList(
+ new EmittedRegion(c3, 0, 3));
+
+ assertRegions(c3, null, expectedRegions, 3);
+ assertRegions(c3, emptyCache(), expectedRegions, 3);
+ assertRegions(c3, blameAndCache(c3), expectedRegions, 3);
+ assertRegions(c3, blameAndCache(c2), expectedRegions, 3);
+ assertRegions(c3, blameAndCache(c1), expectedRegions, 3);
+ }
+
+ @Test
+ public void blame_overwrite_cacheUsage() throws Exception {
+ RevCommit c1, c2, c3;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = commit(r, lines("L1C1", "L2C1", "L3C1"));
+ c2 = commit(r, lines("L1C1", "L2C1", "L3C1", "L4C2"), c1);
+ c3 = commit(r, lines("L1C3", "L2C3", "L3C3"), c2);
+ }
+
+ assertCacheUsage(c3, null, false, 1);
+ assertCacheUsage(c3, emptyCache(), false, 1);
+ assertCacheUsage(c3, blameAndCache(c3), true, 1);
+ assertCacheUsage(c3, blameAndCache(c2), false, 1);
+ assertCacheUsage(c3, blameAndCache(c1), false, 1);
+ }
+
+ /**
+ * Merge:
+ *
+ * <pre>
+ * root
+ * ----
+ * L1 -
+ * L2 -
+ * L3 -
+ * / \
+ * sideA sideB
+ * ----- -----
+ * *L1 a L1 -
+ * *L2 a L2 -
+ * *L3 a L3 -
+ * *L4 a *L4 b
+ * L5 - *L5 b
+ * L6 - *L6 b
+ * L7 - *L7 b
+ * \ /
+ * merge
+ * -----
+ * L1-L4 a (from sideA)
+ * L5-L7 - (common, from root)
+ * L8-L11 b (from sideB)
+ * </pre>
+ *
+ * @throws Exception
+ * any error
+ */
+ @Test
+ public void blame_merge_correctRegions() throws Exception {
+ RevCommit root, sideA, sideB, mergedTip;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ root = commitAsLines(r, "---");
+ sideA = commitAsLines(r, "aaaa---", root);
+ sideB = commitAsLines(r, "---bbbb", root);
+ mergedTip = commitAsLines(r, "aaaa---bbbb", sideA, sideB);
+ }
+
+ List<EmittedRegion> expectedRegions = Arrays.asList(
+ new EmittedRegion(sideA, 0, 4),
+ new EmittedRegion(root, 4, 7),
+ new EmittedRegion(sideB, 7, 11));
+
+ assertRegions(mergedTip, null, expectedRegions, 11);
+ assertRegions(mergedTip, emptyCache(), expectedRegions, 11);
+ assertRegions(mergedTip, blameAndCache(root), expectedRegions, 11);
+ assertRegions(mergedTip, blameAndCache(sideA), expectedRegions, 11);
+ assertRegions(mergedTip, blameAndCache(sideB), expectedRegions, 11);
+ assertRegions(mergedTip, blameAndCache(mergedTip), expectedRegions, 11);
+ }
+
+ @Test
+ public void blame_merge_cacheUsage() throws Exception {
+ RevCommit root, sideA, sideB, mergedTip;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ root = commitAsLines(r, "---");
+ sideA = commitAsLines(r, "aaaa---", root);
+ sideB = commitAsLines(r, "---bbbb", root);
+ mergedTip = commitAsLines(r, "aaaa---bbbb", sideA, sideB);
+ }
+
+ assertCacheUsage(mergedTip, null, /* cacheUsed */ false,
+ /* candidates */ 4);
+ assertCacheUsage(mergedTip, emptyCache(), false, 4);
+
+ // While splitting unblamed regions to parents, sideA comes first
+ // and gets "aaaa----". Processing is by commit time, so sideB is
+ // explored first
+ assertCacheUsage(mergedTip, blameAndCache(sideA), true, 3);
+ assertCacheUsage(mergedTip, blameAndCache(sideB), true, 4);
+ assertCacheUsage(mergedTip, blameAndCache(root), false, 4);
+ }
+
+ /**
+ * Moving block (insertion)
+ *
+ * <pre>
+ * C1 C2 C3 C3 blame
+ * lines ----------------------------------
+ * L1 | C1 C1 C1 C1
+ * L2 | C1 *C2 C2 C2
+ * L3 | C1 *C3 C3
+ * L4 | C1 C1
+ * </pre>
+ *
+ * @throws Exception
+ * any error
+ */
+ @Test
+ public void blame_movingBlock_correctRegions() throws Exception {
+ RevCommit c1, c2, c3;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = commit(r, lines("L1C1", "L2C1"));
+ c2 = commit(r, lines("L1C1", "middle", "L2C1"), c1);
+ c3 = commit(r, lines("L1C1", "middle", "extra", "L2C1"), c2);
+ }
+
+ List<EmittedRegion> expectedRegions = Arrays.asList(
+ new EmittedRegion(c1, 0, 1),
+ new EmittedRegion(c2, 1, 2),
+ new EmittedRegion(c3, 2, 3),
+ new EmittedRegion(c1, 3, 4));
+
+ assertRegions(c3, null, expectedRegions, 4);
+ assertRegions(c3, emptyCache(), expectedRegions, 4);
+ assertRegions(c3, blameAndCache(c3), expectedRegions, 4);
+ assertRegions(c3, blameAndCache(c2), expectedRegions, 4);
+ assertRegions(c3, blameAndCache(c1), expectedRegions, 4);
+ }
+
+ @Test
+ public void blame_movingBlock_cacheUsage() throws Exception {
+ RevCommit c1, c2, c3;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = commitAsLines(r, "root---");
+ c2 = commitAsLines(r, "rootXXX---", c1);
+ c3 = commitAsLines(r, "rootYYYXXX---", c2);
+ }
+
+ assertCacheUsage(c3, null, false, 3);
+ assertCacheUsage(c3, emptyCache(), false, 3);
+ assertCacheUsage(c3, blameAndCache(c3), true, 1);
+ assertCacheUsage(c3, blameAndCache(c2), true, 2);
+ assertCacheUsage(c3, blameAndCache(c1), false, 3);
+ }
+
+ @Test
+ public void blame_cacheOnlyOnChange_unmodifiedInSomeCommits_cacheUsage() throws Exception {
+ String README = "README";
+ String fileC1Content = lines("L1C1", "L2C1", "L3C1");
+ String fileC2Content = lines("L1C1", "L2C1", "L3C1", "L4C2");
+ String fileC3Content = lines("L1C1", "L2C3", "L3C3", "L4C2");
+ String fileC4Content = lines("L1C1", "L2C4", "L3C3", "L4C4");
+
+ RevCommit c1, c2, c3, c4, ni;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = r.commit().add(FILE, fileC1Content).create();
+ c2 = r.commit().parent(c1).add(FILE, fileC2Content).create();
+ // Keep FILE and edit 100 times README
+ ni = c2;
+ for (int i = 0; i < 100; i++) {
+ ni = r.commit().parent(ni).add(README, "whatever " + i).create();
+ }
+ c3 = r.commit().parent(ni).add(FILE, fileC3Content).create();
+ c4 = r.commit().parent(c3).add(FILE, fileC4Content).create();
+ r.branch("refs/heads/master").update(c4);
+ }
+
+ InMemoryBlameCache empty = emptyCache();
+ assertCacheUsage(c4, empty, false, 104);
+ assertEquals(3, empty.callCount);
+
+ InMemoryBlameCache c4Cached = blameAndCache(c4, FILE);
+ assertCacheUsage(c4, c4Cached, true, 1);
+ assertEquals(1, c4Cached.callCount);
+
+ InMemoryBlameCache c3Cached = blameAndCache(c3, FILE);
+ assertCacheUsage(c4, c3Cached, true, 2);
+ assertEquals(2, c3Cached.callCount);
+
+ // This commit doesn't touch the file, shouldn't check the cache
+ InMemoryBlameCache niCached = blameAndCache(ni, FILE);
+ assertCacheUsage(c4, niCached, false, 104);
+ assertEquals(3, niCached.callCount);
+
+ InMemoryBlameCache c2Cached = blameAndCache(c2, FILE);
+ assertCacheUsage(c4, c2Cached, true, 103);
+ assertEquals(3, c2Cached.callCount);
+
+ // No parents, c1 doesn't need cache.
+ InMemoryBlameCache c1Cached = blameAndCache(c1, FILE);
+ assertCacheUsage(c4, c1Cached, false, 104);
+ assertEquals(3, c1Cached.callCount);
+ }
+
+ @Test
+ public void blame_cacheOnlyOnChange_renameWithoutChange_cacheUsage() throws Exception {
+ String OTHER = "other.txt";
+ String c1Content = lines("L1C1", "L2C1", "L3C1");
+ String c2Content = lines("L1C1", "L2C1", "L3C1", "L4C2");
+
+ RevCommit c1, c2, c3;
+ try (TestRepository<FileRepository> r = new TestRepository<>(db)) {
+ c1 = r.commit().add(OTHER, c1Content).create();
+ c2 = r.commit().parent(c1).add(OTHER, c2Content).create();
+ c3 = r.commit().parent(c2).rm(OTHER).add(FILE, c2Content).create();
+ r.branch("refs/heads/master").update(c3);
+ }
+
+ assertCacheUsage(c3, null, false, 3);
+ assertCacheUsage(c3, emptyCache(), false, 3);
+ assertCacheUsage(c3, blameAndCache(c3, FILE), true, 1);
+ assertCacheUsage(c3, blameAndCache(c2, OTHER), true, 2);
+ assertCacheUsage(c3, blameAndCache(c1, OTHER), false, 3);
+ }
+
+ private void assertRegions(RevCommit commit, InMemoryBlameCache cache,
+ List<EmittedRegion> expectedRegions, int resultLineCount)
+ throws IOException {
+ try (BlameGenerator gen = new BlameGenerator(db, FILE, cache)) {
+ gen.push(null, db.parseCommit(commit));
+ List<EmittedRegion> regions = consume(gen);
+ assertRegionsEquals(expectedRegions, regions);
+ assertAllLinesCovered(/* lines= */ resultLineCount, regions);
+ }
+ }
+
+ private void assertCacheUsage(RevCommit commit, InMemoryBlameCache cache,
+ boolean cacheHit, int candidatesVisited) throws IOException {
+ try (BlameGenerator gen = new BlameGenerator(db, FILE, cache)) {
+ gen.push(null, db.parseCommit(commit));
+ consume(gen);
+ assertEquals(cacheHit, gen.getStats().isCacheHit());
+ assertEquals(candidatesVisited,
+ gen.getStats().getCandidatesVisited());
+ }
+ }
+
+ private static void assertAllLinesCovered(int lines,
+ List<EmittedRegion> regions) {
+ Collections.sort(regions);
+ assertEquals("Starts in first line", 0, regions.get(0).resultStart());
+ for (int i = 1; i < regions.size(); i++) {
+ assertEquals("No gaps", regions.get(i).resultStart(),
+ regions.get(i - 1).resultEnd());
+ }
+ assertEquals("Ends in last line", lines,
+ regions.get(regions.size() - 1).resultEnd());
+ }
+
+ private static void assertRegionsEquals(List<EmittedRegion> expected,
+ List<EmittedRegion> actual) {
+ assertEquals(expected.size(), actual.size());
+ Collections.sort(actual);
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(String.format("List differ in element %d", i),
+ expected.get(i), actual.get(i));
+ }
+ }
+
+ private static InMemoryBlameCache emptyCache() {
+ return new InMemoryBlameCache("<empty>");
+ }
+
+ private List<EmittedRegion> consume(BlameGenerator generator)
+ throws IOException {
+ List<EmittedRegion> result = new ArrayList<>();
+ while (generator.next()) {
+ EmittedRegion genRegion = new EmittedRegion(
+ generator.getSourceCommit().toObjectId(),
+ generator.getResultStart(), generator.getResultEnd());
+ result.add(genRegion);
+ }
+ return result;
+ }
+
+ private InMemoryBlameCache blameAndCache(RevCommit commit)
+ throws IOException {
+ return blameAndCache(commit, FILE);
+ }
+
+ private InMemoryBlameCache blameAndCache(RevCommit commit, String path)
+ throws IOException {
+ List<CacheRegion> regions;
+ try (BlameGenerator generator = new BlameGenerator(db, path)) {
+ generator.push(null, commit);
+ regions = consume(generator).stream()
+ .map(EmittedRegion::asCacheRegion)
+ .toList();
+ }
+ InMemoryBlameCache cache = new InMemoryBlameCache("<x>");
+ cache.put(commit, path, regions);
+ return cache;
+ }
+
+ private static RevCommit commitAsLines(TestRepository<?> r,
+ String charPerLine, RevCommit... parents) throws Exception {
+ return commit(r, charPerLine.replaceAll("\\S", "$0\n"), parents);
+ }
+
+ private static RevCommit commit(TestRepository<?> r, String contents,
+ RevCommit... parents) throws Exception {
+ return commit(r, Map.of(FILE, contents), parents);
+ }
+
+ private static RevCommit commit(TestRepository<?> r,
+ Map<String, String> fileContents, RevCommit... parents)
+ throws Exception {
+ TestRepository<?>.CommitBuilder builder = r.commit();
+ for (RevCommit commit : parents) {
+ builder.parent(commit);
+ }
+ fileContents.forEach((path, content) -> {
+ try {
+ builder.add(path, content);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ return builder.create();
+ }
+
+ private static String lines(String... l) {
+ return join("\n", l);
+ }
+
+ private record EmittedRegion(ObjectId oid, int resultStart, int resultEnd)
+ implements Comparable<EmittedRegion> {
+ @Override
+ public int compareTo(EmittedRegion o) {
+ return resultStart - o.resultStart;
+ }
+
+ CacheRegion asCacheRegion() {
+ return new CacheRegion(FILE, oid, resultStart, resultEnd);
+ }
+ }
+
+ private static class InMemoryBlameCache implements BlameCache {
+
+ private final Map<Key, List<CacheRegion>> cache = new HashMap<>();
+
+ private final String description;
+
+ private int callCount;
+
+ public InMemoryBlameCache(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public List<CacheRegion> get(Repository repo, ObjectId commitId,
+ String path) throws IOException {
+ callCount++;
+ return cache.get(new Key(commitId.name(), path));
+ }
+
+ public void put(ObjectId commitId, String path,
+ List<CacheRegion> cachedRegions) {
+ cache.put(new Key(commitId.name(), path), cachedRegions);
+ }
+
+ @Override
+ public String toString() {
+ return "InMemoryCache: " + description;
+ }
+
+ record Key(String commitId, String path) {
+ }
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameRegionMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameRegionMergerTest.java
new file mode 100644
index 0000000000..1b28676fbf
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/blame/BlameRegionMergerTest.java
@@ -0,0 +1,320 @@
+/*
+ * 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.blame;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.eclipse.jgit.blame.cache.CacheRegion;
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+public class BlameRegionMergerTest extends RepositoryTestCase {
+
+ private static final ObjectId O1 = ObjectId
+ .fromString("ff6dd8db6edc9aa0ac58fea1d14a55be46c3eb14");
+
+ private static final ObjectId O2 = ObjectId
+ .fromString("c3c7f680c6bee238617f25f6aa85d0b565fc8ecb");
+
+ private static final ObjectId O3 = ObjectId
+ .fromString("29e014aad0399fe8ede7c101d01b6e440ac9966b");
+
+ List<RevCommit> fakeCommits = List.of(new FakeRevCommit(O1),
+ new FakeRevCommit(O2), new FakeRevCommit(O3));
+
+ // In reverse order, so the code doesn't assume a sorted list
+ List<CacheRegion> cachedRegions = List.of(
+ new CacheRegion("README", O3, 20, 30),
+ new CacheRegion("README", O2, 10, 20),
+ new CacheRegion("README", O1, 0, 10));
+
+ BlameRegionMerger blamer = new BlameRegionMergerFakeCommits(fakeCommits,
+ cachedRegions);
+
+ @Test
+ public void intersectRegions_allInside() {
+ Region unblamed = new Region(15, 18, 10);
+ CacheRegion blamed = new CacheRegion("README", O1, 10, 90);
+
+ Region result = BlameRegionMerger.intersectRegions(unblamed, blamed);
+ // Same lines in result and source
+ assertEquals(15, result.resultStart);
+ assertEquals(18, result.sourceStart);
+ assertEquals(10, result.length);
+ assertNull(result.next);
+ }
+
+ @Test
+ public void intersectRegions_startsBefore() {
+ // Intesecting [4, 14) with [10, 90)
+ Region unblamed = new Region(30, 4, 10);
+ CacheRegion blamed = new CacheRegion("README", O1, 10, 90);
+
+ Region result = BlameRegionMerger.intersectRegions(unblamed, blamed);
+
+ // The unblamed region starting at 4 (sourceStart), starts at 30 in the
+ // original file (resultStart). e.g. some commit introduced
+ // lines. If we take the second portion of the region, we need to move
+ // the result start accordingly.
+ assertEquals(36, result.resultStart);
+ assertEquals(10, result.sourceStart);
+ assertEquals(4, result.length);
+ assertNull(result.next);
+ }
+
+ @Test
+ public void intersectRegions_endsAfter() {
+ // Intesecting [85, 95) with [10, 90)
+ Region unblamed = new Region(30, 85, 10);
+ CacheRegion blamed = new CacheRegion("README", O1, 10, 90);
+
+ Region result = BlameRegionMerger.intersectRegions(unblamed, blamed);
+
+ assertEquals(30, result.resultStart);
+ assertEquals(85, result.sourceStart);
+ assertEquals(5, result.length);
+ assertNull(result.next);
+ }
+
+ @Test
+ public void intersectRegions_spillOverBothSides() {
+ // Intesecting [5, 100) with [10, 90)
+ Region unblamed = new Region(30, 5, 95);
+ CacheRegion blamed = new CacheRegion("README", O1, 10, 90);
+
+ Region result = BlameRegionMerger.intersectRegions(unblamed, blamed);
+
+ assertEquals(35, result.resultStart);
+ assertEquals(10, result.sourceStart);
+ assertEquals(80, result.length);
+ assertNull(result.next);
+ }
+
+ @Test
+ public void intersectRegions_exactMatch() {
+ // Intesecting [5, 100) with [10, 90)
+ Region unblamed = new Region(30, 10, 80);
+ CacheRegion blamed = new CacheRegion("README", O1, 10, 90);
+
+ Region result = BlameRegionMerger.intersectRegions(unblamed, blamed);
+
+ assertEquals(30, result.resultStart);
+ assertEquals(10, result.sourceStart);
+ assertEquals(80, result.length);
+ assertNull(result.next);
+ }
+
+ @Test
+ public void findOverlaps_allInside() {
+ Region unblamed = new Region(0, 11, 4);
+ List<CacheRegion> overlaps = blamer.findOverlaps(unblamed);
+ assertEquals(1, overlaps.size());
+ assertEquals(10, overlaps.get(0).getStart());
+ assertEquals(20, overlaps.get(0).getEnd());
+ }
+
+ @Test
+ public void findOverlaps_overTwoRegions() {
+ Region unblamed = new Region(0, 8, 4);
+ List<CacheRegion> overlaps = blamer.findOverlaps(unblamed);
+ assertEquals(2, overlaps.size());
+ assertEquals(0, overlaps.get(0).getStart());
+ assertEquals(10, overlaps.get(0).getEnd());
+ assertEquals(10, overlaps.get(1).getStart());
+ assertEquals(20, overlaps.get(1).getEnd());
+ }
+
+ @Test
+ public void findOverlaps_overThreeRegions() {
+ Region unblamed = new Region(0, 8, 15);
+ List<CacheRegion> overlaps = blamer.findOverlaps(unblamed);
+ assertEquals(3, overlaps.size());
+ assertEquals(0, overlaps.get(0).getStart());
+ assertEquals(10, overlaps.get(0).getEnd());
+ assertEquals(10, overlaps.get(1).getStart());
+ assertEquals(20, overlaps.get(1).getEnd());
+ assertEquals(20, overlaps.get(2).getStart());
+ assertEquals(30, overlaps.get(2).getEnd());
+ }
+
+ @Test
+ public void blame_exactOverlap() throws IOException {
+ Region unblamed = new Region(0, 10, 10);
+ List<Candidate> blamed = blamer.mergeOneRegion(unblamed);
+
+ assertEquals(1, blamed.size());
+ Candidate c = blamed.get(0);
+ assertEquals(c.sourceCommit.name(), O2.name());
+ assertEquals(c.regionList.resultStart, unblamed.resultStart);
+ assertEquals(c.regionList.sourceStart, unblamed.sourceStart);
+ assertEquals(10, c.regionList.length);
+ assertNull(c.regionList.next);
+ }
+
+ @Test
+ public void blame_corruptedIndex() {
+ Region outOfRange = new Region(0, 43, 4);
+ // This region is out of the blamed area
+ assertThrows(IOException.class,
+ () -> blamer.mergeOneRegion(outOfRange));
+ }
+
+ @Test
+ public void blame_allInsideOneBlamedRegion() throws IOException {
+ Region unblamed = new Region(0, 5, 3);
+ // This region if fully blamed to O1
+ List<Candidate> blamed = blamer.mergeOneRegion(unblamed);
+ assertEquals(1, blamed.size());
+ Candidate c = blamed.get(0);
+ assertEquals(c.sourceCommit.name(), O1.name());
+ assertEquals(c.regionList.resultStart, unblamed.resultStart);
+ assertEquals(c.regionList.sourceStart, unblamed.sourceStart);
+ assertEquals(3, c.regionList.length);
+ assertNull(c.regionList.next);
+ }
+
+ @Test
+ public void blame_overTwoBlamedRegions() throws IOException {
+ Region unblamed = new Region(0, 8, 5);
+ // (8, 10) belongs go C1, (10, 13) to C2
+ List<Candidate> blamed = blamer.mergeOneRegion(unblamed);
+ assertEquals(2, blamed.size());
+ Candidate c = blamed.get(0);
+ assertEquals(c.sourceCommit.name(), O1.name());
+ assertEquals(unblamed.resultStart, c.regionList.resultStart);
+ assertEquals(unblamed.sourceStart, c.regionList.sourceStart);
+ assertEquals(2, c.regionList.length);
+ assertNull(c.regionList.next);
+
+ c = blamed.get(1);
+ assertEquals(c.sourceCommit.name(), O2.name());
+ assertEquals(2, c.regionList.resultStart);
+ assertEquals(10, c.regionList.sourceStart);
+ assertEquals(3, c.regionList.length);
+ assertNull(c.regionList.next);
+ }
+
+ @Test
+ public void blame_all() throws IOException {
+ Region unblamed = new Region(0, 0, 30);
+ List<Candidate> blamed = blamer.mergeOneRegion(unblamed);
+ assertEquals(3, blamed.size());
+ Candidate c = blamed.get(0);
+ assertEquals(c.sourceCommit.name(), O1.name());
+ assertEquals(unblamed.resultStart, c.regionList.resultStart);
+ assertEquals(unblamed.sourceStart, c.regionList.sourceStart);
+ assertEquals(10, c.regionList.length);
+ assertNull(c.regionList.next);
+
+ c = blamed.get(1);
+ assertEquals(c.sourceCommit.name(), O2.name());
+ assertEquals(10, c.regionList.resultStart);
+ assertEquals(10, c.regionList.sourceStart);
+ assertEquals(10, c.regionList.length);
+ assertNull(c.regionList.next);
+
+ c = blamed.get(2);
+ assertEquals(c.sourceCommit.name(), O3.name());
+ assertEquals(20, c.regionList.resultStart);
+ assertEquals(20, c.regionList.sourceStart);
+ assertEquals(10, c.regionList.length);
+ assertNull(c.regionList.next);
+ }
+
+ @Test
+ public void blame_fromCandidate() {
+ // We don't use anything from the candidate besides the
+ // regionList
+ Candidate c = new Candidate(null, null, null);
+ c.regionList = new Region(0, 8, 5);
+ c.regionList.next = new Region(22, 22, 4);
+
+ Candidate blamed = blamer.mergeCandidate(c);
+ // Three candidates
+ assertNotNull(blamed);
+ assertNotNull(blamed.queueNext);
+ assertNotNull(blamed.queueNext.queueNext);
+ assertNull(blamed.queueNext.queueNext.queueNext);
+
+ assertEquals(O1.name(), blamed.sourceCommit.name());
+
+ Candidate second = blamed.queueNext;
+ assertEquals(O2.name(), second.sourceCommit.name());
+
+ Candidate third = blamed.queueNext.queueNext;
+ assertEquals(O3.name(), third.sourceCommit.name());
+ }
+
+ @Test
+ public void blame_fromCandidate_twiceCandidateInOutput() {
+ Candidate c = new Candidate(null, null, null);
+ // This produces O1 and O2
+ c.regionList = new Region(0, 8, 5);
+ // This produces O2 and O3
+ c.regionList.next = new Region(20, 15, 7);
+
+ Candidate blamed = blamer.mergeCandidate(c);
+ assertCandidateSingleRegion(O1, 2, blamed);
+ blamed = blamed.queueNext;
+ assertCandidateSingleRegion(O2, 3, blamed);
+ // We do not merge candidates afterwards, so these are
+ // two different candidates to the same source
+ blamed = blamed.queueNext;
+ assertCandidateSingleRegion(O2, 5, blamed);
+ blamed = blamed.queueNext;
+ assertCandidateSingleRegion(O3, 2, blamed);
+ assertNull(blamed.queueNext);
+ }
+
+ private static void assertCandidateSingleRegion(ObjectId expectedOid,
+ int expectedLength, Candidate actual) {
+ assertNotNull("candidate", actual);
+ assertNotNull("region list not empty", actual.regionList);
+ assertNull("region list has only one element", actual.regionList.next);
+ assertEquals(expectedOid, actual.sourceCommit);
+ assertEquals(expectedLength, actual.regionList.length);
+ }
+
+ private static final class BlameRegionMergerFakeCommits
+ extends BlameRegionMerger {
+
+ private final Map<ObjectId, RevCommit> cache;
+
+ BlameRegionMergerFakeCommits(List<RevCommit> commits,
+ List<CacheRegion> blamedRegions) {
+ super(null, null, blamedRegions);
+ cache = commits.stream().collect(Collectors
+ .toMap(RevCommit::toObjectId, Function.identity()));
+ }
+
+ @Override
+ protected RevCommit parse(ObjectId oid) {
+ return cache.get(oid);
+ }
+ }
+
+ private static final class FakeRevCommit extends RevCommit {
+ FakeRevCommit(AnyObjectId id) {
+ super(id);
+ }
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java
index f657bab771..a2c20aaaba 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java
@@ -28,7 +28,7 @@ public class EditListTest {
assertTrue(l.isEmpty());
assertEquals("EditList[]", l.toString());
- assertEquals(l, l);
+ assertTrue(l.equals(l));
assertEquals(new EditList(), l);
assertFalse(l.equals(""));
assertEquals(l.hashCode(), new EditList().hashCode());
@@ -44,7 +44,7 @@ public class EditListTest {
assertSame(e, l.get(0));
assertSame(e, l.iterator().next());
- assertEquals(l, l);
+ assertTrue(l.equals(l));
assertFalse(l.equals(new EditList()));
final EditList l2 = new EditList();
@@ -69,7 +69,7 @@ public class EditListTest {
assertSame(e1, i.next());
assertSame(e2, i.next());
- assertEquals(l, l);
+ assertTrue(l.equals(l));
assertFalse(l.equals(new EditList()));
final EditList l2 = new EditList();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java
index 8ab9bb12de..86c6d77cc6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java
@@ -98,7 +98,7 @@ public class EditTest {
final Edit e1 = new Edit(1, 2, 3, 4);
final Edit e2 = new Edit(1, 2, 3, 4);
- assertEquals(e1, e1);
+ assertTrue(e1.equals(e1));
assertEquals(e2, e1);
assertEquals(e1, e2);
assertEquals(e1.hashCode(), e2.hashCode());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java
index fca27d32aa..0949d040e9 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/gitrepo/ManifestParserTest.java
@@ -12,12 +12,16 @@ package org.eclipse.jgit.gitrepo;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
+import java.io.File;
import java.io.IOException;
import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -221,4 +225,33 @@ public class ManifestParserTest {
testNormalize("", "");
testNormalize("a/b", "a/b");
}
+
+ @Test
+ public void testXXE() throws Exception {
+ File externalEntity = File.createTempFile("injected", "xml");
+ externalEntity.deleteOnExit();
+ Files.write(externalEntity.toPath(),
+ "<evil>injected xml</evil>"
+ .getBytes(UTF_8),
+ StandardOpenOption.WRITE);
+ String baseUrl = "https://git.google.com/";
+ StringBuilder xmlContent = new StringBuilder();
+ xmlContent.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+ .append("<!DOCTYPE booo [ <!ENTITY foobar SYSTEM \"")
+ .append(externalEntity.getPath()).append("\"> ]>\n")
+ .append("<manifest>")
+ .append("<remote name=\"remote1\" fetch=\".\" />")
+ .append("<default revision=\"master\" remote=\"remote1\" />")
+ .append("&foobar;")
+ .append("<project path=\"foo\" name=\"foo\" groups=\"a,test\" />")
+ .append("</manifest>");
+
+ IOException e = assertThrows(IOException.class,
+ () -> new ManifestParser(null, null, "master", baseUrl, null,
+ null)
+ .read(new ByteArrayInputStream(
+ xmlContent.toString().getBytes(UTF_8))));
+ assertTrue(e.getCause().getMessage().contains("DOCTYPE"));
+ }
+
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java
index 6112952549..6983eaa354 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/ignore/BasicRuleTest.java
@@ -31,7 +31,7 @@ public class BasicRuleTest {
assertFalse(rule1.getNegation());
assertTrue(rule3.getNegation());
assertNotEquals(rule1, null);
- assertEquals(rule1, rule1);
+ assertTrue(rule1.equals(rule1));
assertEquals(rule1, rule2);
assertNotEquals(rule1, rule3);
assertNotEquals(rule1, rule4);
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 f9fbfe8db0..80bd689084 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
@@ -17,10 +17,9 @@ import static org.junit.Assert.fail;
import java.io.IOException;
import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
-import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
@@ -50,7 +49,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.pack.PackConfig;
import org.eclipse.jgit.transport.ReceiveCommand;
-import org.eclipse.jgit.util.GitDateParser;
+import org.eclipse.jgit.util.GitTimeParser;
import org.eclipse.jgit.util.SystemReader;
import org.junit.After;
import org.junit.Before;
@@ -1183,7 +1182,8 @@ public class DfsGarbageCollectorTest {
DfsReader reader = odb.newReader();
DfsPackFile gcPack = findFirstBySource(odb.getPacks(), GC);
assertTrue(gcPack.hasObjectSizeIndex(reader));
- assertEquals(12, gcPack.getIndexedObjectSize(reader, headsBlob));
+ assertEquals(12, gcPack.getIndexedObjectSize(reader,
+ gcPack.findIdxPosition(reader, headsBlob)));
}
@Test
@@ -1204,7 +1204,8 @@ public class DfsGarbageCollectorTest {
DfsReader reader = odb.newReader();
DfsPackFile gcPack = findFirstBySource(odb.getPacks(), GC);
assertTrue(gcPack.hasObjectSizeIndex(reader));
- assertEquals(-1, gcPack.getIndexedObjectSize(reader, tooSmallBlob));
+ assertEquals(-1, gcPack.getIndexedObjectSize(reader,
+ gcPack.findIdxPosition(reader, tooSmallBlob)));
}
@Test
@@ -1294,23 +1295,22 @@ public class DfsGarbageCollectorTest {
DfsPackDescription t1 = odb.newPack(INSERT);
Ref next = new ObjectIdRef.PeeledNonTag(Ref.Storage.LOOSE,
"refs/heads/next", commit0.copy());
- long currentDay = new Date().getTime();
- GregorianCalendar cal = new GregorianCalendar(SystemReader
- .getInstance().getTimeZone(), SystemReader.getInstance()
- .getLocale());
- long ten_days_ago = GitDateParser.parse("10 days ago",cal,SystemReader.getInstance()
- .getLocale()).getTime() ;
- long twenty_days_ago = GitDateParser.parse("20 days ago",cal,SystemReader.getInstance()
- .getLocale()).getTime() ;
- long thirty_days_ago = GitDateParser.parse("30 days ago",cal,SystemReader.getInstance()
- .getLocale()).getTime() ;;
- long fifty_days_ago = GitDateParser.parse("50 days ago",cal,SystemReader.getInstance()
- .getLocale()).getTime() ;
- PersonIdent who2 = new PersonIdent("J.Author", "authemail", currentDay, -8 * 60);
- PersonIdent who3 = new PersonIdent("J.Author", "authemail", ten_days_ago, -8 * 60);
- PersonIdent who4 = new PersonIdent("J.Author", "authemail", twenty_days_ago, -8 * 60);
- PersonIdent who5 = new PersonIdent("J.Author", "authemail", thirty_days_ago, -8 * 60);
- PersonIdent who6 = new PersonIdent("J.Author", "authemail", fifty_days_ago, -8 * 60);
+ Instant currentDay = Instant.now();
+ Instant ten_days_ago = GitTimeParser.parseInstant("10 days ago");
+ Instant twenty_days_ago = GitTimeParser.parseInstant("20 days ago");
+ Instant thirty_days_ago = GitTimeParser.parseInstant("30 days ago");
+ Instant fifty_days_ago = GitTimeParser.parseInstant("50 days ago");
+ final ZoneOffset offset = ZoneOffset.ofHours(-8);
+ PersonIdent who2 = new PersonIdent("J.Author", "authemail", currentDay,
+ offset);
+ PersonIdent who3 = new PersonIdent("J.Author", "authemail",
+ ten_days_ago, offset);
+ PersonIdent who4 = new PersonIdent("J.Author", "authemail",
+ twenty_days_ago, offset);
+ PersonIdent who5 = new PersonIdent("J.Author", "authemail",
+ thirty_days_ago, offset);
+ PersonIdent who6 = new PersonIdent("J.Author", "authemail",
+ fifty_days_ago, offset);
try (DfsOutputStream out = odb.writeFile(t1, REFTABLE)) {
ReftableWriter w = new ReftableWriter(out);
@@ -1332,7 +1332,7 @@ public class DfsGarbageCollectorTest {
gc = new DfsGarbageCollector(repo);
gc.setReftableConfig(new ReftableConfig());
// Expire ref log entries older than 30 days
- gc.setRefLogExpire(Instant.ofEpochMilli(thirty_days_ago));
+ gc.setRefLogExpire(thirty_days_ago);
run(gc);
// Single GC pack present with all objects.
@@ -1360,9 +1360,7 @@ public class DfsGarbageCollectorTest {
assertEquals(lc.getRefName(),"refs/heads/branch2");
// Old entries are purged
assertFalse(lc.next());
-
}
-
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java
index 0b558edf2c..efa98de549 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsInserterTest.java
@@ -214,7 +214,7 @@ public class DfsInserterTest {
}
@Test
- public void testNoCheckExisting() throws IOException {
+ public void testNoDuplicates() throws IOException {
byte[] contents = Constants.encode("foo");
ObjectId fooId;
try (ObjectInserter ins = db.newObjectInserter()) {
@@ -224,21 +224,20 @@ public class DfsInserterTest {
assertEquals(1, db.getObjectDatabase().listPacks().size());
try (ObjectInserter ins = db.newObjectInserter()) {
- ((DfsInserter) ins).checkExisting(false);
+ ins.insert(Constants.OBJ_BLOB, Constants.encode("bar"));
assertEquals(fooId, ins.insert(Constants.OBJ_BLOB, contents));
ins.flush();
}
assertEquals(2, db.getObjectDatabase().listPacks().size());
- // Verify that we have a foo in both INSERT packs.
+ // Newer packs are first. Verify that foo is only in the second pack
try (DfsReader reader = new DfsReader(db.getObjectDatabase())) {
DfsPackFile packs[] = db.getObjectDatabase().getPacks();
-
assertEquals(2, packs.length);
DfsPackFile p1 = packs[0];
assertEquals(PackSource.INSERT,
p1.getPackDescription().getPackSource());
- assertTrue(p1.hasObject(reader, fooId));
+ assertFalse(p1.hasObject(reader, fooId));
DfsPackFile p2 = packs[1];
assertEquals(PackSource.INSERT,
@@ -310,7 +309,8 @@ public class DfsInserterTest {
assertEquals(PackSource.INSERT,
insertPack.getPackDescription().getPackSource());
assertTrue(insertPack.hasObjectSizeIndex(reader));
- assertEquals(contents.length, insertPack.getIndexedObjectSize(reader, fooId));
+ assertEquals(contents.length, insertPack.getIndexedObjectSize(reader,
+ insertPack.findIdxPosition(reader, fooId)));
}
private static String readString(ObjectLoader loader) throws IOException {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
index 9680019f88..f2129fd3c5 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileTest.java
@@ -131,7 +131,8 @@ public class DfsPackFileTest {
DfsReader reader = db.getObjectDatabase().newReader();
DfsPackFile pack = db.getObjectDatabase().getPacks()[0];
assertTrue(pack.hasObjectSizeIndex(reader));
- assertEquals(800, pack.getIndexedObjectSize(reader, blobId));
+ assertEquals(800, pack.getIndexedObjectSize(reader,
+ pack.findIdxPosition(reader, blobId)));
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java
index c1cd231c66..9d26978d66 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackParserTest.java
@@ -65,6 +65,7 @@ public class DfsPackParserTest {
DfsReader reader = repo.getObjectDatabase().newReader();
PackList packList = repo.getObjectDatabase().getPackList();
assertEquals(1, packList.packs.length);
- assertEquals(1, packList.packs[0].getIndexedObjectSize(reader, blobA));
+ assertEquals(1, packList.packs[0].getIndexedObjectSize(reader,
+ packList.packs[0].findIdxPosition(reader, blobA)));
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
index 1af42cb229..a0afc3ef13 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java
@@ -1263,7 +1263,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
}
private ReflogEntry getLastReflog(String name) throws IOException {
- ReflogReader r = diskRepo.getReflogReader(name);
+ ReflogReader r = diskRepo.getRefDatabase().getReflogReader(name);
if (r == null) {
return null;
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableStackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableStackTest.java
index 6c7992716c..e8363ce21d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableStackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableStackTest.java
@@ -81,8 +81,7 @@ public class FileReftableStackTest {
}
public void testCompaction(int N) throws Exception {
- try (FileReftableStack stack = new FileReftableStack(
- new File(reftableDir, "refs"), reftableDir, null,
+ try (FileReftableStack stack = new FileReftableStack(reftableDir, null,
() -> new Config())) {
writeBranches(stack, "refs/heads/branch%d", 0, N);
MergedReftable table = stack.getMergedReftable();
@@ -124,8 +123,7 @@ public class FileReftableStackTest {
// Can't delete in-use files on Windows.
assumeFalse(SystemReader.getInstance().isWindows());
- try (FileReftableStack stack = new FileReftableStack(
- new File(reftableDir, "refs"), reftableDir, null,
+ try (FileReftableStack stack = new FileReftableStack(reftableDir, null,
() -> new Config())) {
outer: for (int i = 0; i < 10; i++) {
final long next = stack.getMergedReftable().maxUpdateIndex()
@@ -152,8 +150,8 @@ public class FileReftableStackTest {
}
}
assertThrows(FileNotFoundException.class,
- () -> new FileReftableStack(new File(reftableDir, "refs"),
- reftableDir, null, () -> new Config()));
+ () -> new FileReftableStack(reftableDir, null,
+ () -> new Config()));
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java
index 32342e3563..5756b41442 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/FileReftableTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import java.io.File;
import java.io.FileOutputStream;
@@ -33,8 +34,15 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
-
import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
@@ -51,6 +59,10 @@ import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FS.ExecutionResult;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.TemporaryBuffer;
import org.junit.Test;
public class FileReftableTest extends SampleDataRepositoryTestCase {
@@ -66,6 +78,30 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
@SuppressWarnings("boxing")
@Test
+ public void testReloadIfNecessary() throws Exception {
+ ObjectId id = db.resolve("master");
+ try (FileRepository repo1 = new FileRepository(db.getDirectory());
+ FileRepository repo2 = new FileRepository(db.getDirectory())) {
+ ((FileReftableDatabase) repo1.getRefDatabase())
+ .setAutoRefresh(true);
+ ((FileReftableDatabase) repo2.getRefDatabase())
+ .setAutoRefresh(true);
+ FileRepository repos[] = { repo1, repo2 };
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 2; j++) {
+ FileRepository repo = repos[j];
+ RefUpdate u = repo.getRefDatabase().newUpdate(
+ String.format("branch%d", i * 10 + j), false);
+ u.setNewObjectId(id);
+ RefUpdate.Result r = u.update();
+ assertEquals(Result.NEW, r);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("boxing")
+ @Test
public void testRacyReload() throws Exception {
ObjectId id = db.resolve("master");
int retry = 0;
@@ -87,13 +123,61 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
u.setNewObjectId(id);
r = u.update();
- assertEquals(r, Result.NEW);
+ assertEquals(Result.NEW, r);
}
}
}
// only the first one succeeds
- assertEquals(retry, 19);
+ assertEquals(19, retry);
+ }
+ }
+
+ @Test
+ public void testConcurrentRacyReload() throws Exception {
+ ObjectId id = db.resolve("master");
+ final CyclicBarrier barrier = new CyclicBarrier(2);
+
+ class UpdateRef implements Callable<RefUpdate.Result> {
+
+ private RefUpdate u;
+
+ UpdateRef(FileRepository repo, String branchName)
+ throws IOException {
+ u = repo.getRefDatabase().newUpdate(branchName,
+ false);
+ u.setNewObjectId(id);
+ }
+
+ @Override
+ public RefUpdate.Result call() throws Exception {
+ barrier.await(); // wait for the other thread to prepare
+ return u.update();
+ }
+ }
+
+ ExecutorService pool = Executors.newFixedThreadPool(2);
+ try (FileRepository repo1 = new FileRepository(db.getDirectory());
+ FileRepository repo2 = new FileRepository(db.getDirectory())) {
+ ((FileReftableDatabase) repo1.getRefDatabase())
+ .setAutoRefresh(true);
+ ((FileReftableDatabase) repo2.getRefDatabase())
+ .setAutoRefresh(true);
+ for (int i = 0; i < 10; i++) {
+ String branchName = String.format("branch%d",
+ Integer.valueOf(i));
+ Future<RefUpdate.Result> ru1 = pool
+ .submit(new UpdateRef(repo1, branchName));
+ Future<RefUpdate.Result> ru2 = pool
+ .submit(new UpdateRef(repo2, branchName));
+ assertTrue((ru1.get() == Result.NEW
+ && ru2.get() == Result.LOCK_FAILURE)
+ || (ru1.get() == Result.LOCK_FAILURE
+ && ru2.get() == Result.NEW));
+ }
+ } finally {
+ pool.shutdown();
+ pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
}
}
@@ -105,13 +189,13 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
RefUpdate u = db.updateRef("refs/heads/master");
u.setForceUpdate(true);
u.setNewObjectId((i%2) == 0 ? c1 : c2);
- assertEquals(u.update(), FORCED);
+ assertEquals(FORCED, u.update());
}
File tableDir = new File(db.getDirectory(), Constants.REFTABLE);
assertTrue(tableDir.listFiles().length > 2);
((FileReftableDatabase)db.getRefDatabase()).compactFully();
- assertEquals(tableDir.listFiles().length,2);
+ assertEquals(2, tableDir.listFiles().length);
}
@Test
@@ -171,9 +255,10 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
v.update();
db.convertToPackedRefs(true, false);
- List<ReflogEntry> logs = db.getReflogReader("refs/heads/master").getReverseEntries(2);
- assertEquals(logs.get(0).getComment(), "banana");
- assertEquals(logs.get(1).getComment(), "apple");
+ List<ReflogEntry> logs = db.getRefDatabase()
+ .getReflogReader("refs/heads/master").getReverseEntries(2);
+ assertEquals("banana", logs.get(0).getComment());
+ assertEquals("apple", logs.get(1).getComment());
}
@Test
@@ -185,8 +270,9 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
ReceiveCommand rc1 = new ReceiveCommand(ObjectId.zeroId(), cur, "refs/heads/batch1");
ReceiveCommand rc2 = new ReceiveCommand(ObjectId.zeroId(), prev, "refs/heads/batch2");
String msg = "message";
+ RefDatabase refDb = db.getRefDatabase();
try (RevWalk rw = new RevWalk(db)) {
- db.getRefDatabase().newBatchUpdate()
+ refDb.newBatchUpdate()
.addCommand(rc1, rc2)
.setAtomic(true)
.setRefLogIdent(person)
@@ -194,15 +280,17 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
.execute(rw, NullProgressMonitor.INSTANCE);
}
- assertEquals(rc1.getResult(), ReceiveCommand.Result.OK);
- assertEquals(rc2.getResult(), ReceiveCommand.Result.OK);
+ assertEquals(ReceiveCommand.Result.OK, rc1.getResult());
+ assertEquals(ReceiveCommand.Result.OK, rc2.getResult());
- ReflogEntry e = db.getReflogReader("refs/heads/batch1").getLastEntry();
+ ReflogEntry e = refDb.getReflogReader("refs/heads/batch1")
+ .getLastEntry();
assertEquals(msg, e.getComment());
assertEquals(person, e.getWho());
assertEquals(cur, e.getNewId());
- e = db.getReflogReader("refs/heads/batch2").getLastEntry();
+ e = refDb.getReflogReader("refs/heads/batch2")
+ .getLastEntry();
assertEquals(msg, e.getComment());
assertEquals(person, e.getWho());
assertEquals(prev, e.getNewId());
@@ -267,7 +355,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
RefUpdate up = db.getRefDatabase().newUpdate("refs/heads/a", false);
up.setForceUpdate(true);
RefUpdate.Result res = up.delete();
- assertEquals(res, FORCED);
+ assertEquals(FORCED, res);
assertNull(db.exactRef("refs/heads/a"));
}
@@ -309,7 +397,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
// the branch HEAD referred to is left untouched
assertEquals(pid, db.resolve("refs/heads/master"));
- ReflogReader reflogReader = db.getReflogReader("HEAD");
+ ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD");
ReflogEntry e = reflogReader.getReverseEntries().get(0);
assertEquals(ppid, e.getNewId());
assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
@@ -330,12 +418,13 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
updateRef.setForceUpdate(true);
RefUpdate.Result update = updateRef.update();
assertEquals(FORCED, update); // internal
- ReflogReader r = db.getReflogReader("refs/heads/master");
+ ReflogReader r = db.getRefDatabase()
+ .getReflogReader("refs/heads/master");
ReflogEntry e = r.getLastEntry();
- assertEquals(e.getNewId(), pid);
- assertEquals(e.getComment(), "REFLOG!: FORCED");
- assertEquals(e.getWho(), person);
+ assertEquals(pid, e.getNewId());
+ assertEquals("REFLOG!: FORCED", e.getComment());
+ assertEquals(person, e.getWho());
}
@Test
@@ -352,10 +441,11 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
ref = db.updateRef(newRef);
ref.setNewObjectId(db.resolve(Constants.HEAD));
- assertEquals(ref.delete(), RefUpdate.Result.NO_CHANGE);
+ assertEquals(RefUpdate.Result.NO_CHANGE, ref.delete());
// Differs from RefupdateTest. Deleting a loose ref leaves reflog trail.
- ReflogReader reader = db.getReflogReader("refs/heads/abc");
+ ReflogReader reader = db.getRefDatabase()
+ .getReflogReader("refs/heads/abc");
assertEquals(ObjectId.zeroId(), reader.getReverseEntry(1).getOldId());
assertEquals(nonZero, reader.getReverseEntry(1).getNewId());
assertEquals(nonZero, reader.getReverseEntry(0).getOldId());
@@ -382,8 +472,9 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
assertNotSame(newid, r.getObjectId());
assertSame(ObjectId.class, r.getObjectId().getClass());
assertEquals(newid, r.getObjectId());
- List<ReflogEntry> reverseEntries1 = db.getReflogReader("refs/heads/abc")
- .getReverseEntries();
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> reverseEntries1 = refDb
+ .getReflogReader("refs/heads/abc").getReverseEntries();
ReflogEntry entry1 = reverseEntries1.get(0);
assertEquals(1, reverseEntries1.size());
assertEquals(ObjectId.zeroId(), entry1.getOldId());
@@ -392,7 +483,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
assertEquals(new PersonIdent(db).toString(),
entry1.getWho().toString());
assertEquals("", entry1.getComment());
- List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD")
+ List<ReflogEntry> reverseEntries2 = refDb.getReflogReader("HEAD")
.getReverseEntries();
assertEquals(0, reverseEntries2.size());
}
@@ -431,7 +522,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
Ref head = db.exactRef("HEAD");
assertTrue(head.isSymbolic());
- assertEquals(head.getTarget().getName(), "refs/heads/unborn");
+ assertEquals("refs/heads/unborn", head.getTarget().getName());
}
/**
@@ -455,7 +546,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
// the branch HEAD referred to is left untouched
assertNull(db.resolve("refs/heads/unborn"));
- ReflogReader reflogReader = db.getReflogReader("HEAD");
+ ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD");
ReflogEntry e = reflogReader.getReverseEntries().get(0);
assertEquals(ObjectId.zeroId(), e.getOldId());
assertEquals(ppid, e.getNewId());
@@ -499,7 +590,7 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
names.add("refs/heads/new/name");
for (String nm : names) {
- ReflogReader rd = db.getReflogReader(nm);
+ ReflogReader rd = db.getRefDatabase().getReflogReader(nm);
assertNotNull(rd);
ReflogEntry last = rd.getLastEntry();
ObjectId id = last.getNewId();
@@ -573,10 +664,10 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
assertTrue(res == Result.NEW || res == FORCED);
}
- assertEquals(refDb.exactRef(refName).getObjectId(), bId);
+ assertEquals(bId, refDb.exactRef(refName).getObjectId());
assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment()));
refDb.compactFully();
- assertEquals(refDb.exactRef(refName).getObjectId(), bId);
+ assertEquals(bId, refDb.exactRef(refName).getObjectId());
assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment()));
}
@@ -644,6 +735,54 @@ public class FileReftableTest extends SampleDataRepositoryTestCase {
checkContainsRef(refs, db.exactRef("HEAD"));
}
+ @Test
+ public void testExternalUpdate_bug_102() throws Exception {
+ ((FileReftableDatabase) db.getRefDatabase()).setAutoRefresh(true);
+ assumeTrue(atLeastGitVersion(2, 45));
+ Git git = Git.wrap(db);
+ git.tag().setName("foo").call();
+ Ref ref = db.exactRef("refs/tags/foo");
+ assertNotNull(ref);
+ runGitCommand("tag", "--force", "foo", "e");
+ Ref e = db.exactRef("refs/heads/e");
+ Ref foo = db.exactRef("refs/tags/foo");
+ assertEquals(e.getObjectId(), foo.getObjectId());
+ }
+
+ private String toString(TemporaryBuffer b) throws IOException {
+ return RawParseUtils.decode(b.toByteArray());
+ }
+
+ private ExecutionResult runGitCommand(String... args)
+ throws IOException, InterruptedException {
+ FS fs = db.getFS();
+ ProcessBuilder pb = fs.runInShell("git", args);
+ pb.directory(db.getWorkTree());
+ System.err.println("PATH=" + pb.environment().get("PATH"));
+ ExecutionResult result = fs.execute(pb, null);
+ assertEquals(0, result.getRc());
+ String err = toString(result.getStderr());
+ if (!err.isEmpty()) {
+ System.err.println(err);
+ }
+ String out = toString(result.getStdout());
+ if (!out.isEmpty()) {
+ System.out.println(out);
+ }
+ return result;
+ }
+
+ private boolean atLeastGitVersion(int minMajor, int minMinor)
+ throws IOException, InterruptedException {
+ String version = toString(runGitCommand("version").getStdout())
+ .split(" ")[2];
+ System.out.println(version);
+ String[] digits = version.split("\\.");
+ int major = Integer.parseInt(digits[0]);
+ int minor = Integer.parseInt(digits[1]);
+ return (major >= minMajor) && (minor >= minMinor);
+ }
+
private RefUpdate updateRef(String name) throws IOException {
final RefUpdate ref = db.updateRef(name);
ref.setNewObjectId(db.resolve(Constants.HEAD));
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java
index 6cad8b6c62..434f7e4bef 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcBasicPackingTest.java
@@ -16,9 +16,9 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Date;
import java.util.List;
import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
@@ -206,7 +206,7 @@ public class GcBasicPackingTest extends GcTestCase {
// The old packfile is too young to be deleted. We should end up with
// two pack files
- gc.setExpire(new Date(oldPackfile.lastModified() - 1));
+ gc.setExpire(Instant.ofEpochMilli(oldPackfile.lastModified() - 1));
gc.gc().get();
stats = gc.getStatistics();
assertEquals(0, stats.numberOfLooseObjects);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java
index ca0f6842fc..84ec132e24 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcPruneNonReferencedTest.java
@@ -16,8 +16,8 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
+import java.time.Instant;
import java.util.Collections;
-import java.util.Date;
import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
import org.eclipse.jgit.lib.ObjectId;
@@ -30,7 +30,7 @@ public class GcPruneNonReferencedTest extends GcTestCase {
@Test
public void nonReferencedNonExpiredObject_notPruned() throws Exception {
RevBlob a = tr.blob("a");
- gc.setExpire(new Date(lastModified(a)));
+ gc.setExpire(Instant.ofEpochMilli(lastModified(a)));
gc.prune(Collections.<ObjectId> emptySet());
assertTrue(repo.getObjectDatabase().has(a));
}
@@ -58,7 +58,7 @@ public class GcPruneNonReferencedTest extends GcTestCase {
@Test
public void nonReferencedObjects_onlyExpiredPruned() throws Exception {
RevBlob a = tr.blob("a");
- gc.setExpire(new Date(lastModified(a) + 1));
+ gc.setExpire(Instant.ofEpochMilli(lastModified(a) + 1));
fsTick();
RevBlob b = tr.blob("b");
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcSinceBitmapStatisticsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcSinceBitmapStatisticsTest.java
index 3cd766c4e9..af52e2cb85 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcSinceBitmapStatisticsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcSinceBitmapStatisticsTest.java
@@ -20,6 +20,7 @@ import java.util.stream.StreamSupport;
import org.eclipse.jgit.internal.storage.file.GC.RepoStatistics;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.pack.PackConfig;
import org.junit.Test;
public class GcSinceBitmapStatisticsTest extends GcTestCase {
@@ -51,11 +52,19 @@ public class GcSinceBitmapStatisticsTest extends GcTestCase {
}
@Test
- public void testShouldReportNoPacksDirectlyAfterGc() throws Exception {
- // given
+ public void testShouldReportNoPacksFilesSinceBitmapWhenPackfilesAreOlderThanBitmapFile()
+ throws Exception {
addCommit(null);
- gc.gc().get();
+ configureGC(/* buildBitmap */ false).gc().get();
+ assertEquals(1L, gc.getStatistics().numberOfPackFiles);
+ assertEquals(0L, repositoryBitmapFiles());
+ assertEquals(1L, gc.getStatistics().numberOfPackFilesSinceBitmap);
+
+ addCommit(null);
+ configureGC(/* buildBitmap */ true).gc().get();
+
assertEquals(1L, repositoryBitmapFiles());
+ assertEquals(2L, gc.getStatistics().numberOfPackFiles);
assertEquals(0L, gc.getStatistics().numberOfPackFilesSinceBitmap);
}
@@ -79,8 +88,11 @@ public class GcSinceBitmapStatisticsTest extends GcTestCase {
// progress & pack
addCommit(parent);
- tr.packAndPrune();
+ assertEquals(1L, gc.getStatistics().numberOfPackFiles);
+ assertEquals(0L, gc.getStatistics().numberOfPackFilesSinceBitmap);
+ tr.packAndPrune();
+ assertEquals(2L, gc.getStatistics().numberOfPackFiles);
assertEquals(1L, gc.getStatistics().numberOfPackFilesSinceBitmap);
}
@@ -90,13 +102,17 @@ public class GcSinceBitmapStatisticsTest extends GcTestCase {
// commit & gc
RevCommit parent = addCommit(null);
gc.gc().get();
+ assertEquals(0L, gc.getStatistics().numberOfLooseObjects);
assertEquals(0L, gc.getStatistics().numberOfObjectsSinceBitmap);
// progress & pack
addCommit(parent);
+ assertEquals(1L, gc.getStatistics().numberOfLooseObjects);
assertEquals(1L, gc.getStatistics().numberOfObjectsSinceBitmap);
tr.packAndPrune();
+ assertEquals(0L, gc.getStatistics().numberOfLooseObjects);
+ // Number of objects contained in the newly created PackFile
assertEquals(3L, gc.getStatistics().numberOfObjectsSinceBitmap);
}
@@ -164,4 +180,11 @@ public class GcSinceBitmapStatisticsTest extends GcTestCase {
}
}).sum();
}
+
+ private GC configureGC(boolean buildBitmap) {
+ PackConfig pc = new PackConfig(repo.getObjectDatabase().getConfig());
+ pc.setBuildBitmaps(buildBitmap);
+ gc.setPackConfig(pc);
+ return gc;
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
index d1342c0fbd..33cbc868ca 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java
@@ -49,7 +49,10 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import java.io.File;
@@ -66,6 +69,7 @@ import java.util.concurrent.Future;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -207,33 +211,35 @@ public class ObjectDirectoryTest extends RepositoryTestCase {
.fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b");
WindowCursor curs = new WindowCursor(db.getObjectDatabase());
- LooseObjects mock = mock(LooseObjects.class);
+ Config config = new Config();
+ config.setString("core", null, "trustLooseObjectStat", "ALWAYS");
+ LooseObjects spy = Mockito.spy(new LooseObjects(config, trash));
UnpackedObjectCache unpackedObjectCacheMock = mock(
UnpackedObjectCache.class);
- Mockito.when(mock.getObjectLoader(any(), any(), any()))
- .thenThrow(new IOException("Stale File Handle"));
- Mockito.when(mock.open(curs, id)).thenCallRealMethod();
- Mockito.when(mock.unpackedObjectCache())
- .thenReturn(unpackedObjectCacheMock);
+ doThrow(new IOException("Stale File Handle")).when(spy)
+ .getObjectLoader(any(), any(), any());
+ doReturn(unpackedObjectCacheMock).when(spy).unpackedObjectCache();
- assertNull(mock.open(curs, id));
+ assertNull(spy.open(curs, id));
verify(unpackedObjectCacheMock).remove(id);
}
- @Test
+ @Test(expected = IOException.class)
public void testOpenLooseObjectPropagatesIOExceptions() throws Exception {
ObjectId id = ObjectId
.fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b");
WindowCursor curs = new WindowCursor(db.getObjectDatabase());
- LooseObjects mock = mock(LooseObjects.class);
+ Config config = new Config();
+ config.setString("core", null, "trustLooseObjectStat", "NEVER");
+ LooseObjects spy = spy(new LooseObjects(config,
+ db.getObjectDatabase().getDirectory()));
- Mockito.when(mock.getObjectLoader(any(), any(), any()))
- .thenThrow(new IOException("some IO failure"));
- Mockito.when(mock.open(curs, id)).thenCallRealMethod();
+ doThrow(new IOException("some IO failure")).when(spy)
+ .getObjectLoader(any(), any(), any());
- assertThrows(IOException.class, () -> mock.open(curs, id));
+ spy.open(curs, id);
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
index 24bdc4a97a..1f934acced 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
@@ -13,6 +13,7 @@ package org.eclipse.jgit.internal.storage.file;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
@@ -25,6 +26,7 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry;
import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;
@@ -99,6 +101,39 @@ public abstract class PackIndexTestCase extends RepositoryTestCase {
}
}
+ @Test
+ public void testIteratorMutableEntryCompareTo() {
+ Iterator<PackIndex.MutableEntry> iterA = smallIdx.iterator();
+ Iterator<PackIndex.MutableEntry> iterB = smallIdx.iterator();
+
+ MutableEntry aEntry = iterA.next();
+ iterB.next();
+ MutableEntry bEntry = iterB.next();
+ // b is one ahead
+ assertTrue(aEntry.compareBySha1To(bEntry) < 0);
+ assertTrue(bEntry.compareBySha1To(aEntry) > 0);
+
+ // advance a, now should be equal
+ assertEquals(0, iterA.next().compareBySha1To(bEntry));
+ }
+
+ @Test
+ public void testIteratorMutableEntryCopyTo() {
+ Iterator<PackIndex.MutableEntry> it = smallIdx.iterator();
+
+ MutableObjectId firstOidCopy = new MutableObjectId();
+ MutableEntry next = it.next();
+ next.copyOidTo(firstOidCopy);
+ ObjectId firstImmutable = next.toObjectId();
+
+ MutableEntry second = it.next();
+
+ // The copy has the right value after "next"
+ assertTrue(firstImmutable.equals(firstOidCopy));
+ assertFalse("iterator has moved",
+ second.toObjectId().equals(firstImmutable));
+ }
+
/**
* Test results of iterator comparing to content of well-known (prepared)
* small index.
@@ -106,22 +141,22 @@ public abstract class PackIndexTestCase extends RepositoryTestCase {
@Test
public void testIteratorReturnedValues1() {
Iterator<PackIndex.MutableEntry> iter = smallIdx.iterator();
- assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", iter.next()
- .name());
- assertEquals("540a36d136cf413e4b064c2b0e0a4db60f77feab", iter.next()
- .name());
- assertEquals("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259", iter.next()
- .name());
- assertEquals("6ff87c4664981e4397625791c8ea3bbb5f2279a3", iter.next()
- .name());
- assertEquals("82c6b885ff600be425b4ea96dee75dca255b69e7", iter.next()
- .name());
- assertEquals("902d5476fa249b7abc9d84c611577a81381f0327", iter.next()
- .name());
- assertEquals("aabf2ffaec9b497f0950352b3e582d73035c2035", iter.next()
- .name());
- assertEquals("c59759f143fb1fe21c197981df75a7ee00290799", iter.next()
- .name());
+ assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904",
+ iter.next().name());
+ assertEquals("540a36d136cf413e4b064c2b0e0a4db60f77feab",
+ iter.next().name());
+ assertEquals("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259",
+ iter.next().name());
+ assertEquals("6ff87c4664981e4397625791c8ea3bbb5f2279a3",
+ iter.next().name());
+ assertEquals("82c6b885ff600be425b4ea96dee75dca255b69e7",
+ iter.next().name());
+ assertEquals("902d5476fa249b7abc9d84c611577a81381f0327",
+ iter.next().name());
+ assertEquals("aabf2ffaec9b497f0950352b3e582d73035c2035",
+ iter.next().name());
+ assertEquals("c59759f143fb1fe21c197981df75a7ee00290799",
+ iter.next().name());
assertFalse(iter.hasNext());
}
@@ -198,16 +233,16 @@ public abstract class PackIndexTestCase extends RepositoryTestCase {
@Test
public void testIteratorReturnedValues2() {
Iterator<PackIndex.MutableEntry> iter = denseIdx.iterator();
- while (!iter.next().name().equals(
- "0a3d7772488b6b106fb62813c4d6d627918d9181")) {
+ while (!iter.next().name()
+ .equals("0a3d7772488b6b106fb62813c4d6d627918d9181")) {
// just iterating
}
- assertEquals("1004d0d7ac26fbf63050a234c9b88a46075719d3", iter.next()
- .name()); // same level-1
- assertEquals("10da5895682013006950e7da534b705252b03be6", iter.next()
- .name()); // same level-1
- assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8", iter.next()
- .name());
+ assertEquals("1004d0d7ac26fbf63050a234c9b88a46075719d3",
+ iter.next().name()); // same level-1
+ assertEquals("10da5895682013006950e7da534b705252b03be6",
+ iter.next().name()); // same level-1
+ assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8",
+ iter.next().name());
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java
index cb977bd601..acc36d76f4 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java
@@ -40,6 +40,7 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefRename;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
@@ -111,16 +112,17 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertNotSame(newid, r.getObjectId());
assertSame(ObjectId.class, r.getObjectId().getClass());
assertEquals(newid, r.getObjectId());
- List<ReflogEntry> reverseEntries1 = db
+ List<ReflogEntry> reverseEntries1 = db.getRefDatabase()
.getReflogReader("refs/heads/abc").getReverseEntries();
ReflogEntry entry1 = reverseEntries1.get(0);
assertEquals(1, reverseEntries1.size());
assertEquals(ObjectId.zeroId(), entry1.getOldId());
assertEquals(r.getObjectId(), entry1.getNewId());
- assertEquals(new PersonIdent(db).toString(), entry1.getWho().toString());
+ assertEquals(new PersonIdent(db).toString(),
+ entry1.getWho().toString());
assertEquals("", entry1.getComment());
- List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD")
- .getReverseEntries();
+ List<ReflogEntry> reverseEntries2 = db.getRefDatabase()
+ .getReflogReader("HEAD").getReverseEntries();
assertEquals(0, reverseEntries2.size());
}
@@ -136,8 +138,11 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
final RefUpdate ru2 = updateRef(newRef2);
Result update2 = ru2.update();
assertEquals(Result.LOCK_FAILURE, update2);
- assertEquals(1, db.getReflogReader("refs/heads/z").getReverseEntries().size());
- assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(1, refDb.getReflogReader("refs/heads/z")
+ .getReverseEntries().size());
+ assertEquals(0,
+ refDb.getReflogReader("HEAD").getReverseEntries().size());
}
@Test
@@ -147,8 +152,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
final RefUpdate ru = updateRef(newRef);
Result update = ru.update();
assertEquals(Result.LOCK_FAILURE, update);
- assertNull(db.getReflogReader("refs/heads/master/x"));
- assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
+ RefDatabase refDb = db.getRefDatabase();
+ assertNull(refDb.getReflogReader("refs/heads/master/x"));
+ assertEquals(0,
+ refDb.getReflogReader("HEAD").getReverseEntries().size());
}
@Test
@@ -163,9 +170,12 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
final RefUpdate ru2 = updateRef(newRef2);
Result update2 = ru2.update();
assertEquals(Result.LOCK_FAILURE, update2);
- assertEquals(1, db.getReflogReader("refs/heads/z/a").getReverseEntries().size());
- assertNull(db.getReflogReader("refs/heads/z"));
- assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(1, refDb.getReflogReader("refs/heads/z/a")
+ .getReverseEntries().size());
+ assertNull(refDb.getReflogReader("refs/heads/z"));
+ assertEquals(0,
+ refDb.getReflogReader("HEAD").getReverseEntries().size());
}
@Test
@@ -175,8 +185,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
final RefUpdate ru = updateRef(newRef);
Result update = ru.update();
assertEquals(Result.LOCK_FAILURE, update);
- assertNull(db.getReflogReader("refs/heads/prefix"));
- assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
+ RefDatabase refDb = db.getRefDatabase();
+ assertNull(refDb.getReflogReader("refs/heads/prefix"));
+ assertEquals(0,
+ refDb.getReflogReader("HEAD").getReverseEntries().size());
}
/**
@@ -197,8 +209,11 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
Result delete = updateRef2.delete();
assertEquals(Result.REJECTED_CURRENT_BRANCH, delete);
assertEquals(pid, db.resolve("refs/heads/master"));
- assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size());
- assertEquals(0,db.getReflogReader("HEAD").getReverseEntries().size());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(1, refDb.getReflogReader("refs/heads/master")
+ .getReverseEntries().size());
+ assertEquals(0,
+ refDb.getReflogReader("HEAD").getReverseEntries().size());
}
@Test
@@ -209,7 +224,8 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
updateRef.setForceUpdate(true);
Result update = updateRef.update();
assertEquals(Result.FORCED, update);
- assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size());
+ assertEquals(1, db.getRefDatabase().getReflogReader("refs/heads/master")
+ .getReverseEntries().size());
}
@Test
@@ -219,15 +235,18 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
ref.update(); // create loose ref
ref = updateRef(newRef); // refresh
delete(ref, Result.NO_CHANGE);
- assertNull(db.getReflogReader("refs/heads/abc"));
+ assertNull(db.getRefDatabase().getReflogReader("refs/heads/abc"));
}
@Test
public void testDeleteHead() throws IOException {
final RefUpdate ref = updateRef(Constants.HEAD);
delete(ref, Result.REJECTED_CURRENT_BRANCH, true, false);
- assertEquals(0, db.getReflogReader("refs/heads/master").getReverseEntries().size());
- assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(0, refDb.getReflogReader("refs/heads/master")
+ .getReverseEntries().size());
+ assertEquals(0,
+ refDb.getReflogReader("HEAD").getReverseEntries().size());
}
@Test
@@ -423,7 +442,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
// the branch HEAD referred to is left untouched
assertEquals(pid, db.resolve("refs/heads/master"));
- ReflogReader reflogReader = db.getReflogReader("HEAD");
+ ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD");
ReflogEntry e = reflogReader.getReverseEntries().get(0);
assertEquals(pid, e.getOldId());
assertEquals(ppid, e.getNewId());
@@ -453,7 +472,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
// the branch HEAD referred to is left untouched
assertNull(db.resolve("refs/heads/unborn"));
- ReflogReader reflogReader = db.getReflogReader("HEAD");
+ ReflogReader reflogReader = db.getRefDatabase().getReflogReader("HEAD");
ReflogEntry e = reflogReader.getReverseEntries().get(0);
assertEquals(ObjectId.zeroId(), e.getOldId());
assertEquals(ppid, e.getNewId());
@@ -691,9 +710,12 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertEquals(Result.RENAMED, result);
assertEquals(rb, db.resolve("refs/heads/new/name"));
assertNull(db.resolve("refs/heads/b"));
- assertEquals(1, db.getReflogReader("new/name").getReverseEntries().size());
- assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name")
- .getLastEntry().getComment());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(1, refDb.getReflogReader("refs/heads/new/name")
+ .getReverseEntries().size());
+ assertEquals("Branch: renamed b to new/name",
+ refDb.getReflogReader("refs/heads/new/name").getLastEntry()
+ .getComment());
assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged
}
@@ -713,11 +735,15 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertEquals(Result.RENAMED, result);
assertEquals(rb, db.resolve("refs/heads/new/name"));
assertNull(db.resolve("refs/heads/b"));
- assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size());
- assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name")
- .getLastEntry().getComment());
- assertEquals("Just a message", db.getReflogReader("new/name")
- .getReverseEntries().get(1).getComment());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(2, refDb.getReflogReader("refs/heads/new/name")
+ .getReverseEntries().size());
+ assertEquals("Branch: renamed b to new/name",
+ refDb.getReflogReader("refs/heads/new/name").getLastEntry()
+ .getComment());
+ assertEquals("Just a message",
+ refDb.getReflogReader("refs/heads/new/name").getReverseEntries()
+ .get(1).getComment());
assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged
}
@@ -737,13 +763,20 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertEquals(Result.RENAMED, result);
assertEquals(rb, db.resolve("refs/heads/new/name"));
assertNull(db.resolve("refs/heads/b"));
- assertEquals("Branch: renamed b to new/name", db.getReflogReader(
- "new/name").getLastEntry().getComment());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals("Branch: renamed b to new/name",
+ refDb.getReflogReader("refs/heads/new/name").getLastEntry()
+ .getComment());
assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
assertEquals(rb, db.resolve(Constants.HEAD));
- assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size());
- assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name").getReverseEntries().get(0).getComment());
- assertEquals("Just a message", db.getReflogReader("new/name").getReverseEntries().get(1).getComment());
+ assertEquals(2, refDb.getReflogReader("refs/heads/new/name")
+ .getReverseEntries().size());
+ assertEquals("Branch: renamed b to new/name",
+ refDb.getReflogReader("refs/heads/new/name").getReverseEntries()
+ .get(0).getComment());
+ assertEquals("Just a message",
+ refDb.getReflogReader("refs/heads/new/name").getReverseEntries()
+ .get(1).getComment());
}
@Test
@@ -766,11 +799,17 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertEquals(Result.RENAMED, result);
assertEquals(rb2, db.resolve("refs/heads/new/name"));
assertNull(db.resolve("refs/heads/b"));
- assertEquals("Branch: renamed b to new/name", db.getReflogReader(
- "new/name").getLastEntry().getComment());
- assertEquals(3, db.getReflogReader("refs/heads/new/name").getReverseEntries().size());
- assertEquals("Branch: renamed b to new/name", db.getReflogReader("refs/heads/new/name").getReverseEntries().get(0).getComment());
- assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals("Branch: renamed b to new/name",
+ refDb.getReflogReader("refs/heads/new/name").getLastEntry()
+ .getComment());
+ assertEquals(3, refDb.getReflogReader("refs/heads/new/name")
+ .getReverseEntries().size());
+ assertEquals("Branch: renamed b to new/name",
+ refDb.getReflogReader("refs/heads/new/name").getReverseEntries()
+ .get(0).getComment());
+ assertEquals(0,
+ refDb.getReflogReader("HEAD").getReverseEntries().size());
// make sure b's log file is gone too.
assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists());
@@ -789,9 +828,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
ObjectId oldfromId = db.resolve(fromName);
ObjectId oldHeadId = db.resolve(Constants.HEAD);
writeReflog(db, oldfromId, "Just a message", fromName);
- List<ReflogEntry> oldFromLog = db
+ RefDatabase refDb = db.getRefDatabase();
+ List<ReflogEntry> oldFromLog = refDb
.getReflogReader(fromName).getReverseEntries();
- List<ReflogEntry> oldHeadLog = oldHeadId != null ? db
+ List<ReflogEntry> oldHeadLog = oldHeadId != null ? refDb
.getReflogReader(Constants.HEAD).getReverseEntries() : null;
assertTrue("internal check, we have a log", new File(db.getDirectory(),
@@ -818,10 +858,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertEquals(oldHeadId, db.resolve(Constants.HEAD));
assertEquals(oldfromId, db.resolve(fromName));
assertNull(db.resolve(toName));
- assertEquals(oldFromLog.toString(), db.getReflogReader(fromName)
+ assertEquals(oldFromLog.toString(), refDb.getReflogReader(fromName)
.getReverseEntries().toString());
if (oldHeadId != null && oldHeadLog != null)
- assertEquals(oldHeadLog.toString(), db.getReflogReader(
+ assertEquals(oldHeadLog.toString(), refDb.getReflogReader(
Constants.HEAD).getReverseEntries().toString());
} finally {
lockFile.unlock();
@@ -942,15 +982,18 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertEquals(Result.RENAMED, result);
assertNull(db.resolve("refs/heads/a"));
assertEquals(rb, db.resolve("refs/heads/a/b"));
- assertEquals(3, db.getReflogReader("a/b").getReverseEntries().size());
- assertEquals("Branch: renamed a to a/b", db.getReflogReader("a/b")
- .getReverseEntries().get(0).getComment());
- assertEquals("Just a message", db.getReflogReader("a/b")
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(3, refDb.getReflogReader("refs/heads/a/b")
+ .getReverseEntries().size());
+ assertEquals("Branch: renamed a to a/b",
+ refDb.getReflogReader("refs/heads/a/b").getReverseEntries()
+ .get(0).getComment());
+ assertEquals("Just a message", refDb.getReflogReader("refs/heads/a/b")
.getReverseEntries().get(1).getComment());
- assertEquals("Setup", db.getReflogReader("a/b").getReverseEntries()
- .get(2).getComment());
+ assertEquals("Setup", refDb.getReflogReader("refs/heads/a/b")
+ .getReverseEntries().get(2).getComment());
// same thing was logged to HEAD
- assertEquals("Branch: renamed a to a/b", db.getReflogReader("HEAD")
+ assertEquals("Branch: renamed a to a/b", refDb.getReflogReader("HEAD")
.getReverseEntries().get(0).getComment());
}
@@ -978,15 +1021,20 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
assertNull(db.resolve("refs/heads/prefix/a"));
assertEquals(rb, db.resolve("refs/heads/prefix"));
- assertEquals(3, db.getReflogReader("prefix").getReverseEntries().size());
- assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader(
- "prefix").getReverseEntries().get(0).getComment());
- assertEquals("Just a message", db.getReflogReader("prefix")
- .getReverseEntries().get(1).getComment());
- assertEquals("Setup", db.getReflogReader("prefix").getReverseEntries()
- .get(2).getComment());
- assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader(
- "HEAD").getReverseEntries().get(0).getComment());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(3, refDb.getReflogReader("refs/heads/prefix")
+ .getReverseEntries().size());
+ assertEquals("Branch: renamed prefix/a to prefix",
+ refDb.getReflogReader("refs/heads/prefix").getReverseEntries()
+ .get(0).getComment());
+ assertEquals("Just a message",
+ refDb.getReflogReader("refs/heads/prefix").getReverseEntries()
+ .get(1).getComment());
+ assertEquals("Setup", refDb.getReflogReader("refs/heads/prefix")
+ .getReverseEntries().get(2).getComment());
+ assertEquals("Branch: renamed prefix/a to prefix",
+ refDb.getReflogReader("HEAD").getReverseEntries().get(0)
+ .getComment());
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java
index eb521ff9eb..16645cbcd7 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogReaderTest.java
@@ -27,6 +27,7 @@ import org.eclipse.jgit.lib.CheckoutEntry;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
@@ -154,18 +155,22 @@ public class ReflogReaderTest extends SampleDataRepositoryTestCase {
setupReflog("logs/refs/heads/a", aLine);
setupReflog("logs/refs/heads/master", masterLine);
setupReflog("logs/HEAD", headLine);
- assertEquals("branch: change to master", db.getReflogReader("master")
- .getLastEntry().getComment());
- assertEquals("branch: change to a", db.getReflogReader("a")
- .getLastEntry().getComment());
- assertEquals("branch: change to HEAD", db.getReflogReader("HEAD")
- .getLastEntry().getComment());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals("branch: change to master",
+ refDb.getReflogReader("refs/heads/master").getLastEntry()
+ .getComment());
+ assertEquals("branch: change to a",
+ refDb.getReflogReader("refs/heads/a").getLastEntry()
+ .getComment());
+ assertEquals("branch: change to HEAD",
+ refDb.getReflogReader("HEAD").getLastEntry().getComment());
}
@Test
public void testReadLineWithMissingComment() throws Exception {
setupReflog("logs/refs/heads/master", oneLineWithoutComment);
- final ReflogReader reader = db.getReflogReader("master");
+ final ReflogReader reader = db.getRefDatabase()
+ .getReflogReader("refs/heads/master");
ReflogEntry e = reader.getLastEntry();
assertEquals(ObjectId
.fromString("da85355dfc525c9f6f3927b876f379f46ccf826e"), e
@@ -183,15 +188,18 @@ public class ReflogReaderTest extends SampleDataRepositoryTestCase {
@Test
public void testNoLog() throws Exception {
- assertEquals(0, db.getReflogReader("master").getReverseEntries().size());
- assertNull(db.getReflogReader("master").getLastEntry());
+ RefDatabase refDb = db.getRefDatabase();
+ assertEquals(0,
+ refDb.getReflogReader("refs/heads/master").getReverseEntries()
+ .size());
+ assertNull(refDb.getReflogReader("refs/heads/master").getLastEntry());
}
@Test
public void testCheckout() throws Exception {
setupReflog("logs/HEAD", switchBranch);
- List<ReflogEntry> entries = db.getReflogReader(Constants.HEAD)
- .getReverseEntries();
+ List<ReflogEntry> entries = db.getRefDatabase()
+ .getReflogReader(Constants.HEAD).getReverseEntries();
assertEquals(1, entries.size());
ReflogEntry entry = entries.get(0);
CheckoutEntry checkout = entry.parseCheckout();
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java
index 8e9b7b84bd..a8363336d9 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ReflogWriterTest.java
@@ -16,6 +16,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.time.Instant;
+import java.time.ZoneOffset;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
@@ -32,7 +34,7 @@ public class ReflogWriterTest extends SampleDataRepositoryTestCase {
ReflogWriter writer =
new ReflogWriter((RefDirectory) db.getRefDatabase());
PersonIdent ident = new PersonIdent("John Doe", "john@doe.com",
- 1243028200000L, 120);
+ Instant.ofEpochMilli(1243028200000L), ZoneOffset.ofHours(2));
ObjectId oldId = ObjectId
.fromString("da85355dfc525c9f6f3927b876f379f46ccf826e");
ObjectId newId = ObjectId
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexBuilderTest.java
new file mode 100644
index 0000000000..e6fefc623d
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexBuilderTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024, GerritForge Inc. 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.midx;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndexLoader.MultiPackIndexBuilder;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndexLoader.MultiPackIndexFormatException;
+import org.junit.Test;
+
+public class MultiPackIndexBuilderTest {
+
+ @Test
+ public void testRepeatedChunk() throws Exception {
+ byte[] buffer = new byte[2048];
+
+ MultiPackIndexBuilder builder1 = MultiPackIndexBuilder.builder();
+ builder1.addOidFanout(buffer);
+ Exception e1 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ builder1.addOidFanout(buffer);
+ });
+ assertEquals("midx chunk id 0x4f494446 appears multiple times",
+ e1.getMessage());
+
+ MultiPackIndexBuilder builder2 = MultiPackIndexBuilder.builder();
+ builder2.addOidLookUp(buffer);
+ Exception e2 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ builder2.addOidLookUp(buffer);
+ });
+ assertEquals("midx chunk id 0x4f49444c appears multiple times",
+ e2.getMessage());
+
+ MultiPackIndexBuilder builder3 = MultiPackIndexBuilder.builder();
+ builder3.addObjectOffsets(buffer);
+ Exception e3 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ builder3.addObjectOffsets(buffer);
+ });
+ assertEquals("midx chunk id 0x4f4f4646 appears multiple times",
+ e3.getMessage());
+
+ MultiPackIndexBuilder builder4 = MultiPackIndexBuilder.builder();
+ builder4.addPackNames(buffer);
+ Exception e4 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ builder4.addPackNames(buffer);
+ });
+ assertEquals("midx chunk id 0x504e414d appears multiple times",
+ e4.getMessage());
+
+ MultiPackIndexBuilder builder5 = MultiPackIndexBuilder.builder();
+ builder5.addBitmappedPacks(buffer);
+ Exception e5 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ builder5.addBitmappedPacks(buffer);
+ });
+ assertEquals("midx chunk id 0x42544d50 appears multiple times",
+ e5.getMessage());
+
+ MultiPackIndexBuilder builder6 = MultiPackIndexBuilder.builder();
+ builder6.addObjectLargeOffsets(buffer);
+ Exception e6 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ builder6.addObjectLargeOffsets(buffer);
+ });
+ assertEquals("midx chunk id 0x4c4f4646 appears multiple times",
+ e6.getMessage());
+
+ MultiPackIndexBuilder builder7 = MultiPackIndexBuilder.builder();
+ builder7.addReverseIndex(buffer);
+ Exception e7 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ builder7.addReverseIndex(buffer);
+ });
+ assertEquals("midx chunk id 0x52494458 appears multiple times",
+ e7.getMessage());
+ }
+
+ @Test
+ public void testNeededChunk() {
+ byte[] buffer = new byte[2048];
+
+ Exception e1 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ MultiPackIndexBuilder.builder().addOidLookUp(buffer).build();
+ });
+ assertEquals("midx 0x4f494446 chunk has not been loaded",
+ e1.getMessage());
+
+ Exception e2 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ MultiPackIndexBuilder.builder().addOidFanout(buffer)
+ .addOidLookUp(buffer).build();
+ });
+ assertEquals("midx 0x504e414d chunk has not been loaded",
+ e2.getMessage());
+
+ Exception e3 = assertThrows(MultiPackIndexFormatException.class, () -> {
+ MultiPackIndexBuilder.builder().addOidFanout(buffer)
+ .addOidLookUp(buffer).addPackNames(buffer).build();
+ });
+ assertEquals("midx 0x4f4f4646 chunk has not been loaded",
+ e3.getMessage());
+ }
+}
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
new file mode 100644
index 0000000000..494f1d1137
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoaderTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2024, GerritForge Inc. 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.midx;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.junit.FakeIndexFactory;
+import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.junit.Test;
+
+/**
+ * Test that the loader accepts valid files, discard broken files
+ * <p>
+ * Contents and lookups are covered in the MultiPackIndexTest
+ */
+public class MultiPackIndexLoaderTest {
+
+ @Test
+ public void load_validFile_basic_upstream() throws Exception {
+ MultiPackIndex midx = MultiPackIndexLoader
+ .open(JGitTestUtil.getTestResourceFile("multi-pack-index.v1"));
+ assertNotNull(midx);
+ }
+
+ @Test
+ public void load_validFile_basic_jgit() throws Exception {
+ PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000001", 500),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000005", 12),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000010", 1500)));
+ PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000002", 501),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000003", 13),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000015", 1501)));
+ PackIndex idxThree = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000004", 502),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000007", 14),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000012", 1502)));
+
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo, "p3",
+ idxThree);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+ assertNotNull(midx);
+ }
+
+ @Test
+ public void load_emptyFile() {
+ assertThrows(IOException.class, () -> MultiPackIndexLoader
+ .read(new ByteArrayInputStream(new byte[0])));
+ }
+
+ @Test
+ public void load_rubbishFile() {
+ assertThrows(MultiPackIndexLoader.MultiPackIndexFormatException.class,
+ () -> MultiPackIndexLoader.read(new ByteArrayInputStream(
+ "More than 12 bytes of not-midx".getBytes(UTF_8))));
+ }
+}
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
new file mode 100644
index 0000000000..ab452854b2
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexTest.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2024, GerritForge Inc. 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.midx;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.junit.FakeIndexFactory;
+import org.eclipse.jgit.junit.JGitTestUtil;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+
+public class MultiPackIndexTest {
+
+ @Test
+ public void basic_upstream() throws IOException {
+ int knownPackId = 22;
+ int knowOffset = 258;
+ String knownOid = "3f4ee50f784c1e9550f09a67d2ffc1bc76917bdc";
+ String knownPackName = "pack-e4b191e4343f2b7ff851026c2d8595a001077344.idx";
+ String[] packNames = {
+ "pack-15d67b35f2b6a66ff995e09cedb36b101e0e0262.idx",
+ "pack-1a979514a5965e71523187a17806e03af44344ed.idx",
+ "pack-1de6731c035633ba8f5b41dacbc680a5a36ddd90.idx",
+ "pack-1ee98948e4e362c56f3cdec7f5837d06e152854f.idx",
+ "pack-1f6fe52ac3d33f3091d8eb8497474554bfa80bc4.idx",
+ "pack-34b1aa6b437a9d968412454204c2676a88dc55fa.idx",
+ "pack-3b245f7b4aff32a52d0520608f662bbf403792b9.idx",
+ "pack-47901f7f8d1c440492035c4165796a330c7f79e0.idx",
+ "pack-4e7f889b79aea8905a0062ce1bd68e5ef3af6a55.idx",
+ "pack-71ea652e4aea2cbc609545b4fbc3eda6325d88a1.idx",
+ "pack-723b1238411a4257c18167e91fbabed313ba332f.idx",
+ "pack-7bd57092a7daa4dc31277e1ec86f3de8d968ae17.idx",
+ "pack-883d4f469c5ea0f6d373ee623a758aeaf17715fc.idx",
+ "pack-8eadd378a011ddaa5ec751f2a6d9789ef501120f.idx",
+ "pack-92221b6f79a211944ccc6740fc22c9553ea1ba22.idx",
+ "pack-b139d0cae5f54c70d057a8f4d2cf99f0ae0c326c.idx",
+ "pack-b4f5c96d1fa6b1fac17a2a43710693c5514a9224.idx",
+ "pack-bed4bc1521f965e55a5a8a58dffaaefc70ea4753.idx",
+ "pack-cdc6baa7d90707a3c0dac4c188f797f0f79b97bb.idx",
+ "pack-d6d58a58fa24b74c8c082f4f63c4d2ddfb824cc9.idx",
+ "pack-daec59ae07f1091f3b81bd8266481bb5db3c868a.idx",
+ "pack-e2197d60e09ad9091407eff4e06d39ec940851e1.idx",
+ "pack-e4b191e4343f2b7ff851026c2d8595a001077344.idx",
+ "pack-eedf783b5da4caa57be33b08990fe57f245a7413.idx",
+ "pack-efb23e968801b9050bc70f0115a8a0eec88fb879.idx",
+ "pack-f919c0660c207ddf6bb0569a3041d682d19fb4f7.idx" };
+ MultiPackIndex midx = MultiPackIndexLoader
+ .open(JGitTestUtil.getTestResourceFile("multi-pack-index.v1"));
+ assertNotNull(midx);
+ assertArrayEquals(packNames, midx.getPackNames());
+
+ MultiPackIndex.PackOffset oo = midx.find(ObjectId.fromString(knownOid));
+
+ assertEquals(knowOffset, oo.getOffset());
+ assertEquals(knownPackId, oo.getPackId());
+ assertEquals(knownPackName, midx.getPackNames()[oo.getPackId()]);
+ }
+
+ @Test
+ public void basicMidx() throws IOException {
+ PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000001", 500),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000005", 12),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000010", 1500)));
+ PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000002", 501),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000003", 13),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000015", 1501)));
+ PackIndex idxThree = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000004", 502),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000007", 14),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000012", 1502)));
+
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo, "p3",
+ idxThree);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+ assertEquals(3, midx.getPackNames().length);
+ assertInIndex(midx, 0, "0000000000000000000000000000000000000001", 500);
+ assertInIndex(midx, 0, "0000000000000000000000000000000000000005", 12);
+ assertInIndex(midx, 0, "0000000000000000000000000000000000000010",
+ 1500);
+ assertInIndex(midx, 1, "0000000000000000000000000000000000000002", 501);
+ assertInIndex(midx, 1, "0000000000000000000000000000000000000003", 13);
+ assertInIndex(midx, 1, "0000000000000000000000000000000000000015",
+ 1501);
+ assertInIndex(midx, 2, "0000000000000000000000000000000000000004", 502);
+ assertInIndex(midx, 2, "0000000000000000000000000000000000000007", 14);
+ assertInIndex(midx, 2, "0000000000000000000000000000000000000012",
+ 1502);
+
+ assertNull(midx.find(ObjectId.zeroId()));
+ }
+
+ @Test
+ public void jgit_largeOffsetChunk() throws IOException {
+ PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000001", (1L << 34)),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000005", 12)));
+ PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000002", (1L << 35)),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000003", 13)));
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+ assertEquals(2, midx.getPackNames().length);
+ assertInIndex(midx, 0, "0000000000000000000000000000000000000001",
+ (1L << 34));
+ assertInIndex(midx, 0, "0000000000000000000000000000000000000005", 12);
+ assertInIndex(midx, 1, "0000000000000000000000000000000000000002",
+ (1L << 35));
+ }
+
+ @Test
+ public void jgit_largeOffset_noChunk() throws IOException {
+ // All offsets fit in 32 bits, no large offset chunk
+ // Most significant bit to 1 is still valid offset
+ PackIndex idxOne = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000001",
+ 0xff00_0000),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000005", 12)));
+ PackIndex idxTwo = FakeIndexFactory.indexOf(List.of(
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000002", 501),
+ new FakeIndexFactory.IndexObject(
+ "0000000000000000000000000000000000000003", 13)));
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+ assertEquals(2, midx.getPackNames().length);
+ assertInIndex(midx, 0, "0000000000000000000000000000000000000001",
+ 0xff00_0000L);
+ assertInIndex(midx, 0, "0000000000000000000000000000000000000005", 12);
+ }
+
+ @Test
+ public void jgit_resolve() throws IOException {
+ AbbreviatedObjectId abbrev = AbbreviatedObjectId
+ .fromString("32fe829a1c");
+
+ PackIndex idxOne = indexWith(
+ // Noise
+ "0000000000000000000000000000000000000001",
+ "3000000000000000000000000000000000000005",
+ // One before abbrev
+ "32fe829a1b000000000000000000000000000001",
+ // matches
+ "32fe829a1c000000000000000000000000000001",
+ "32fe829a1c000000000000000000000000000100",
+ // One after abbrev
+ "32fe829a1d000000000000000000000000000000");
+ PackIndex idxTwo = indexWith(
+ // Noise
+ "8888880000000000000000000000000000000002",
+ "bbbbbb0000000000000000000000000000000003",
+ // Match
+ "32fe829a1c000000000000000000000000000010");
+
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+
+
+ Set<ObjectId> results = new HashSet<>();
+ midx.resolve(results, abbrev, 100);
+
+ assertEquals(3, results.size());
+ assertTrue(results.contains(ObjectId
+ .fromString("32fe829a1c000000000000000000000000000001")));
+ assertTrue(results.contains(ObjectId
+ .fromString("32fe829a1c000000000000000000000000000010")));
+ assertTrue(results.contains(ObjectId
+ .fromString("32fe829a1c000000000000000000000000000100")));
+
+ }
+
+ @Test
+ public void jgit_resolve_matchLimit() throws IOException {
+ AbbreviatedObjectId abbrev = AbbreviatedObjectId
+ .fromString("32fe829a1c");
+
+ PackIndex idxOne = indexWith(
+ // Noise
+ "0000000000000000000000000000000000000001",
+ "3000000000000000000000000000000000000005",
+ // One before abbrev
+ "32fe829a1b000000000000000000000000000001",
+ // matches
+ "32fe829a1c000000000000000000000000000001",
+ "32fe829a1c000000000000000000000000000100",
+ // One after abbrev
+ "32fe829a1d000000000000000000000000000000");
+ PackIndex idxTwo = indexWith(
+ // Noise
+ "8888880000000000000000000000000000000002",
+ "bbbbbb0000000000000000000000000000000003",
+ // Match
+ "32fe829a1c000000000000000000000000000010");
+
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+
+
+ Set<ObjectId> results = new HashSet<>();
+ midx.resolve(results, abbrev, 2);
+
+ assertEquals(2, results.size());
+ assertTrue(results.contains(ObjectId
+ .fromString("32fe829a1c000000000000000000000000000001")));
+ assertTrue(results.contains(ObjectId
+ .fromString("32fe829a1c000000000000000000000000000010")));
+ }
+
+ @Test
+ public void jgit_resolve_noMatches() throws IOException {
+ AbbreviatedObjectId abbrev = AbbreviatedObjectId
+ .fromString("4400000000");
+
+ PackIndex idxOne = indexWith(
+ "0000000000000000000000000000000000000001",
+ "3000000000000000000000000000000000000005",
+ "32fe829a1b000000000000000000000000000001",
+ "32fe829a1c000000000000000000000000000001",
+ "32fe829a1c000000000000000000000000000100",
+ "32fe829a1d000000000000000000000000000000");
+ PackIndex idxTwo = indexWith(
+ // Noise
+ "8888880000000000000000000000000000000002",
+ "bbbbbb0000000000000000000000000000000003",
+ "32fe829a1c000000000000000000000000000010");
+
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+
+
+ Set<ObjectId> results = new HashSet<>();
+ midx.resolve(results, abbrev, 200);
+
+ assertEquals(0, results.size());
+ }
+
+ @Test
+ public void jgit_resolve_empty() throws IOException {
+ AbbreviatedObjectId abbrev = AbbreviatedObjectId
+ .fromString("4400000000");
+
+ PackIndex idxOne = FakeIndexFactory.indexOf(List.of());
+ PackIndex idxTwo = FakeIndexFactory.indexOf(List.of());
+
+ Map<String, PackIndex> packs = Map.of("p1", idxOne, "p2", idxTwo);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+ MultiPackIndex midx = MultiPackIndexLoader
+ .read(new ByteArrayInputStream(out.toByteArray()));
+
+
+ Set<ObjectId> results = new HashSet<>();
+ midx.resolve(results, abbrev, 200);
+
+ assertEquals(0, results.size());
+ }
+
+ private static PackIndex indexWith(String... oids) {
+ List<FakeIndexFactory.IndexObject> idxObjs = new ArrayList<>(
+ oids.length);
+ int offset = 12;
+ for (String oid : oids) {
+ idxObjs.add(new FakeIndexFactory.IndexObject(oid, offset));
+ offset += 10;
+ }
+ return FakeIndexFactory.indexOf(idxObjs);
+ }
+
+ private static void assertInIndex(MultiPackIndex midx, int expectedPackId,
+ String oid, long expectedOffset) {
+ MultiPackIndex.PackOffset packOffset = midx
+ .find(ObjectId.fromString(oid));
+ assertNotNull(packOffset);
+ assertEquals("Wrong packId for " + oid, expectedPackId,
+ packOffset.getPackId());
+ assertEquals(expectedOffset, packOffset.getOffset());
+ }
+}
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
new file mode 100644
index 0000000000..8b57a2dcb4
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriterTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.midx;
+
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_LARGEOFFSETS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDLOOKUP;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_PACKNAMES;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_REVINDEX;
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.junit.FakeIndexFactory;
+import org.eclipse.jgit.junit.FakeIndexFactory.IndexObject;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.util.NB;
+import org.junit.Test;
+
+public class MultiPackIndexWriterTest {
+
+ @Test
+ public void write_allSmallOffsets() throws IOException {
+ PackIndex index1 = indexOf(
+ object("0000000000000000000000000000000000000001", 500),
+ object("0000000000000000000000000000000000000003", 1500),
+ object("0000000000000000000000000000000000000005", 3000));
+ PackIndex index2 = indexOf(
+ object("0000000000000000000000000000000000000002", 500),
+ object("0000000000000000000000000000000000000004", 1500),
+ object("0000000000000000000000000000000000000006", 3000));
+
+ Map<String, PackIndex> data = Map.of("packname1", index1, "packname2",
+ index2);
+
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, data);
+ // header (12 bytes)
+ // + chunkHeader (6 * 12 bytes)
+ // + fanout table (256 * 4 bytes)
+ // + OIDs (6 * 20 bytes)
+ // + (pack, offset) pairs (6 * 8)
+ // + RIDX (6 * 4 bytes)
+ // + packfile names (2 * 10)
+ // + checksum (20)
+ assertEquals(1340, out.size());
+ List<Integer> chunkIds = readChunkIds(out);
+ assertEquals(5, chunkIds.size());
+ assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
+ assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
+ assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
+ assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
+ assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+ }
+
+ @Test
+ public void write_smallOffset_limit() throws IOException {
+ PackIndex index1 = indexOf(
+ object("0000000000000000000000000000000000000001", 500),
+ object("0000000000000000000000000000000000000003", 1500),
+ 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);
+
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, data);
+ // header (12 bytes)
+ // + chunkHeader (6 * 12 bytes)
+ // + fanout table (256 * 4 bytes)
+ // + OIDs (6 * 20 bytes)
+ // + (pack, offset) pairs (6 * 8)
+ // + RIDX (6 * 4 bytes)
+ // + packfile names (2 * 10)
+ // + checksum (20)
+ assertEquals(1340, out.size());
+ List<Integer> chunkIds = readChunkIds(out);
+ assertEquals(5, chunkIds.size());
+ assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
+ assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
+ assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
+ assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
+ assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+ }
+
+ @Test
+ public void write_largeOffset() throws IOException {
+ PackIndex index1 = indexOf(
+ object("0000000000000000000000000000000000000001", 500),
+ object("0000000000000000000000000000000000000003", 1500),
+ object("0000000000000000000000000000000000000005", 1L << 32));
+ PackIndex index2 = indexOf(
+ object("0000000000000000000000000000000000000002", 500),
+ object("0000000000000000000000000000000000000004", 1500),
+ object("0000000000000000000000000000000000000006", 3000));
+ Map<String, PackIndex> data =
+ Map.of("packname1", index1, "packname2", index2);
+
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, data);
+ // header (12 bytes)
+ // + chunkHeader (7 * 12 bytes)
+ // + fanout table (256 * 4 bytes)
+ // + OIDs (6 * 20 bytes)
+ // + (pack, offset) pairs (6 * 8)
+ // + (large-offset) (1 * 8)
+ // + RIDX (6 * 4 bytes)
+ // + packfile names (2 * 10)
+ // + checksum (20)
+ assertEquals(1360, out.size());
+ List<Integer> chunkIds = readChunkIds(out);
+ assertEquals(6, chunkIds.size());
+ assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
+ assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
+ assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
+ assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_LARGEOFFSETS));
+ assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
+ assertEquals(5, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+ }
+
+ @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);
+ MultiPackIndexWriter writer = new MultiPackIndexWriter();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ writer.write(NullProgressMonitor.INSTANCE, out, packs);
+ List<Integer> chunkIds = readChunkIds(out);
+ assertEquals(1134, out.size());
+ assertEquals(5, chunkIds.size());
+ assertEquals(0, chunkIds.indexOf(MIDX_CHUNKID_OIDFANOUT));
+ assertEquals(1, chunkIds.indexOf(MIDX_CHUNKID_OIDLOOKUP));
+ assertEquals(2, chunkIds.indexOf(MIDX_CHUNKID_OBJECTOFFSETS));
+ assertEquals(3, chunkIds.indexOf(MIDX_CHUNKID_REVINDEX));
+ assertEquals(4, chunkIds.indexOf(MIDX_CHUNKID_PACKNAMES));
+ }
+
+ private List<Integer> readChunkIds(ByteArrayOutputStream out) {
+ List<Integer> chunkIds = new ArrayList<>();
+ byte[] raw = out.toByteArray();
+ int numChunks = raw[6];
+ int position = 12;
+ for (int i = 0; i < numChunks; i++) {
+ chunkIds.add(NB.decodeInt32(raw, position));
+ position += CHUNK_LOOKUP_WIDTH;
+ }
+ return chunkIds;
+ }
+
+ private static PackIndex indexOf(IndexObject... objs) {
+ return FakeIndexFactory.indexOf(Arrays.asList(objs));
+ }
+
+ private static IndexObject object(String name, long offset) {
+ return new IndexObject(name, offset);
+ }
+}
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
new file mode 100644
index 0000000000..8218cbc20d
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexMergerTest.java
@@ -0,0 +1,239 @@
+/*
+ * 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.midx;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.junit.FakeIndexFactory;
+import org.eclipse.jgit.junit.FakeIndexFactory.IndexObject;
+import org.junit.Test;
+
+public class PackIndexMergerTest {
+
+ @Test
+ public void rawIterator_noDuplicates() {
+ 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(
+ Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+ assertEquals(9, merger.getUniqueObjectCount());
+ assertEquals(3, merger.getPackCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator();
+ assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501);
+ assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13);
+ assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 502);
+ assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 14);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
+ 1500);
+ assertNextEntry(it, "0000000000000000000000000000000000000012", 2,
+ 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));
+ assertEquals(3, merger.getUniqueObjectCount());
+ assertEquals(3, merger.getPackCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ Iterator<PackIndexMerger.MidxMutableEntry> it = merger.rawIterator();
+ assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000001", 1, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000001", 2, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000005", 1, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000005", 2, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
+ 1500);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 1,
+ 1500);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 2,
+ 1500);
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void bySha1Iterator_noDuplicates() {
+ 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(
+ Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+ assertEquals(9, merger.getUniqueObjectCount());
+ assertEquals(3, merger.getPackCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator();
+ assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 501);
+ assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 13);
+ assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 502);
+ assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 14);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
+ 1500);
+ assertNextEntry(it, "0000000000000000000000000000000000000012", 2,
+ 1502);
+ assertNextEntry(it, "0000000000000000000000000000000000000015", 1,
+ 1501);
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void bySha1Iterator_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));
+ assertEquals(3, merger.getUniqueObjectCount());
+ assertEquals(3, merger.getPackCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator();
+ assertNextEntry(it, "0000000000000000000000000000000000000001", 0, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000005", 0, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
+ 1500);
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void bySha1Iterator_differentIndexSizes() {
+ PackIndex idxOne = indexOf(
+ oidOffset("0000000000000000000000000000000000000010", 1500));
+ PackIndex idxTwo = indexOf(
+ oidOffset("0000000000000000000000000000000000000002", 500),
+ oidOffset("0000000000000000000000000000000000000003", 12));
+ PackIndex idxThree = indexOf(
+ oidOffset("0000000000000000000000000000000000000004", 500),
+ oidOffset("0000000000000000000000000000000000000007", 12),
+ oidOffset("0000000000000000000000000000000000000012", 1500));
+ PackIndexMerger merger = new PackIndexMerger(
+ Map.of("p1", idxOne, "p2", idxTwo, "p3", idxThree));
+ assertEquals(6, merger.getUniqueObjectCount());
+ assertEquals(3, merger.getPackCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ Iterator<PackIndexMerger.MidxMutableEntry> it = merger.bySha1Iterator();
+ assertNextEntry(it, "0000000000000000000000000000000000000002", 1, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000003", 1, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000004", 2, 500);
+ assertNextEntry(it, "0000000000000000000000000000000000000007", 2, 12);
+ assertNextEntry(it, "0000000000000000000000000000000000000010", 0,
+ 1500);
+ assertNextEntry(it, "0000000000000000000000000000000000000012", 2,
+ 1500);
+ assertFalse(it.hasNext());
+ }
+
+ @Test
+ public void merger_noIndexes() {
+ PackIndexMerger merger = new PackIndexMerger(Map.of());
+ assertEquals(0, merger.getUniqueObjectCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ assertTrue(merger.getPackNames().isEmpty());
+ assertEquals(0, merger.getPackCount());
+ assertFalse(merger.bySha1Iterator().hasNext());
+ }
+
+ @Test
+ public void merger_emptyIndexes() {
+ PackIndexMerger merger = new PackIndexMerger(
+ Map.of("p1", indexOf(), "p2", indexOf()));
+ assertEquals(0, merger.getUniqueObjectCount());
+ assertFalse(merger.needsLargeOffsetsChunk());
+ assertEquals(2, merger.getPackNames().size());
+ assertEquals(2, merger.getPackCount());
+ assertFalse(merger.bySha1Iterator().hasNext());
+ }
+
+ @Test
+ public void bySha1Iterator_largeOffsets_needsChunk() {
+ PackIndex idx1 = indexOf(
+ oidOffset("0000000000000000000000000000000000000002", 1L << 32),
+ oidOffset("0000000000000000000000000000000000000004", 12));
+ PackIndex idx2 = indexOf(oidOffset(
+ "0000000000000000000000000000000000000003", (1L << 31) + 10));
+ PackIndexMerger merger = new PackIndexMerger(
+ Map.of("p1", idx1, "p2", idx2));
+ assertTrue(merger.needsLargeOffsetsChunk());
+ assertEquals(2, merger.getOffsetsOver31BitsCount());
+ assertEquals(3, merger.getUniqueObjectCount());
+ }
+
+ @Test
+ public void bySha1Iterator_largeOffsets_noChunk() {
+ // If no value is over 2^32-1, then we don't need large offset
+ PackIndex idx1 = indexOf(
+ oidOffset("0000000000000000000000000000000000000002",
+ (1L << 31) + 15),
+ oidOffset("0000000000000000000000000000000000000004", 12));
+ PackIndex idx2 = indexOf(oidOffset(
+ "0000000000000000000000000000000000000003", (1L << 31) + 10));
+ PackIndexMerger merger = new PackIndexMerger(
+ Map.of("p1", idx1, "p2", idx2));
+ assertFalse(merger.needsLargeOffsetsChunk());
+ assertEquals(2, merger.getOffsetsOver31BitsCount());
+ assertEquals(3, merger.getUniqueObjectCount());
+ }
+
+ private static void assertNextEntry(
+ Iterator<PackIndexMerger.MidxMutableEntry> it, String oid,
+ int packId, long offset) {
+ assertTrue(it.hasNext());
+ PackIndexMerger.MidxMutableEntry e = it.next();
+ assertEquals(oid, e.getObjectId().name());
+ assertEquals(packId, e.getPackId());
+ assertEquals(offset, e.getOffset());
+ }
+
+ private static IndexObject oidOffset(String oid, long offset) {
+ return new IndexObject(oid, offset);
+ }
+
+ private static PackIndex indexOf(IndexObject... objs) {
+ return FakeIndexFactory.indexOf(Arrays.asList(objs));
+ }
+}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java
new file mode 100644
index 0000000000..0b3ccacfc1
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/midx/PackIndexPeekIteratorTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.midx;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.Arrays;
+
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.junit.FakeIndexFactory;
+import org.junit.Test;
+
+public class PackIndexPeekIteratorTest {
+ @Test
+ public void next() {
+ PackIndex index1 = indexOf(
+ object("0000000000000000000000000000000000000001", 500),
+ object("0000000000000000000000000000000000000003", 1500),
+ object("0000000000000000000000000000000000000005", 3000));
+ PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1);
+ assertEquals("0000000000000000000000000000000000000001", it.next().name());
+ assertEquals("0000000000000000000000000000000000000003", it.next().name());
+ assertEquals("0000000000000000000000000000000000000005", it.next().name());
+ assertNull(it.next());
+ }
+
+ @Test
+ public void peek_doesNotAdvance() {
+ PackIndex index1 = indexOf(
+ object("0000000000000000000000000000000000000001", 500),
+ object("0000000000000000000000000000000000000003", 1500),
+ object("0000000000000000000000000000000000000005", 3000));
+ PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1);
+ it.next();
+ assertEquals("0000000000000000000000000000000000000001", it.peek().name());
+ assertEquals("0000000000000000000000000000000000000001", it.peek().name());
+ it.next();
+ assertEquals("0000000000000000000000000000000000000003", it.peek().name());
+ assertEquals("0000000000000000000000000000000000000003", it.peek().name());
+ it.next();
+ assertEquals("0000000000000000000000000000000000000005", it.peek().name());
+ assertEquals("0000000000000000000000000000000000000005", it.peek().name());
+ it.next();
+ assertNull(it.peek());
+ assertNull(it.peek());
+ }
+
+ @Test
+ public void empty() {
+ PackIndex index1 = indexOf();
+ PackIndexMerger.PackIndexPeekIterator it = new PackIndexMerger.PackIndexPeekIterator(0, index1);
+ assertNull(it.next());
+ assertNull(it.peek());
+ }
+
+ private static PackIndex indexOf(FakeIndexFactory.IndexObject... objs) {
+ return FakeIndexFactory.indexOf(Arrays.asList(objs));
+ }
+
+ private static FakeIndexFactory.IndexObject object(String name, long offset) {
+ return new FakeIndexFactory.IndexObject(name, offset);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java
index 6fc7f25475..62dbda47fd 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableCompactorTest.java
@@ -19,6 +19,8 @@ import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.time.Instant;
+import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -27,6 +29,7 @@ import org.eclipse.jgit.internal.storage.io.BlockSource;
import org.eclipse.jgit.internal.storage.reftable.ReftableWriter.Stats;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
+import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.junit.Test;
@@ -279,6 +282,95 @@ public class ReftableCompactorTest {
}
}
+ @Test
+ public void reflog_all() throws IOException {
+ byte[] inTab;
+ try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
+ ReftableWriter writer = new ReftableWriter(inBuf)
+ .setMinUpdateIndex(0).setMaxUpdateIndex(2).begin();
+ writer.writeLog(MASTER, 2, person(Instant.ofEpochSecond(500)),
+ id(3), id(4), null);
+ writer.writeLog(MASTER, 1, person(Instant.ofEpochSecond(300)),
+ id(2), id(3), null);
+ writer.writeLog(MASTER, 0, person(Instant.ofEpochSecond(100)),
+ id(1), id(2), null);
+ writer.finish();
+ inTab = inBuf.toByteArray();
+ }
+
+ ReftableCompactor compactor;
+ try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
+ compactor = new ReftableCompactor(outBuf);
+ // No setReflogExpire time is set
+ List<ReftableReader> readers = new ArrayList<>();
+ readers.add(read(inTab));
+ compactor.addAll(readers);
+ compactor.compact();
+ }
+ Stats stats = compactor.getStats();
+ assertEquals(3, stats.logCount());
+ }
+
+ @Test
+ public void reflog_setExpireOlderThan() throws IOException {
+ byte[] inTab;
+ try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
+ ReftableWriter writer = new ReftableWriter(inBuf)
+ .setMinUpdateIndex(0).setMaxUpdateIndex(2).begin();
+ writer.writeLog(MASTER, 2, person(Instant.ofEpochSecond(500)),
+ id(3), id(4), null);
+ writer.writeLog(MASTER, 1, person(Instant.ofEpochSecond(300)),
+ id(2), id(3), null);
+ writer.writeLog(MASTER, 0, person(Instant.ofEpochSecond(100)),
+ id(1), id(2), null);
+ writer.finish();
+ inTab = inBuf.toByteArray();
+ }
+
+ ReftableCompactor compactor;
+ try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
+ compactor = new ReftableCompactor(outBuf);
+ compactor.setReflogExpireOlderThan(Instant.ofEpochSecond(300));
+ List<ReftableReader> readers = new ArrayList<>();
+ readers.add(read(inTab));
+ compactor.addAll(readers);
+ compactor.compact();
+ }
+
+ Stats stats = compactor.getStats();
+ assertEquals(2, stats.logCount());
+ }
+
+ @Test
+ public void reflog_disable() throws IOException {
+ byte[] inTab;
+ try (ByteArrayOutputStream inBuf = new ByteArrayOutputStream()) {
+ ReftableWriter writer = new ReftableWriter(inBuf)
+ .setMinUpdateIndex(0).setMaxUpdateIndex(2).begin();
+ writer.writeLog(MASTER, 2, person(Instant.ofEpochSecond(500)),
+ id(3), id(4), null);
+ writer.writeLog(MASTER, 1, person(Instant.ofEpochSecond(300)),
+ id(2), id(3), null);
+ writer.writeLog(MASTER, 0, person(Instant.ofEpochSecond(100)),
+ id(1), id(2), null);
+ writer.finish();
+ inTab = inBuf.toByteArray();
+ }
+
+ ReftableCompactor compactor;
+ try (ByteArrayOutputStream outBuf = new ByteArrayOutputStream()) {
+ compactor = new ReftableCompactor(outBuf);
+ compactor.setReflogExpireOlderThan(Instant.MAX);
+ List<ReftableReader> readers = new ArrayList<>();
+ readers.add(read(inTab));
+ compactor.addAll(readers);
+ compactor.compact();
+ }
+
+ Stats stats = compactor.getStats();
+ assertEquals(0, stats.logCount());
+ }
+
private static Ref ref(String name, int id) {
return new ObjectIdRef.PeeledNonTag(PACKED, name, id(id));
}
@@ -296,6 +388,10 @@ public class ReftableCompactorTest {
return ObjectId.fromRaw(buf);
}
+ private static PersonIdent person(Instant when) {
+ return new PersonIdent("a. u. thor", "author@jgit.com", when, ZoneId.systemDefault());
+ }
+
private static ReftableReader read(byte[] table) {
return new ReftableReader(BlockSource.from(table));
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
index ea0d92acfd..a54002bc74 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/ReftableTest.java
@@ -29,6 +29,8 @@ import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -175,7 +177,8 @@ public class ReftableTest {
@Test
public void hasObjLogs() throws IOException {
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
String msg = "test";
ReftableConfig cfg = new ReftableConfig();
cfg.setIndexObjects(false);
@@ -617,7 +620,8 @@ public class ReftableTest {
.setMinUpdateIndex(1)
.setMaxUpdateIndex(2)
.begin();
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
String msg = "test";
writer.writeLog(MASTER, 1, who, ObjectId.zeroId(), id(1), msg);
@@ -633,7 +637,8 @@ public class ReftableTest {
.setMinUpdateIndex(1)
.setMaxUpdateIndex(1)
.begin();
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
String msg = "test";
writer.writeLog(NEXT, 1, who, ObjectId.zeroId(), id(1), msg);
@@ -647,7 +652,8 @@ public class ReftableTest {
public void withReflog() throws IOException {
Ref master = ref(MASTER, 1);
Ref next = ref(NEXT, 2);
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
String msg = "test";
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@@ -712,11 +718,14 @@ public class ReftableTest {
writer.writeRef(master);
writer.writeRef(next);
- PersonIdent who1 = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who1 = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
writer.writeLog(MASTER, 3, who1, ObjectId.zeroId(), id(1), "1");
- PersonIdent who2 = new PersonIdent("Log", "Ger", 1500079710, -8 * 60);
+ PersonIdent who2 = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
writer.writeLog(MASTER, 2, who2, id(1), id(2), "2");
- PersonIdent who3 = new PersonIdent("Log", "Ger", 1500079711, -8 * 60);
+ PersonIdent who3 = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
writer.writeLog(MASTER, 1, who3, id(2), id(3), "3");
writer.finish();
@@ -753,7 +762,8 @@ public class ReftableTest {
.setMaxUpdateIndex(1)
.setConfig(cfg)
.begin();
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
// Fill out the 1st ref block.
List<String> names = new ArrayList<>();
@@ -782,7 +792,8 @@ public class ReftableTest {
@Test
public void reflogSeek() throws IOException {
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochSecond(1500079709), ZoneOffset.ofHours(-8));
String msg = "test";
String msgNext = "test next";
@@ -827,7 +838,8 @@ public class ReftableTest {
@Test
public void reflogSeekPrefix() throws IOException {
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ReftableWriter writer = new ReftableWriter(buffer)
@@ -850,7 +862,8 @@ public class ReftableTest {
@Test
public void onlyReflog() throws IOException {
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
String msg = "test";
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@@ -916,7 +929,8 @@ public class ReftableTest {
writer.writeRef(ref);
}
- PersonIdent who = new PersonIdent("Log", "Ger", 1500079709, -8 * 60);
+ PersonIdent who = new PersonIdent("Log", "Ger",
+ Instant.ofEpochMilli(1500079709), ZoneOffset.ofHours(-8));
for (Ref ref : refs) {
writer.writeLog(ref.getName(), 1, who,
ObjectId.zeroId(), ref.getObjectId(),
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java
index 924703464b..1581d49797 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/junit/TestRepositoryTest.java
@@ -11,6 +11,7 @@
package org.eclipse.jgit.junit;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.time.Instant.EPOCH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -18,7 +19,6 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
-import java.util.Date;
import java.util.regex.Pattern;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
@@ -199,8 +199,8 @@ public class TestRepositoryTest {
assertEquals(orig.getAuthorIdent(), amended.getAuthorIdent());
// Committer name/email is the same, but time was incremented.
- assertEquals(new PersonIdent(orig.getCommitterIdent(), new Date(0)),
- new PersonIdent(amended.getCommitterIdent(), new Date(0)));
+ assertEquals(new PersonIdent(orig.getCommitterIdent(), EPOCH),
+ new PersonIdent(amended.getCommitterIdent(), EPOCH));
assertTrue(orig.getCommitTime() < amended.getCommitTime());
assertEquals("foo contents", blobAsString(amended, "foo"));
@@ -294,8 +294,8 @@ public class TestRepositoryTest {
assertEquals(toPick.getAuthorIdent(), result.getAuthorIdent());
// Committer name/email matches default, and time was incremented.
- assertEquals(new PersonIdent(head.getCommitterIdent(), new Date(0)),
- new PersonIdent(result.getCommitterIdent(), new Date(0)));
+ assertEquals(new PersonIdent(head.getCommitterIdent(), EPOCH),
+ new PersonIdent(result.getCommitterIdent(), EPOCH));
assertTrue(toPick.getCommitTime() < result.getCommitTime());
assertEquals("message to cherry-pick", result.getFullMessage());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java
index 31940a16f7..06fee8ea71 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java
@@ -1636,6 +1636,47 @@ public class ConfigTest {
assertFalse(config.get(CoreConfig.KEY).enableCommitGraph());
}
+ @Test
+ public void testGetNoDefaultBoolean() {
+ Config config = new Config();
+ assertNull(config.getBoolean("foo", "bar"));
+ assertNull(config.getBoolean("foo", "bar", "baz"));
+ }
+
+ @Test
+ public void testGetNoDefaultEnum() {
+ Config config = new Config();
+ assertNull(config.getEnum(new TestEnum[] { TestEnum.ONE_TWO }, "foo",
+ "bar", "baz"));
+ }
+
+ @Test
+ public void testGetNoDefaultInt() {
+ Config config = new Config();
+ assertNull(config.getInt("foo", "bar"));
+ assertNull(config.getInt("foo", "bar", "baz"));
+ }
+ @Test
+ public void testGetNoDefaultIntInRange() {
+ Config config = new Config();
+ assertNull(config.getIntInRange("foo", "bar", 1, 5));
+ assertNull(config.getIntInRange("foo", "bar", "baz", 1, 5));
+ }
+
+ @Test
+ public void testGetNoDefaultLong() {
+ Config config = new Config();
+ assertNull(config.getLong("foo", "bar"));
+ assertNull(config.getLong("foo", "bar", "baz"));
+ }
+
+ @Test
+ public void testGetNoDefaultTimeUnit() {
+ Config config = new Config();
+ assertNull(config.getTimeUnit("foo", "bar", "baz",
+ TimeUnit.SECONDS));
+ }
+
private static void assertValueRoundTrip(String value)
throws ConfigInvalidException {
assertValueRoundTrip(value, value);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java
index 2b7b6ca76c..cd98606e53 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java
@@ -2,7 +2,7 @@
* Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
- * Copyright (C) 2013, Robin Stocker <robin@nibor.org> and others
+ * Copyright (C) 2013, 2025 Robin Stocker <robin@nibor.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
@@ -539,7 +539,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertTrue(diff.getAssumeUnchanged().contains("file3"));
assertTrue(diff.getModified().contains("file"));
- git.add().addFilepattern(".").call();
+ git.add().addFilepattern(".").setAll(false).call();
iterator = new FileTreeIterator(db);
diff = new IndexDiff(db, Constants.HEAD, iterator);
@@ -551,6 +551,18 @@ public class IndexDiffTest extends RepositoryTestCase {
assertTrue(diff.getAssumeUnchanged().contains("file3"));
assertTrue(diff.getChanged().contains("file"));
assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
+
+ git.add().addFilepattern(".").call();
+
+ iterator = new FileTreeIterator(db);
+ diff = new IndexDiff(db, Constants.HEAD, iterator);
+ diff.diff();
+ assertEquals(1, diff.getAssumeUnchanged().size());
+ assertEquals(0, diff.getModified().size());
+ assertEquals(1, diff.getChanged().size());
+ assertTrue(diff.getAssumeUnchanged().contains("file2"));
+ assertTrue(diff.getChanged().contains("file"));
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java
index b02f245865..85f9612b6a 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefDatabaseConflictingNamesTest.java
@@ -71,6 +71,11 @@ public class RefDatabaseConflictingNamesTest {
}
@Override
+ public ReflogReader getReflogReader(Ref ref) throws IOException {
+ return null;
+ }
+
+ @Override
public void create() throws IOException {
// Not needed
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java
index 854180e3ea..a93937eeea 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java
@@ -16,6 +16,9 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.ZoneOffset;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.storage.file.FileBasedConfig;
@@ -24,22 +27,23 @@ import org.junit.Test;
public class ReflogConfigTest extends RepositoryTestCase {
@Test
public void testlogAllRefUpdates() throws Exception {
- long commitTime = 1154236443000L;
- int tz = -4 * 60;
+ Instant commitTime = Instant.ofEpochSecond(1154236443L);
+ ZoneOffset tz = ZoneOffset.ofHours(-4);
// check that there are no entries in the reflog and turn off writing
// reflogs
- assertTrue(db.getReflogReader(Constants.HEAD).getReverseEntries()
+ RefDatabase refDb = db.getRefDatabase();
+ assertTrue(refDb.getReflogReader(Constants.HEAD).getReverseEntries()
.isEmpty());
- final FileBasedConfig cfg = db.getConfig();
+ FileBasedConfig cfg = db.getConfig();
cfg.setBoolean("core", null, "logallrefupdates", false);
cfg.save();
// do one commit and check that reflog size is 0: no reflogs should be
// written
commit("A Commit\n", commitTime, tz);
- commitTime += 60 * 1000;
- assertTrue("Reflog for HEAD still contain no entry", db
+ commitTime = commitTime.plus(Duration.ofMinutes(1));
+ assertTrue("Reflog for HEAD still contain no entry", refDb
.getReflogReader(Constants.HEAD).getReverseEntries().isEmpty());
// set the logAllRefUpdates parameter to true and check it
@@ -52,10 +56,10 @@ public class ReflogConfigTest extends RepositoryTestCase {
// do one commit and check that reflog size is increased to 1
commit("A Commit\n", commitTime, tz);
- commitTime += 60 * 1000;
- assertTrue(
- "Reflog for HEAD should contain one entry",
- db.getReflogReader(Constants.HEAD).getReverseEntries().size() == 1);
+ commitTime = commitTime.plus(Duration.ofMinutes(1));
+ assertTrue("Reflog for HEAD should contain one entry",
+ refDb.getReflogReader(Constants.HEAD).getReverseEntries()
+ .size() == 1);
// set the logAllRefUpdates parameter to false and check it
cfg.setBoolean("core", null, "logallrefupdates", false);
@@ -67,10 +71,10 @@ public class ReflogConfigTest extends RepositoryTestCase {
// do one commit and check that reflog size is 2
commit("A Commit\n", commitTime, tz);
- commitTime += 60 * 1000;
- assertTrue(
- "Reflog for HEAD should contain two entries",
- db.getReflogReader(Constants.HEAD).getReverseEntries().size() == 2);
+ commitTime = commitTime.plus(Duration.ofMinutes(1));
+ assertTrue("Reflog for HEAD should contain two entries",
+ refDb.getReflogReader(Constants.HEAD).getReverseEntries()
+ .size() == 2);
// set the logAllRefUpdates parameter to false and check it
cfg.setEnum("core", null, "logallrefupdates",
@@ -84,13 +88,13 @@ public class ReflogConfigTest extends RepositoryTestCase {
// do one commit and check that reflog size is 3
commit("A Commit\n", commitTime, tz);
assertTrue("Reflog for HEAD should contain three entries",
- db.getReflogReader(Constants.HEAD).getReverseEntries()
+ refDb.getReflogReader(Constants.HEAD).getReverseEntries()
.size() == 3);
}
- private void commit(String commitMsg, long commitTime, int tz)
+ private void commit(String commitMsg, Instant commitTime, ZoneOffset tz)
throws IOException {
- final CommitBuilder commit = new CommitBuilder();
+ CommitBuilder commit = new CommitBuilder();
commit.setAuthor(new PersonIdent(author, commitTime, tz));
commit.setCommitter(new PersonIdent(committer, commitTime, tz));
commit.setMessage(commitMsg);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java
index ae811f830f..8865ba9ebd 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java
@@ -15,6 +15,9 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import java.time.Instant;
+import java.time.ZoneOffset;
+
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.junit.RepositoryTestCase;
@@ -162,7 +165,8 @@ public class CherryPickTest extends RepositoryTestCase {
final ObjectId[] parentIds) throws Exception {
final CommitBuilder c = new CommitBuilder();
c.setTreeId(treeB.writeTree(odi));
- c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
+ c.setAuthor(new PersonIdent("A U Thor", "a.u.thor",
+ Instant.ofEpochSecond(1), ZoneOffset.UTC));
c.setCommitter(c.getAuthor());
c.setParentIds(parentIds);
c.setMessage("Tree " + c.getTreeId().name());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java
index f410960bec..b1998f30f8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/GitlinkMergeTest.java
@@ -15,6 +15,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.time.Instant;
+import java.time.ZoneOffset;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.dircache.DirCache;
@@ -357,7 +359,8 @@ public class GitlinkMergeTest extends SampleDataRepositoryTestCase {
ObjectId[] parentIds) throws Exception {
CommitBuilder c = new CommitBuilder();
c.setTreeId(treeB.writeTree(odi));
- c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
+ c.setAuthor(new PersonIdent("A U Thor", "a.u.thor",
+ Instant.ofEpochSecond(1), ZoneOffset.UTC));
c.setCommitter(c.getAuthor());
c.setParentIds(parentIds);
c.setMessage("Tree " + c.getTreeId().name());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java
index 798aebe3b0..0016adfb66 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java
@@ -16,6 +16,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.time.Instant;
+import java.time.ZoneOffset;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
@@ -375,7 +377,8 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
ObjectId[] parentIds) throws Exception {
CommitBuilder c = new CommitBuilder();
c.setTreeId(treeB.writeTree(odi));
- c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
+ c.setAuthor(new PersonIdent("A U Thor", "a.u.thor",
+ Instant.ofEpochMilli(1L), ZoneOffset.UTC));
c.setCommitter(c.getAuthor());
c.setParentIds(parentIds);
c.setMessage("Tree " + c.getTreeId().name());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java
index 2955516af0..014ff928a8 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java
@@ -23,7 +23,9 @@ import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
-import java.util.TimeZone;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.CommitBuilder;
@@ -94,18 +96,17 @@ public class RevCommitParseTest extends RepositoryTestCase {
assertNotNull(cAuthor);
assertEquals(authorName, cAuthor.getName());
assertEquals(authorEmail, cAuthor.getEmailAddress());
- assertEquals((long) authorTime * 1000, cAuthor.getWhen().getTime());
- assertEquals(TimeZone.getTimeZone("GMT" + authorTimeZone),
- cAuthor.getTimeZone());
+ assertEquals(Instant.ofEpochSecond(authorTime),
+ cAuthor.getWhenAsInstant());
+ assertEquals(ZoneId.of(authorTimeZone), cAuthor.getZoneId());
final PersonIdent cCommitter = c.getCommitterIdent();
assertNotNull(cCommitter);
assertEquals(committerName, cCommitter.getName());
assertEquals(committerEmail, cCommitter.getEmailAddress());
- assertEquals((long) committerTime * 1000,
- cCommitter.getWhen().getTime());
- assertEquals(TimeZone.getTimeZone("GMT" + committerTimeZone),
- cCommitter.getTimeZone());
+ assertEquals(Instant.ofEpochSecond(committerTime),
+ cCommitter.getWhenAsInstant());
+ assertEquals(ZoneId.of(committerTimeZone), cCommitter.getZoneId());
}
private RevCommit create(String msg) throws Exception {
@@ -153,9 +154,13 @@ public class RevCommitParseTest extends RepositoryTestCase {
c.parseCanonical(rw, b.toString().getBytes(UTF_8));
}
assertEquals(
- new PersonIdent("", "a_u_thor@example.com", 1218123387000L, 7),
+ new PersonIdent("", "a_u_thor@example.com",
+ Instant.ofEpochMilli(1218123387000L),
+ ZoneOffset.ofHoursMinutes(0, 7)),
c.getAuthorIdent());
- assertEquals(new PersonIdent("", "", 1218123390000L, -5),
+ assertEquals(
+ new PersonIdent("", "", Instant.ofEpochMilli(1218123390000L),
+ ZoneOffset.ofHoursMinutes(0, -5)),
c.getCommitterIdent());
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java
index c2f8f10631..e47dd898b0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCommitGraphTest.java
@@ -37,8 +37,9 @@ import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.ChangedPathTreeFilter;
+import org.eclipse.jgit.treewalk.filter.OrTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilter;
-import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.junit.Test;
@@ -172,61 +173,99 @@ public class RevWalkCommitGraphTest extends RevWalkTestCase {
}
@Test
- public void testChangedPathFilter() throws Exception {
- RevCommit c1 = commitFile("file1", "1", "master");
- commitFile("file2", "2", "master");
- RevCommit c3 = commitFile("file1", "3", "master");
- RevCommit c4 = commitFile("file2", "4", "master");
+ public void testChangedPathFilter_allModify() throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(tree(file("file2", blob("2"))), c1);
+ RevCommit c3 = commit(tree(file("file1", blob("3"))), c2);
+ RevCommit c4 = commit(tree(file("file2", blob("4"))), c3);
+
+ branch(c4, "master");
enableAndWriteCommitGraph();
- TreeRevFilter trf = new TreeRevFilter(rw, PathFilter.create("file1"));
+ TreeRevFilter trf = new TreeRevFilter(rw,
+ ChangedPathTreeFilter.create("file1"));
rw.markStart(rw.lookupCommit(c4));
rw.setRevFilter(trf);
+ assertEquals(c4, rw.next());
assertEquals(c3, rw.next());
+ assertEquals(c2, rw.next());
assertEquals(c1, rw.next());
assertNull(rw.next());
- // 1 commit that has exactly one parent and matches path
- assertEquals(1, trf.getChangedPathFilterTruePositive());
+ // all commits modified file1 but c1 did not have a parent
+ assertEquals(3, trf.getChangedPathFilterTruePositive());
// No false positives
assertEquals(0, trf.getChangedPathFilterFalsePositive());
- // 2 commits that have exactly one parent and don't match path
- assertEquals(2, trf.getChangedPathFilterNegative());
+ // No negatives because all 4 commits had modified file1
+ assertEquals(0, trf.getChangedPathFilterNegative());
}
@Test
- public void testChangedPathFilterWithMultiPaths() throws Exception {
- RevCommit c1 = commitFile("file1", "1", "master");
- RevCommit c2 = commitFile("file1", "2", "master");
- RevCommit c3 = commitFile("file2", "3", "master");
- RevCommit c4 = commitFile("file3", "4", "master");
+ public void testChangedPathFilter_someModify() throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(tree(file("file1", blob("1"))), c1);
+ RevCommit c3 = commit(tree(file("file1", blob("2"))), c2);
+ RevCommit c4 = commit(tree(file("file1", blob("1"))), c3);
+
+ branch(c4, "master");
enableAndWriteCommitGraph();
TreeRevFilter trf = new TreeRevFilter(rw,
- PathFilterGroup.createFromStrings(List.of("file1", "file2")));
+ ChangedPathTreeFilter.create("file1"));
rw.markStart(rw.lookupCommit(c4));
rw.setRevFilter(trf);
+ assertEquals(c4, rw.next());
assertEquals(c3, rw.next());
- assertEquals(c2, rw.next());
assertEquals(c1, rw.next());
assertNull(rw.next());
- // c2 and c3 has either file1 or file2, c1 did not use ChangedPathFilter
- // since it has no parent
+ // c4 and c3 modified file1. c1 did not have a parent
assertEquals(2, trf.getChangedPathFilterTruePositive());
// No false positives
assertEquals(0, trf.getChangedPathFilterFalsePositive());
- // c4 does not match either file1 or file2
+ // c2 did not modify file1
assertEquals(1, trf.getChangedPathFilterNegative());
}
@Test
+ public void testChangedPathFilterWithMultiPaths() throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(tree(file("file1", blob("2"))), c1);
+ RevCommit c3 = commit(tree(file("file2", blob("3"))), c2);
+ RevCommit c4 = commit(tree(file("file3", blob("4"))), c3);
+
+ branch(c4, "master");
+
+ enableAndWriteCommitGraph();
+
+ TreeRevFilter trf = new TreeRevFilter(rw,
+ ChangedPathTreeFilter.create("file1", "file2"));
+ rw.markStart(rw.lookupCommit(c4));
+ rw.setRevFilter(trf);
+ assertEquals(c4, rw.next());
+ assertEquals(c3, rw.next());
+ assertEquals(c2, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // all commits have modified either file1 or file2, c1 did not have a
+ // parent
+ assertEquals(3, trf.getChangedPathFilterTruePositive());
+
+ // No false positives
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // No negative
+ assertEquals(0, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
public void testChangedPathFilterWithFollowFilter() throws Exception {
RevCommit c0 = commit(tree());
RevCommit c1 = commit(tree(file("file", blob("contents"))), c0);
@@ -245,9 +284,8 @@ public class RevWalkCommitGraphTest extends RevWalkTestCase {
db.getConfig().setString(ConfigConstants.CONFIG_DIFF_SECTION, null,
ConfigConstants.CONFIG_KEY_RENAMES, "true");
- TreeRevFilter trf = new TreeRevFilter(rw,
- new FollowFilter(PathFilter.create("renamed-file"),
- db.getConfig().get(DiffConfig.KEY)));
+ TreeRevFilter trf = new TreeRevFilter(rw, FollowFilter
+ .create("renamed-file", db.getConfig().get(DiffConfig.KEY)));
rw.markStart(rw.lookupCommit(c4));
rw.setRevFilter(trf);
assertEquals(c3, rw.next());
@@ -267,6 +305,296 @@ public class RevWalkCommitGraphTest extends RevWalkTestCase {
}
@Test
+ public void testChangedPathFilter_pathFilter_or_pathFilter_binaryOperation()
+ throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(
+ tree(file("file1", blob("1")), file("file2", blob("2"))), c1);
+ RevCommit c3 = commit(tree(file("file2", blob("2"))), c2);
+ RevCommit c4 = commit(
+ tree(file("file2", blob("2")), file("file3", blob("3"))), c3);
+ RevCommit c5 = commit(
+ tree(file("file2", blob("2")), file("file3", blob("3"))), c4);
+
+ branch(c5, "master");
+
+ enableAndWriteCommitGraph();
+
+ ChangedPathTreeFilter pf1 = ChangedPathTreeFilter.create("file1");
+ ChangedPathTreeFilter pf2 = ChangedPathTreeFilter.create("file2");
+
+ TreeFilter tf = OrTreeFilter
+ .create(new ChangedPathTreeFilter[] { pf1, pf2 });
+
+ TreeRevFilter trf = new TreeRevFilter(rw, tf);
+ rw.markStart(rw.lookupCommit(c5));
+ rw.setRevFilter(trf);
+ assertEquals(c3, rw.next());
+ assertEquals(c2, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // c2 and c3 has either file1 or file2, c1 is not counted as
+ // ChangedPathFilter only applies to commits with 1 parent
+ assertEquals(2, trf.getChangedPathFilterTruePositive());
+
+ // No false positives
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // c4 and c5 did not modify file1 or file2
+ assertEquals(2, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
+ public void testChangedPathFilter_pathFilter_or_pathFilter_or_pathFilter_listOperation()
+ throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(
+ tree(file("file1", blob("1")), file("file2", blob("2"))), c1);
+ RevCommit c3 = commit(tree(file("file2", blob("2"))), c2);
+ RevCommit c4 = commit(tree(file("file3", blob("3"))), c3);
+ RevCommit c5 = commit(tree(file("file3", blob("3"))), c4);
+
+ branch(c5, "master");
+
+ enableAndWriteCommitGraph();
+
+ ChangedPathTreeFilter pf1 = ChangedPathTreeFilter.create("file1");
+ ChangedPathTreeFilter pf2 = ChangedPathTreeFilter.create("file2");
+ ChangedPathTreeFilter pf3 = ChangedPathTreeFilter.create("file3");
+
+ TreeFilter tf = OrTreeFilter
+ .create(new ChangedPathTreeFilter[] { pf1, pf2, pf3 });
+
+ TreeRevFilter trf = new TreeRevFilter(rw, tf);
+ rw.markStart(rw.lookupCommit(c5));
+ rw.setRevFilter(trf);
+ assertEquals(c4, rw.next());
+ assertEquals(c3, rw.next());
+ assertEquals(c2, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // c2 and c3 has either modified file1 or file2 or file3, c1 is not
+ // counted as ChangedPathFilter only applies to commits with 1 parent
+ assertEquals(3, trf.getChangedPathFilterTruePositive());
+
+ // No false positives
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // c5 does not modify either file1 or file2 or file3
+ assertEquals(1, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
+ public void testChangedPathFilter_pathFilter_or_nonPathFilter_binaryOperation()
+ throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(tree(file("file2", blob("2"))), c1);
+ RevCommit c3 = commit(tree(file("file2", blob("3"))), c2);
+ RevCommit c4 = commit(tree(file("file2", blob("3"))), c3);
+
+ branch(c4, "master");
+
+ enableAndWriteCommitGraph();
+
+ ChangedPathTreeFilter pf = ChangedPathTreeFilter.create("file1");
+ TreeFilter npf = TreeFilter.ANY_DIFF;
+
+ TreeFilter tf = OrTreeFilter.create(new TreeFilter[] { pf, npf });
+
+ TreeRevFilter trf = new TreeRevFilter(rw, tf);
+ rw.markStart(rw.lookupCommit(c4));
+ rw.setRevFilter(trf);
+ assertEquals(c3, rw.next());
+ assertEquals(c2, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // c2 modified file1, c3 defaulted positive due to ANY_DIFF, c1 is not
+ // counted as ChangedPathFilter only applies to commits with 1 parent
+ assertEquals(2, trf.getChangedPathFilterTruePositive());
+
+ // c4 defaulted positive due to ANY_DIFF, but didn't no diff with its
+ // parent c3
+ assertEquals(1, trf.getChangedPathFilterFalsePositive());
+
+ // No negative due to the OrTreeFilter
+ assertEquals(0, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
+ public void testChangedPathFilter_nonPathFilter_or_nonPathFilter_binaryOperation()
+ throws Exception {
+ RevCommit c1 = commitFile("file1", "1", "master");
+ RevCommit c2 = commitFile("file2", "2", "master");
+ RevCommit c3 = commitFile("file3", "3", "master");
+ RevCommit c4 = commitFile("file4", "4", "master");
+
+ enableAndWriteCommitGraph();
+
+ TreeFilter npf1 = TreeFilter.ANY_DIFF;
+ TreeFilter npf2 = TreeFilter.ANY_DIFF;
+
+ TreeFilter tf = OrTreeFilter.create(new TreeFilter[] { npf1, npf2 });
+
+ TreeRevFilter trf = new TreeRevFilter(rw, tf);
+ rw.markStart(rw.lookupCommit(c4));
+ rw.setRevFilter(trf);
+ assertEquals(c4, rw.next());
+ assertEquals(c3, rw.next());
+ assertEquals(c2, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // No true positives since there's no pathFilter
+ assertEquals(0, trf.getChangedPathFilterTruePositive());
+
+ // No false positives since there's no pathFilter
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // No negative since there's no pathFilter
+ assertEquals(0, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
+ public void testChangedPathFilter_pathFilter_and_pathFilter_binaryOperation()
+ throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(tree(file("file2", blob("2"))), c1);
+
+ branch(c2, "master");
+
+ enableAndWriteCommitGraph();
+
+ ChangedPathTreeFilter pf1 = ChangedPathTreeFilter.create("file1");
+ ChangedPathTreeFilter pf2 = ChangedPathTreeFilter.create("file2");
+
+ TreeFilter atf = AndTreeFilter
+ .create(new ChangedPathTreeFilter[] { pf1, pf2 });
+ TreeRevFilter trf = new TreeRevFilter(rw, atf);
+
+ rw.markStart(rw.lookupCommit(c2));
+ rw.setRevFilter(trf);
+
+ assertNull(rw.next());
+
+ // c1 is not counted as ChangedPathFilter only applies to commits with 1
+ // parent
+ assertEquals(0, trf.getChangedPathFilterTruePositive());
+
+ // c2 has modified both file 1 and file2,
+ // however nothing is returned from TreeWalk since a TreeHead
+ // cannot be two paths at once
+ assertEquals(1, trf.getChangedPathFilterFalsePositive());
+
+ // No negatives
+ assertEquals(0, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
+ public void testChangedPathFilter_pathFilter_and_pathFilter_and_pathFilter_listOperation()
+ throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(tree(file("file2", blob("2"))), c1);
+ RevCommit c3 = commit(tree(file("file3", blob("3"))), c2);
+
+ branch(c3, "master");
+
+ enableAndWriteCommitGraph();
+
+ ChangedPathTreeFilter pf1 = ChangedPathTreeFilter.create("file1");
+ ChangedPathTreeFilter pf2 = ChangedPathTreeFilter.create("file2");
+ ChangedPathTreeFilter pf3 = ChangedPathTreeFilter.create("file3");
+
+ TreeFilter tf = AndTreeFilter
+ .create(new ChangedPathTreeFilter[] { pf1, pf2, pf3 });
+
+ TreeRevFilter trf = new TreeRevFilter(rw, tf);
+ rw.markStart(rw.lookupCommit(c3));
+ rw.setRevFilter(trf);
+ assertNull(rw.next());
+
+ // c1 is not counted as ChangedPathFilter only applies to commits with 1
+ // parent
+ assertEquals(0, trf.getChangedPathFilterTruePositive());
+
+ // No false positives
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // c2 and c3 can not possibly have both file1, file2, and file3 as
+ // treeHead at once
+ assertEquals(2, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
+ public void testChangedPathFilter_pathFilter_and_nonPathFilter_binaryOperation()
+ throws Exception {
+ RevCommit c1 = commit(tree(file("file1", blob("1"))));
+ RevCommit c2 = commit(tree(file("file1", blob("2"))), c1);
+ RevCommit c3 = commit(tree(file("file1", blob("2"))), c2);
+
+ branch(c3, "master");
+
+ enableAndWriteCommitGraph();
+
+ ChangedPathTreeFilter pf = ChangedPathTreeFilter.create("file1");
+ TreeFilter npf = TreeFilter.ANY_DIFF;
+
+ TreeFilter tf = AndTreeFilter.create(new TreeFilter[] { pf, npf });
+
+ TreeRevFilter trf = new TreeRevFilter(rw, tf);
+ rw.markStart(rw.lookupCommit(c3));
+ rw.setRevFilter(trf);
+ assertEquals(c2, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // c2 modified file1 and c1 is not counted as ChangedPathFilter only
+ // applies to commits with 1 parent
+ assertEquals(1, trf.getChangedPathFilterTruePositive());
+
+ // No false positives
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // c3 did not modify file1
+ assertEquals(1, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
+ public void testChangedPathFilter_nonPathFilter_and_nonPathFilter_binaryOperation()
+ throws Exception {
+ RevCommit c1 = commitFile("file1", "1", "master");
+ commitFile("file1", "1", "master");
+ RevCommit c3 = commitFile("file3", "3", "master");
+ RevCommit c4 = commitFile("file4", "4", "master");
+
+ enableAndWriteCommitGraph();
+
+ TreeFilter npf1 = TreeFilter.ANY_DIFF;
+ TreeFilter npf2 = TreeFilter.ANY_DIFF;
+
+ TreeFilter tf = AndTreeFilter.create(new TreeFilter[] { npf1, npf2 });
+
+ TreeRevFilter trf = new TreeRevFilter(rw, tf);
+ rw.markStart(rw.lookupCommit(c4));
+ rw.setRevFilter(trf);
+ assertEquals(c4, rw.next());
+ assertEquals(c3, rw.next());
+ assertEquals(c1, rw.next());
+ assertNull(rw.next());
+
+ // No true positives since there's no path
+ assertEquals(0, trf.getChangedPathFilterTruePositive());
+
+ // No false positives since there's no path
+ assertEquals(0, trf.getChangedPathFilterFalsePositive());
+
+ // No negative since there's no path
+ assertEquals(0, trf.getChangedPathFilterNegative());
+ }
+
+ @Test
public void testWalkWithCommitMessageFilter() throws Exception {
RevCommit a = commit();
RevCommit b = commitBuilder().parent(a)
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
index 0a045c917b..ffc7c96f69 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkUtilsReachableTest.java
@@ -14,6 +14,7 @@ import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import org.eclipse.jgit.api.Git;
@@ -121,7 +122,7 @@ public class RevWalkUtilsReachableTest extends RevWalkTestCase {
Collection<Ref> sortedRefs = RefComparator.sort(allRefs);
List<Ref> actual = RevWalkUtils.findBranchesReachableFrom(commit,
rw, sortedRefs);
- assertEquals(refsThatShouldContainCommit, actual);
+ assertEquals(new HashSet<>(refsThatShouldContainCommit), new HashSet<>(actual));
}
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java
index c5e9c2deaa..d54117005d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/submodule/SubmoduleUpdateTest.java
@@ -17,21 +17,25 @@ import java.io.File;
import java.io.IOException;
import java.util.Collection;
+import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.InitCommand;
+import org.eclipse.jgit.api.SubmoduleAddCommand;
import org.eclipse.jgit.api.SubmoduleUpdateCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
-import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.junit.Test;
@@ -40,6 +44,91 @@ import org.junit.Test;
*/
public class SubmoduleUpdateTest extends RepositoryTestCase {
+ private Repository submoduleRepo;
+
+ private Git git;
+
+ private AnyObjectId subRepoCommit2;
+
+ private void createSubmoduleRepo() throws IOException, GitAPIException {
+ File directory = createTempDirectory("submodule_repo");
+ InitCommand init = Git.init();
+ init.setDirectory(directory);
+ init.call();
+ submoduleRepo = Git.open(directory).getRepository();
+ try (Git sub = Git.wrap(submoduleRepo)) {
+ // commit something
+ JGitTestUtil.writeTrashFile(submoduleRepo, "commit1.txt",
+ "commit 1");
+ sub.add().addFilepattern("commit1.txt").call();
+ sub.commit().setMessage("commit 1").call().getId();
+
+ JGitTestUtil.writeTrashFile(submoduleRepo, "commit2.txt",
+ "commit 2");
+ sub.add().addFilepattern("commit2.txt").call();
+ subRepoCommit2 = sub.commit().setMessage("commit 2").call().getId();
+ }
+ }
+
+ private void addSubmodule(String path) throws GitAPIException {
+ SubmoduleAddCommand command = new SubmoduleAddCommand(db);
+ command.setPath(path);
+ String uri = submoduleRepo.getDirectory().toURI().toString();
+ command.setURI(uri);
+ try (Repository repo = command.call()) {
+ assertNotNull(repo);
+ }
+ git.add().addFilepattern(path).addFilepattern(Constants.DOT_GIT_MODULES)
+ .call();
+ git.commit().setMessage("adding submodule").call();
+ recursiveDelete(new File(git.getRepository().getWorkTree(), path));
+ recursiveDelete(
+ new File(new File(git.getRepository().getCommonDirectory(),
+ Constants.MODULES), path));
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ createSubmoduleRepo();
+
+ git = Git.wrap(db);
+ // commit something
+ writeTrashFile("initial.txt", "initial");
+ git.add().addFilepattern("initial.txt").call();
+ git.commit().setMessage("initial commit").call();
+ }
+
+ public void updateModeClonedRestoredSubmoduleTemplate(String mode)
+ throws Exception {
+ String path = "sub";
+ addSubmodule(path);
+
+ StoredConfig cfg = git.getRepository().getConfig();
+ if (mode != null) {
+ cfg.load();
+ cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
+ ConfigConstants.CONFIG_KEY_UPDATE, mode);
+ cfg.save();
+ }
+ SubmoduleUpdateCommand update = new SubmoduleUpdateCommand(db);
+ update.call();
+ try (Git subGit = Git.open(new File(db.getWorkTree(), path))) {
+ update.call();
+ assertEquals(subRepoCommit2.getName(),
+ subGit.getRepository().getBranch());
+ }
+
+ recursiveDelete(new File(db.getWorkTree(), path));
+
+ update.call();
+ try (Git subGit = Git.open(new File(db.getWorkTree(), path))) {
+ update.call();
+ assertEquals(subRepoCommit2.getName(),
+ subGit.getRepository().getBranch());
+ }
+ }
+
@Test
public void repositoryWithNoSubmodules() throws GitAPIException {
SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db);
@@ -50,35 +139,9 @@ public class SubmoduleUpdateTest extends RepositoryTestCase {
@Test
public void repositoryWithSubmodule() throws Exception {
- writeTrashFile("file.txt", "content");
- Git git = Git.wrap(db);
- git.add().addFilepattern("file.txt").call();
- final RevCommit commit = git.commit().setMessage("create file").call();
final String path = "sub";
- DirCache cache = db.lockDirCache();
- DirCacheEditor editor = cache.editor();
- editor.add(new PathEdit(path) {
-
- @Override
- public void apply(DirCacheEntry ent) {
- ent.setFileMode(FileMode.GITLINK);
- ent.setObjectId(commit);
- }
- });
- editor.commit();
-
- StoredConfig config = db.getConfig();
- config.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
- ConfigConstants.CONFIG_KEY_URL, db.getDirectory().toURI()
- .toString());
- config.save();
-
- FileBasedConfig modulesConfig = new FileBasedConfig(new File(
- db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
- modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
- ConfigConstants.CONFIG_KEY_PATH, path);
- modulesConfig.save();
+ addSubmodule(path);
SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db);
Collection<String> updated = command.call();
@@ -90,7 +153,7 @@ public class SubmoduleUpdateTest extends RepositoryTestCase {
assertTrue(generator.next());
try (Repository subRepo = generator.getRepository()) {
assertNotNull(subRepo);
- assertEquals(commit, subRepo.resolve(Constants.HEAD));
+ assertEquals(subRepoCommit2, subRepo.resolve(Constants.HEAD));
String worktreeDir = subRepo.getConfig().getString(
ConfigConstants.CONFIG_CORE_SECTION, null,
ConfigConstants.CONFIG_KEY_WORKTREE);
@@ -104,8 +167,8 @@ public class SubmoduleUpdateTest extends RepositoryTestCase {
}
@Test
- public void repositoryWithUnconfiguredSubmodule() throws IOException,
- GitAPIException {
+ public void repositoryWithUnconfiguredSubmodule()
+ throws IOException, GitAPIException {
final ObjectId id = ObjectId
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
final String path = "sub";
@@ -121,16 +184,14 @@ public class SubmoduleUpdateTest extends RepositoryTestCase {
});
editor.commit();
- FileBasedConfig modulesConfig = new FileBasedConfig(new File(
- db.getWorkTree(), Constants.DOT_GIT_MODULES), db.getFS());
+ FileBasedConfig modulesConfig = new FileBasedConfig(
+ new File(db.getWorkTree(), Constants.DOT_GIT_MODULES),
+ db.getFS());
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_PATH, path);
String url = "git://server/repo.git";
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
ConfigConstants.CONFIG_KEY_URL, url);
- String update = "rebase";
- modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
- ConfigConstants.CONFIG_KEY_UPDATE, update);
modulesConfig.save();
SubmoduleUpdateCommand command = new SubmoduleUpdateCommand(db);
@@ -140,8 +201,8 @@ public class SubmoduleUpdateTest extends RepositoryTestCase {
}
@Test
- public void repositoryWithInitializedSubmodule() throws IOException,
- GitAPIException {
+ public void repositoryWithInitializedSubmodule()
+ throws IOException, GitAPIException {
final ObjectId id = ObjectId
.fromString("abcd1234abcd1234abcd1234abcd1234abcd1234");
final String path = "sub";
@@ -168,4 +229,77 @@ public class SubmoduleUpdateTest extends RepositoryTestCase {
assertNotNull(updated);
assertTrue(updated.isEmpty());
}
+
+ @Test
+ public void updateModeMergeClonedRestoredSubmodule() throws Exception {
+ updateModeClonedRestoredSubmoduleTemplate(
+ ConfigConstants.CONFIG_KEY_MERGE);
+ }
+
+ @Test
+ public void updateModeRebaseClonedRestoredSubmodule() throws Exception {
+ updateModeClonedRestoredSubmoduleTemplate(
+ ConfigConstants.CONFIG_KEY_REBASE);
+ }
+
+ @Test
+ public void updateModeCheckoutClonedRestoredSubmodule() throws Exception {
+ updateModeClonedRestoredSubmoduleTemplate(
+ ConfigConstants.CONFIG_KEY_CHECKOUT);
+ }
+
+ @Test
+ public void updateModeMissingClonedRestoredSubmodule() throws Exception {
+ updateModeClonedRestoredSubmoduleTemplate(null);
+ }
+
+ @Test
+ public void updateMode() throws Exception {
+ String path = "sub";
+ addSubmodule(path);
+
+ StoredConfig cfg = git.getRepository().getConfig();
+ cfg.load();
+ cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
+ ConfigConstants.CONFIG_KEY_UPDATE,
+ ConfigConstants.CONFIG_KEY_REBASE);
+ cfg.save();
+
+ SubmoduleUpdateCommand update = new SubmoduleUpdateCommand(db);
+ update.call();
+ try (Git subGit = Git.open(new File(db.getWorkTree(), path))) {
+ CheckoutCommand checkout = subGit.checkout();
+ checkout.setName("master");
+ checkout.call();
+ update.call();
+ assertEquals("master", subGit.getRepository().getBranch());
+ }
+
+ cfg.load();
+ cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
+ ConfigConstants.CONFIG_KEY_UPDATE,
+ ConfigConstants.CONFIG_KEY_CHECKOUT);
+ cfg.save();
+
+ update.call();
+ try (Git subGit = Git.open(new File(db.getWorkTree(), path))) {
+ assertEquals(subRepoCommit2.getName(),
+ subGit.getRepository().getBranch());
+ }
+
+ cfg.load();
+ cfg.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
+ ConfigConstants.CONFIG_KEY_UPDATE,
+ ConfigConstants.CONFIG_KEY_MERGE);
+ cfg.save();
+
+ update.call();
+ try (Git subGit = Git.open(new File(db.getWorkTree(), path))) {
+ CheckoutCommand checkout = subGit.checkout();
+ checkout.setName("master");
+ checkout.call();
+ update.call();
+ assertEquals("master", subGit.getRepository().getBranch());
+ }
+ }
}
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java
index 4f01e4d445..a03222be0c 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java
@@ -23,6 +23,8 @@ import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -318,8 +320,8 @@ public class PushCertificateStoreTest {
}
private PersonIdent newIdent() {
- return new PersonIdent(
- "A U. Thor", "author@example.com", ts.getAndIncrement(), 0);
+ return new PersonIdent("A U. Thor", "author@example.com",
+ Instant.ofEpochMilli(ts.getAndIncrement()), ZoneOffset.UTC);
}
private PushCertificateStore newStore() {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java
index 029b45e1e6..96d3a5835a 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportHttpTest.java
@@ -14,10 +14,10 @@ import static org.hamcrest.MatcherAssert.assertThat;
import java.io.File;
import java.io.IOException;
import java.net.HttpCookie;
+import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -101,7 +101,7 @@ public class TransportHttpTest extends SampleDataRepositoryTestCase {
.singletonList("cookie2=some value; Max-Age=1234; Path=/"));
try (TransportHttp transportHttp = new TransportHttp(db, uri)) {
- Date creationDate = new Date();
+ Instant creationDate = Instant.now();
transportHttp.processResponseCookies(connection);
// evaluate written cookie file
@@ -112,8 +112,9 @@ public class TransportHttpTest extends SampleDataRepositoryTestCase {
cookie.setPath("/u/2/");
cookie.setMaxAge(
- (Instant.parse("2100-01-01T11:00:00.000Z").toEpochMilli()
- - creationDate.getTime()) / 1000);
+ Duration.between(creationDate,
+ Instant.parse("2100-01-01T11:00:00.000Z"))
+ .getSeconds());
cookie.setSecure(true);
cookie.setHttpOnly(true);
expectedCookies.add(cookie);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java
index d403624b71..67920029d4 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java
@@ -82,6 +82,43 @@ public class URIishTest {
}
@Test
+ public void testBrokenFilePath() throws Exception {
+ String str = "D:\\\\my\\\\x";
+ URIish u = new URIish(str);
+ assertNull(u.getScheme());
+ assertFalse(u.isRemote());
+ assertEquals(str, u.getPath());
+ assertEquals(u, new URIish(str));
+ }
+
+ @Test
+ public void testStackOverflow() throws Exception {
+ StringBuilder b = new StringBuilder("D:\\");
+ for (int i = 0; i < 4000; i++) {
+ b.append("x\\");
+ }
+ String str = b.toString();
+ URIish u = new URIish(str);
+ assertNull(u.getScheme());
+ assertFalse(u.isRemote());
+ assertEquals(str, u.getPath());
+ }
+
+ @Test
+ public void testStackOverflow2() throws Exception {
+ StringBuilder b = new StringBuilder("D:\\");
+ for (int i = 0; i < 4000; i++) {
+ b.append("x\\");
+ }
+ b.append('y');
+ String str = b.toString();
+ URIish u = new URIish(str);
+ assertNull(u.getScheme());
+ assertFalse(u.isRemote());
+ assertEquals(str, u.getPath());
+ }
+
+ @Test
public void testRelativePath() throws Exception {
final String str = "../../foo/bar";
URIish u = new URIish(str);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
index aaecfd290e..5c2f0e5c7d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/UploadPackTest.java
@@ -1,5 +1,6 @@
package org.eclipse.jgit.transport;
+import static java.time.ZoneOffset.UTC;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
@@ -18,6 +19,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -1506,14 +1508,19 @@ public class UploadPackTest {
public void testV2FetchShallowSince() throws Exception {
PersonIdent person = new PersonIdent(remote.getRepository());
- RevCommit beyondBoundary = remote.commit()
- .committer(new PersonIdent(person, 1510000000, 0)).create();
- RevCommit boundary = remote.commit().parent(beyondBoundary)
- .committer(new PersonIdent(person, 1520000000, 0)).create();
- RevCommit tooOld = remote.commit()
- .committer(new PersonIdent(person, 1500000000, 0)).create();
+ RevCommit beyondBoundary = remote.commit().committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1510000), UTC))
+ .create();
+ RevCommit boundary = remote.commit().parent(beyondBoundary).committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1520000), UTC))
+ .create();
+ RevCommit tooOld = remote.commit().committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC))
+ .create();
RevCommit merge = remote.commit().parent(boundary).parent(tooOld)
- .committer(new PersonIdent(person, 1530000000, 0)).create();
+ .committer(new PersonIdent(person,
+ Instant.ofEpochSecond(1530000), UTC))
+ .create();
remote.update("branch1", merge);
@@ -1559,12 +1566,15 @@ public class UploadPackTest {
public void testV2FetchShallowSince_excludedParentWithMultipleChildren() throws Exception {
PersonIdent person = new PersonIdent(remote.getRepository());
- RevCommit base = remote.commit()
- .committer(new PersonIdent(person, 1500000000, 0)).create();
- RevCommit child1 = remote.commit().parent(base)
- .committer(new PersonIdent(person, 1510000000, 0)).create();
- RevCommit child2 = remote.commit().parent(base)
- .committer(new PersonIdent(person, 1520000000, 0)).create();
+ RevCommit base = remote.commit().committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC))
+ .create();
+ RevCommit child1 = remote.commit().parent(base).committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1510000), UTC))
+ .create();
+ RevCommit child2 = remote.commit().parent(base).committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1520000), UTC))
+ .create();
remote.update("branch1", child1);
remote.update("branch2", child2);
@@ -1601,8 +1611,9 @@ public class UploadPackTest {
public void testV2FetchShallowSince_noCommitsSelected() throws Exception {
PersonIdent person = new PersonIdent(remote.getRepository());
- RevCommit tooOld = remote.commit()
- .committer(new PersonIdent(person, 1500000000, 0)).create();
+ RevCommit tooOld = remote.commit().committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC))
+ .create();
remote.update("branch1", tooOld);
@@ -1726,12 +1737,15 @@ public class UploadPackTest {
public void testV2FetchDeepenNot_excludedParentWithMultipleChildren() throws Exception {
PersonIdent person = new PersonIdent(remote.getRepository());
- RevCommit base = remote.commit()
- .committer(new PersonIdent(person, 1500000000, 0)).create();
- RevCommit child1 = remote.commit().parent(base)
- .committer(new PersonIdent(person, 1510000000, 0)).create();
- RevCommit child2 = remote.commit().parent(base)
- .committer(new PersonIdent(person, 1520000000, 0)).create();
+ RevCommit base = remote.commit().committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1500000), UTC))
+ .create();
+ RevCommit child1 = remote.commit().parent(base).committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1510000), UTC))
+ .create();
+ RevCommit child2 = remote.commit().parent(base).committer(
+ new PersonIdent(person, Instant.ofEpochSecond(1520000), UTC))
+ .create();
remote.update("base", base);
remote.update("branch1", child1);
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilterTest.java
new file mode 100644
index 0000000000..88f6b75c6b
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilterTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.treewalk.filter;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import org.eclipse.jgit.internal.storage.commitgraph.ChangedPathFilter;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.filter.TreeFilter.MutableBoolean;
+import org.junit.Test;
+
+public class ChangedPathTreeFilterTest {
+
+ @Test
+ public void shouldTreeWalk_no_usingCpf() {
+ ChangedPathTreeFilter f = ChangedPathTreeFilter.create("a/b");
+ MutableBoolean cfpUsed = new MutableBoolean();
+
+ boolean result = f.shouldTreeWalk(FakeRevCommit.withCpfFor("c"), null,
+ cfpUsed);
+
+ assertFalse(result);
+ assertTrue(cfpUsed.get());
+ }
+
+ @Test
+ public void shouldTreeWalk_yes_usingCpf() {
+ ChangedPathTreeFilter f = ChangedPathTreeFilter.create("a/b");
+ MutableBoolean cfpUsed = new MutableBoolean();
+
+ boolean result = f.shouldTreeWalk(FakeRevCommit.withCpfFor("a/b"), null,
+ cfpUsed);
+
+ assertTrue(result);
+ assertTrue(cfpUsed.get());
+ }
+
+ @Test
+ public void shouldTreeWalk_yes_noCpf() {
+ ChangedPathTreeFilter f = ChangedPathTreeFilter.create("a/b");
+ MutableBoolean cfpUsed = new MutableBoolean();
+
+ boolean result = f.shouldTreeWalk(FakeRevCommit.noCpf(), null,
+ cfpUsed);
+
+ assertTrue(result);
+ assertFalse(cfpUsed.get());
+ }
+
+ @Test
+ public void shouldTreeWalk_no_usingCpf_noReport() {
+ ChangedPathTreeFilter f = ChangedPathTreeFilter.create("a/b");
+ boolean result = f.shouldTreeWalk(FakeRevCommit.withCpfFor("c"), null,
+ null);
+
+ assertFalse(result);
+ }
+
+ @Test
+ public void shouldTreeWalk_yes_usingCpf_noReport() {
+ ChangedPathTreeFilter f = ChangedPathTreeFilter.create("a/b");
+ boolean result = f.shouldTreeWalk(FakeRevCommit.withCpfFor("a/b"), null,
+ null);
+ assertTrue(result);
+ }
+
+ @Test
+ public void shouldTreeWalk_yes_noCpf_noReport() {
+ ChangedPathTreeFilter f = ChangedPathTreeFilter.create("a/b");
+ boolean result = f.shouldTreeWalk(FakeRevCommit.noCpf(), null,
+ null);
+
+ assertTrue(result);
+ }
+
+ private static class FakeRevCommit extends RevCommit {
+
+ static RevCommit withCpfFor(String... paths) {
+ return new FakeRevCommit(
+ ChangedPathFilter.fromPaths(Arrays.stream(paths)
+ .map(str -> ByteBuffer.wrap(str.getBytes(UTF_8)))
+ .collect(Collectors.toSet())));
+ }
+
+ static RevCommit noCpf() {
+ return new FakeRevCommit(null);
+ }
+
+ private final ChangedPathFilter cpf;
+
+ /**
+ * Create a new commit reference.
+ *
+ * @param cpf
+ * changedPathFilter
+ */
+ protected FakeRevCommit(ChangedPathFilter cpf) {
+ super(ObjectId.zeroId());
+ this.cpf = cpf;
+ }
+
+ @Override
+ public ChangedPathFilter getChangedPathFilter(RevWalk rw) {
+ return cpf;
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java
index 32652494d2..44e8632228 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/ChangeIdUtilTest.java
@@ -12,7 +12,9 @@ package org.eclipse.jgit.util;
import static org.junit.Assert.assertEquals;
-import java.util.concurrent.TimeUnit;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.ZoneId;
import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.lib.ObjectId;
@@ -53,9 +55,9 @@ public class ChangeIdUtilTest {
MockSystemReader mockSystemReader = new MockSystemReader();
- final long when = mockSystemReader.getCurrentTime();
+ Instant when = mockSystemReader.now();
- final int tz = new MockSystemReader().getTimezone(when);
+ ZoneId tz = new MockSystemReader().getTimeZoneAt(when);
PersonIdent author = new PersonIdent("J. Author", "ja@example.com");
{
@@ -218,23 +220,23 @@ public class ChangeIdUtilTest {
@Test
public void testACommitWithSubjectBodyBugBrackersAndSob() throws Exception {
assertEquals(
- "a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\nChange-Id: I90ecb589bef766302532c3e00915e10114b00f62\n[bracket]\nSigned-off-by: me@you.too\n",
- call("a commit with subject body, bug. brackers and sob\n\nText\n\nBug: 33\n[bracket]\nSigned-off-by: me@you.too\n\n"));
+ "a commit with subject body, bug, brackers and sob\n\nText\n\nBug: 33\n[bracket]\nChange-Id: I94dc6ed919a4baaa7c1bf8712717b888c6b90363\nSigned-off-by: me@you.too\n",
+ call("a commit with subject body, bug, brackers and sob\n\nText\n\nBug: 33\n[bracket]\nSigned-off-by: me@you.too\n\n"));
}
@Test
public void testACommitWithSubjectBodyBugLineWithASpaceAndSob()
throws Exception {
assertEquals(
- "a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\nChange-Id: I864e2218bdee033c8ce9a7f923af9e0d5dc16863\n \nSigned-off-by: me@you.too\n",
- call("a commit with subject body, bug. line with a space and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n"));
+ "a commit with subject body, bug, line with a space and sob\n\nText\n\nBug: 33\n \nChange-Id: I126b472d2e0e64ad8187d61857f0169f9ccdae86\nSigned-off-by: me@you.too\n",
+ call("a commit with subject body, bug, line with a space and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n"));
}
@Test
public void testACommitWithSubjectBodyBugEmptyLineAndSob() throws Exception {
assertEquals(
- "a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\nChange-Id: I33f119f533313883e6ada3df600c4f0d4db23a76\n \nSigned-off-by: me@you.too\n",
- call("a commit with subject body, bug. empty line and sob\n\nText\n\nBug: 33\n \nSigned-off-by: me@you.too\n\n"));
+ "a commit with subject body, bug, empty line and sob\n\nText\n\nBug: 33\n\nChange-Id: Ic3b61b6e39a0815669b65302e9e75e6a5a019a26\nSigned-off-by: me@you.too\n",
+ call("a commit with subject body, bug, empty line and sob\n\nText\n\nBug: 33\n\nSigned-off-by: me@you.too\n\n"));
}
@Test
@@ -342,9 +344,7 @@ public class ChangeIdUtilTest {
/** Increment the {@link #author} and {@link #committer} times. */
protected void tick() {
- final long delta = TimeUnit.MILLISECONDS.convert(5 * 60,
- TimeUnit.SECONDS);
- final long now = author.getWhen().getTime() + delta;
+ Instant now = author.getWhenAsInstant().plus(Duration.ofMinutes(5));
author = new PersonIdent(author, now, tz);
committer = new PersonIdent(committer, now, tz);
@@ -528,7 +528,7 @@ public class ChangeIdUtilTest {
}
@Test
- public void testChangeIdAfterBugOrIssue() throws Exception {
+ public void testChangeIdAfterOtherFooters() throws Exception {
assertEquals("a\n" + //
"\n" + //
"Bug: 42\n" + //
@@ -541,6 +541,18 @@ public class ChangeIdUtilTest {
assertEquals("a\n" + //
"\n" + //
+ "Bug: 42\n" + //
+ " multi-line Bug footer\n" + //
+ "Change-Id: Icc953ef35f1a4ee5eb945132aefd603ae3d9dd9f\n" + //
+ SOB1,//
+ call("a\n" + //
+ "\n" + //
+ "Bug: 42\n" + //
+ " multi-line Bug footer\n" + //
+ SOB1));
+
+ assertEquals("a\n" + //
+ "\n" + //
"Issue: 42\n" + //
"Change-Id: Ie66e07d89ae5b114c0975b49cf326e90331dd822\n" + //
SOB1,//
@@ -548,6 +560,14 @@ public class ChangeIdUtilTest {
"\n" + //
"Issue: 42\n" + //
SOB1));
+
+ assertEquals("a\n" + //
+ "\n" + //
+ "Other: none\n" + //
+ "Change-Id: Ide70e625dea61854206378a377dd12e462ae720f\n",//
+ call("a\n" + //
+ "\n" + //
+ "Other: none\n"));
}
@Test
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefMapTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefMapTest.java
index a8077fdb0c..0c9cb2d2b0 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefMapTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RefMapTest.java
@@ -423,7 +423,7 @@ public class RefMapTest {
Map.Entry<String, Ref> ent_b = itr.next();
assertEquals(ent_a.hashCode(), "A".hashCode());
- assertEquals(ent_a, ent_a);
+ assertTrue(ent_a.equals(ent_a));
assertFalse(ent_a.equals(ent_b));
assertEquals(a.toString(), ent_a.toString());
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java
index 015da164c3..9a1c710752 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java
@@ -12,6 +12,7 @@ package org.eclipse.jgit.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@@ -172,4 +173,22 @@ public class StringUtilsTest {
assertEquals("foo bar ",
StringUtils.commonPrefix("foo bar 42", "foo bar 24"));
}
+
+ @Test
+ public void testTrim() {
+ assertEquals("a", StringUtils.trim("a", '/'));
+ assertEquals("aaaa", StringUtils.trim("aaaa", '/'));
+ assertEquals("aaa", StringUtils.trim("/aaa", '/'));
+ assertEquals("aaa", StringUtils.trim("aaa/", '/'));
+ assertEquals("aaa", StringUtils.trim("/aaa/", '/'));
+ assertEquals("aa/aa", StringUtils.trim("/aa/aa/", '/'));
+ assertEquals("aa/aa", StringUtils.trim("aa/aa", '/'));
+
+ assertEquals("", StringUtils.trim("", '/'));
+ assertEquals("", StringUtils.trim("/", '/'));
+ assertEquals("", StringUtils.trim("//", '/'));
+ assertEquals("", StringUtils.trim("///", '/'));
+
+ assertNull(StringUtils.trim(null, '/'));
+ }
}
diff --git a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
index 423d22b748..8ee3e0197a 100644
--- a/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/MANIFEST.MF
@@ -4,14 +4,14 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit.ui
Bundle-SymbolicName: org.eclipse.jgit.ui
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Vendor: %Bundle-Vendor
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Export-Package: org.eclipse.jgit.awtui;version="7.2.0"
-Import-Package: org.eclipse.jgit.errors;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.lib;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.nls;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revplot;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.revwalk;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.transport;version="[7.2.0,7.3.0)",
- org.eclipse.jgit.util;version="[7.2.0,7.3.0)"
+Export-Package: org.eclipse.jgit.awtui;version="7.4.0"
+Import-Package: org.eclipse.jgit.errors;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.lib;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.nls;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revplot;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.revwalk;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.transport;version="[7.4.0,7.5.0)",
+ org.eclipse.jgit.util;version="[7.4.0,7.5.0)"
diff --git a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
index 12363f802e..86ff12a837 100644
--- a/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit.ui/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit.ui - Sources
Bundle-SymbolicName: org.eclipse.jgit.ui.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit.ui;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit.ui;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit.ui/pom.xml b/org.eclipse.jgit.ui/pom.xml
index ada06ed656..0f8944be88 100644
--- a/org.eclipse.jgit.ui/pom.xml
+++ b/org.eclipse.jgit.ui/pom.xml
@@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.ui</artifactId>
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
new file mode 100644
index 0000000000..877a488a73
--- /dev/null
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.jgit" version="2">
+ <resource path="src/org/eclipse/jgit/lib/RefDatabase.java" type="org.eclipse.jgit.lib.RefDatabase">
+ <filter id="336695337">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.RefDatabase"/>
+ <message_argument value="getReflogReader(Ref)"/>
+ </message_arguments>
+ </filter>
+ <filter id="336695337">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.RefDatabase"/>
+ <message_argument value="getReflogReader(String)"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/lib/TypedConfigGetter.java" type="org.eclipse.jgit.lib.TypedConfigGetter">
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getBoolean(Config, String, String, String, Boolean)"/>
+ </message_arguments>
+ </filter>
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getInt(Config, String, String, String, Integer)"/>
+ </message_arguments>
+ </filter>
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getIntInRange(Config, String, String, String, Integer, Integer, Integer)"/>
+ </message_arguments>
+ </filter>
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getIntInRange(Config, String, String, String, int, int, Integer)"/>
+ </message_arguments>
+ </filter>
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getLong(Config, String, String, String, Long)"/>
+ </message_arguments>
+ </filter>
+ <filter id="403804204">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getTimeUnit(Config, String, String, String, Long, TimeUnit)"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/revwalk/RevWalk.java" type="org.eclipse.jgit.revwalk.RevWalk">
+ <filter id="1142947843">
+ <message_arguments>
+ <message_argument value="6.10.1"/>
+ <message_argument value="isMergedIntoAnyCommit(RevCommit, Collection&lt;RevCommit&gt;)"/>
+ </message_arguments>
+ </filter>
+ </resource>
+</component>
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 659ad8549f..6b25c7e6f0 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -3,14 +3,14 @@ Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit
Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 7.2.0.qualifier
+Bundle-Version: 7.4.0.qualifier
Bundle-Localization: OSGI-INF/l10n/plugin
Bundle-Vendor: %Bundle-Vendor
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/org.eclipse.jgit.internal.util.CleanupService.xml
Eclipse-ExtensibleAPI: true
-Export-Package: org.eclipse.jgit.annotations;version="7.2.0",
- org.eclipse.jgit.api;version="7.2.0";
+Export-Package: org.eclipse.jgit.annotations;version="7.4.0",
+ org.eclipse.jgit.api;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.notes,
org.eclipse.jgit.dircache,
@@ -25,72 +25,77 @@ Export-Package: org.eclipse.jgit.annotations;version="7.2.0",
org.eclipse.jgit.revwalk.filter,
org.eclipse.jgit.blame,
org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="7.2.0";
+ org.eclipse.jgit.api.errors;version="7.4.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="7.2.0";
+ org.eclipse.jgit.attributes;version="7.4.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk",
- org.eclipse.jgit.blame;version="7.2.0";
+ org.eclipse.jgit.blame;version="7.4.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
- org.eclipse.jgit.treewalk.filter,
- org.eclipse.jgit.diff",
- org.eclipse.jgit.diff;version="7.2.0";
+ org.eclipse.jgit.blame.cache,
+ org.eclipse.jgit.diff,
+ org.eclipse.jgit.treewalk.filter",
+ org.eclipse.jgit.blame.cache;version="7.4.0";
+ uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.diff;version="7.4.0";
uses:="org.eclipse.jgit.lib,
- org.eclipse.jgit.attributes,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.patch,
+ org.eclipse.jgit.attributes,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util",
- org.eclipse.jgit.dircache;version="7.2.0";
+ org.eclipse.jgit.dircache;version="7.4.0";
uses:="org.eclipse.jgit.events,
org.eclipse.jgit.lib,
org.eclipse.jgit.attributes,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util",
- org.eclipse.jgit.errors;version="7.2.0";
+ org.eclipse.jgit.errors;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.dircache,
- org.eclipse.jgit.lib,
- org.eclipse.jgit.internal.storage.pack",
- org.eclipse.jgit.events;version="7.2.0";
+ org.eclipse.jgit.lib",
+ org.eclipse.jgit.events;version="7.4.0";
uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="7.2.0",
- org.eclipse.jgit.gitrepo;version="7.2.0";
+ org.eclipse.jgit.fnmatch;version="7.4.0",
+ org.eclipse.jgit.gitrepo;version="7.4.0";
uses:="org.xml.sax.helpers,
org.eclipse.jgit.api,
+ org.eclipse.jgit.api.errors,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.xml.sax",
- org.eclipse.jgit.gitrepo.internal;version="7.2.0";x-internal:=true,
- org.eclipse.jgit.hooks;version="7.2.0";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="7.2.0",
- org.eclipse.jgit.ignore.internal;version="7.2.0";
+ org.eclipse.jgit.gitrepo.internal;version="7.4.0";x-internal:=true,
+ org.eclipse.jgit.hooks;version="7.4.0";
+ uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.util",
+ org.eclipse.jgit.ignore;version="7.4.0",
+ org.eclipse.jgit.ignore.internal;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="7.2.0";
+ org.eclipse.jgit.internal;version="7.4.0";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.diff;version="7.2.0";
+ org.eclipse.jgit.internal.diff;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.diffmergetool;version="7.2.0";
+ org.eclipse.jgit.internal.diffmergetool;version="7.4.0";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.pgm.test,
org.eclipse.jgit.pgm,
org.eclipse.egit.ui",
- org.eclipse.jgit.internal.fsck;version="7.2.0";
+ org.eclipse.jgit.internal.fsck;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.revwalk;version="7.2.0";
+ org.eclipse.jgit.internal.revwalk;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.commitgraph;version="7.2.0";
+ org.eclipse.jgit.internal.storage.commitgraph;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.dfs;version="7.2.0";
+ org.eclipse.jgit.internal.storage.dfs;version="7.4.0";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.http.server,
org.eclipse.jgit.http.test,
org.eclipse.jgit.lfs.test",
- org.eclipse.jgit.internal.storage.file;version="7.2.0";
+ org.eclipse.jgit.internal.storage.file;version="7.4.0";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.junit,
org.eclipse.jgit.junit.http,
@@ -99,41 +104,43 @@ Export-Package: org.eclipse.jgit.annotations;version="7.2.0",
org.eclipse.jgit.pgm,
org.eclipse.jgit.pgm.test,
org.eclipse.jgit.ssh.apache",
- org.eclipse.jgit.internal.storage.io;version="7.2.0";
+ org.eclipse.jgit.internal.storage.io;version="7.4.0";
x-friends:="org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.memory;version="7.2.0";
+ org.eclipse.jgit.internal.storage.memory;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.storage.pack;version="7.2.0";
+ org.eclipse.jgit.internal.storage.midx;version="7.4.0";x-internal:=true,
+ org.eclipse.jgit.internal.storage.pack;version="7.4.0";
x-friends:="org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftable;version="7.2.0";
+ org.eclipse.jgit.internal.storage.reftable;version="7.4.0";
x-friends:="org.eclipse.jgit.http.test,
org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.submodule;version="7.2.0";x-internal:=true,
- org.eclipse.jgit.internal.transport.connectivity;version="7.2.0";
+ org.eclipse.jgit.internal.submodule;version="7.4.0";x-internal:=true,
+ org.eclipse.jgit.internal.transport.connectivity;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.http;version="7.2.0";
+ org.eclipse.jgit.internal.transport.http;version="7.4.0";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.parser;version="7.2.0";
+ org.eclipse.jgit.internal.transport.parser;version="7.4.0";
x-friends:="org.eclipse.jgit.http.server,
org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.ssh;version="7.2.0";
+ org.eclipse.jgit.internal.transport.ssh;version="7.4.0";
x-friends:="org.eclipse.jgit.ssh.apache,
org.eclipse.jgit.ssh.jsch,
org.eclipse.jgit.test",
- org.eclipse.jgit.internal.util;version="7.2.0";
- x-friends:=" org.eclipse.jgit.junit",
- org.eclipse.jgit.lib;version="7.2.0";
+ org.eclipse.jgit.internal.util;version="7.4.0";
+ x-friends:="org.eclipse.jgit.junit",
+ org.eclipse.jgit.lib;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.util.sha1,
org.eclipse.jgit.dircache,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.internal.storage.file,
+ org.eclipse.jgit.api,
org.eclipse.jgit.attributes,
org.eclipse.jgit.events,
com.googlecode.javaewah,
@@ -142,12 +149,12 @@ Export-Package: org.eclipse.jgit.annotations;version="7.2.0",
org.eclipse.jgit.util,
org.eclipse.jgit.submodule,
org.eclipse.jgit.util.time",
- org.eclipse.jgit.lib.internal;version="7.2.0";
+ org.eclipse.jgit.lib.internal;version="7.4.0";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.pgm,
org.eclipse.egit.ui",
- org.eclipse.jgit.logging;version="7.2.0",
- org.eclipse.jgit.merge;version="7.2.0";
+ org.eclipse.jgit.logging;version="7.4.0",
+ org.eclipse.jgit.merge;version="7.4.0";
uses:="org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
@@ -156,67 +163,69 @@ Export-Package: org.eclipse.jgit.annotations;version="7.2.0",
org.eclipse.jgit.util,
org.eclipse.jgit.api,
org.eclipse.jgit.attributes",
- org.eclipse.jgit.nls;version="7.2.0",
- org.eclipse.jgit.notes;version="7.2.0";
+ org.eclipse.jgit.nls;version="7.4.0",
+ org.eclipse.jgit.notes;version="7.4.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="7.2.0";
+ org.eclipse.jgit.patch;version="7.4.0";
uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.revwalk,
org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="7.2.0";
- uses:="org.eclipse.jgit.lib,
- org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="7.2.0";
+ org.eclipse.jgit.revplot;version="7.4.0";
+ uses:="org.eclipse.jgit.revwalk,
+ org.eclipse.jgit.lib",
+ org.eclipse.jgit.revwalk;version="7.4.0";
uses:="org.eclipse.jgit.lib,
+ org.eclipse.jgit.revwalk.filter,
org.eclipse.jgit.diff,
org.eclipse.jgit.treewalk.filter,
- org.eclipse.jgit.revwalk.filter,
- org.eclipse.jgit.treewalk",
- org.eclipse.jgit.revwalk.filter;version="7.2.0";
+ org.eclipse.jgit.treewalk,
+ org.eclipse.jgit.internal.storage.commitgraph",
+ org.eclipse.jgit.revwalk.filter;version="7.4.0";
uses:="org.eclipse.jgit.revwalk,
org.eclipse.jgit.lib,
org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="7.2.0";
+ org.eclipse.jgit.storage.file;version="7.4.0";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="7.2.0";
+ org.eclipse.jgit.storage.pack;version="7.4.0";
uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="7.2.0";
+ org.eclipse.jgit.submodule;version="7.4.0";
uses:="org.eclipse.jgit.lib,
- org.eclipse.jgit.diff,
org.eclipse.jgit.treewalk.filter,
+ org.eclipse.jgit.diff,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util",
- org.eclipse.jgit.transport;version="7.2.0";
+ org.eclipse.jgit.transport;version="7.4.0";
uses:="javax.crypto,
+ org.eclipse.jgit.hooks,
org.eclipse.jgit.util.io,
org.eclipse.jgit.lib,
- org.eclipse.jgit.revwalk,
org.eclipse.jgit.transport.http,
- org.eclipse.jgit.internal.storage.file,
+ org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util,
org.eclipse.jgit.internal.storage.pack,
org.eclipse.jgit.transport.resolver,
org.eclipse.jgit.storage.pack,
org.eclipse.jgit.errors",
- org.eclipse.jgit.transport.http;version="7.2.0";
+ org.eclipse.jgit.transport.http;version="7.4.0";
uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="7.2.0";
+ org.eclipse.jgit.transport.resolver;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.lib",
- org.eclipse.jgit.treewalk;version="7.2.0";
+ org.eclipse.jgit.treewalk;version="7.4.0";
uses:="org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
org.eclipse.jgit.attributes,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util",
- org.eclipse.jgit.treewalk.filter;version="7.2.0";
+ org.eclipse.jgit.treewalk.filter;version="7.4.0";
uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="7.2.0";
+ org.eclipse.jgit.util;version="7.4.0";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.hooks,
org.eclipse.jgit.revwalk,
@@ -229,12 +238,12 @@ Export-Package: org.eclipse.jgit.annotations;version="7.2.0",
org.eclipse.jgit.treewalk,
javax.net.ssl,
org.eclipse.jgit.util.time",
- org.eclipse.jgit.util.io;version="7.2.0";
+ org.eclipse.jgit.util.io;version="7.4.0";
uses:="org.eclipse.jgit.attributes,
org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util.sha1;version="7.2.0",
- org.eclipse.jgit.util.time;version="7.2.0"
+ org.eclipse.jgit.util.sha1;version="7.4.0",
+ org.eclipse.jgit.util.time;version="7.4.0"
Bundle-RequiredExecutionEnvironment: JavaSE-17
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
javax.crypto,
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index 0f9ec1fb22..b52bd7d908 100644
--- a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
@@ -3,5 +3,5 @@ Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.jgit - Sources
Bundle-SymbolicName: org.eclipse.jgit.source
Bundle-Vendor: Eclipse.org - JGit
-Bundle-Version: 7.2.0.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="7.2.0.qualifier";roots="."
+Bundle-Version: 7.4.0.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="7.4.0.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index df7ae83647..ec3f314bef 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit</artifactId>
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 acfe812a20..e24cba6ac4 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -64,8 +64,6 @@ binaryHunkDecodeError=Binary hunk, line {0}: invalid input
binaryHunkInvalidLength=Binary hunk, line {0}: input corrupt; expected length byte, got 0x{1}
binaryHunkLineTooShort=Binary hunk, line {0}: input ended prematurely
binaryHunkMissingNewline=Binary hunk, line {0}: input line not terminated by newline
-bitmapAccessErrorForPackfile=Error whilst trying to access bitmap file for {}
-bitmapFailedToGet=Failed to get bitmap index file {}
bitmapMissingObject=Bitmap at {0} is missing {1}.
bitmapsMustBePrepared=Bitmaps must be prepared before they may be written.
bitmapUseNoopNoListener=Use NOOP instance for no listener
@@ -78,6 +76,7 @@ branchNameInvalid=Branch name {0} is not allowed
buildingBitmaps=Building bitmaps
cachedPacksPreventsIndexCreation=Using cached packs prevents index creation
cachedPacksPreventsListingObjects=Using cached packs prevents listing objects
+cacheRegionAllOrNoneNull=expected all null or none: {0}, {1}
cannotAccessLastModifiedForSafeDeletion=Unable to access lastModifiedTime of file {0}, skip deletion since we cannot safely avoid race condition
cannotBeCombined=Cannot be combined.
cannotBeRecursiveWhenTreesAreIncluded=TreeWalk shouldn't be recursive when tree objects are included.
@@ -161,7 +160,7 @@ commitGraphChunkNeeded=commit-graph 0x{0} chunk has not been loaded
commitGraphChunkRepeated=commit-graph chunk id 0x{0} appears multiple times
commitGraphChunkUnknown=unknown commit-graph chunk: 0x{0}
commitGraphFileIsTooLargeForJgit=commit-graph file is too large for jgit
-commitGraphUnexpectedSize=Commit-graph: expected %d bytes but out has %d bytes
+commitGraphUnexpectedSize=Commit-graph: expected {0} bytes but out has {1} bytes
commitGraphWritingCancelled=commit-graph writing was canceled
commitMessageNotSpecified=commit message not specified
commitOnRepoWithoutHEADCurrentlyNotSupported=Commit on repo without HEAD currently not supported
@@ -267,6 +266,7 @@ deletingBranches=Deleting branches...
deletingNotSupported=Deleting {0} not supported.
depthMustBeAt1=Depth must be >= 1
depthWithUnshallow=Depth and unshallow can\'t be used together
+deprecatedTrustFolderStat=Option core.trustFolderStat is deprecated, replace it by core.trustStat.
destinationIsNotAWildcard=Destination is not a wildcard.
detachedHeadDetected=HEAD is detached
diffToolNotGivenError=No diff tool provided and no defaults configured.
@@ -464,6 +464,7 @@ invalidTimestamp=Invalid timestamp in {0}
invalidTimeUnitValue2=Invalid time unit value: {0}.{1}={2}
invalidTimeUnitValue3=Invalid time unit value: {0}.{1}.{2}={3}
invalidTreeZeroLengthName=Cannot append a tree entry with zero-length name
+invalidTrustStat=core.trustStat must not be set to TrustStat.INHERIT, falling back to TrustStat.ALWAYS.
invalidURL=Invalid URL {0}
invalidWildcards=Invalid wildcards {0}
invalidRefSpec=Invalid refspec {0}
@@ -495,6 +496,7 @@ logInvalidDefaultCharset=System property "native.encoding" specifies unknown cha
logLargerFiletimeDiff={}: inconsistent duration from file timestamps on {}, {}: diff = {} > {} (last good value). Aborting measurement.
logSmallerFiletime={}: got smaller file timestamp on {}, {}: {} < {}. Aborting measurement at resolution {}.
logXDGConfigHomeInvalid=Environment variable XDG_CONFIG_HOME contains an invalid path {}
+logXDGCacheHomeInvalid=Environment variable XDG_CACHE_HOME contains an invalid path {}
looseObjectHandleIsStale=loose-object {0} file handle is stale. retry {1} of {2}
maxCountMustBeNonNegative=max count must be >= 0
mergeConflictOnNonNoteEntries=Merge conflict on non-note entries: base = {0}, ours = {1}, theirs = {2}
@@ -507,6 +509,9 @@ mergeRecursiveTooManyMergeBasesFor = "More than {0} merge bases for:\n a {1}\n b
mergeToolNotGivenError=No merge tool provided and no defaults configured.
mergeToolNullError=Parameter for merge tool cannot be null.
messageAndTaggerNotAllowedInUnannotatedTags = Unannotated tags cannot have a message or tagger
+midxChunkNeeded=midx 0x{0} chunk has not been loaded
+midxChunkRepeated=midx chunk id 0x{0} appears multiple times
+midxChunkUnknown=unknown midx chunk: 0x{0}
minutesAgo={0} minutes ago
mismatchOffset=mismatch offset for object {0}
mismatchCRC=mismatch CRC for object {0}
@@ -527,6 +532,10 @@ mkDirsFailed=Creating directories for {0} failed
month=month
months=months
monthsAgo={0} months ago
+multiPackIndexFileIsTooLargeForJgit=Multipack index file is too large for jgit
+multiPackIndexPackCountMismatch=Multipack index: header mentions {0} packs but packfile names chunk has {1}
+multiPackIndexUnexpectedSize=MultiPack index: expected {0} bytes but out has {1} bytes
+multiPackIndexWritingCancelled=Multipack index writing was canceled
multipleMergeBasesFor=Multiple merge bases for:\n {0}\n {1} found:\n {2}\n {3}
nameMustNotBeNullOrEmpty=Ref name must not be null or empty.
need2Arguments=Need 2 arguments
@@ -554,6 +563,7 @@ notACommitGraph=not a commit-graph
notADIRCFile=Not a DIRC file.
notAGitDirectory=not a git directory
notAPACKFile=Not a PACK file.
+notAMIDX=not a multi-pack-index
notARef=Not a ref: {0}: {1}
notASCIIString=Not ASCII string: {0}
notAuthorized=not authorized
@@ -615,6 +625,7 @@ peerDidNotSupplyACompleteObjectGraph=peer did not supply a complete object graph
personIdentEmailNonNull=E-mail address of PersonIdent must not be null.
personIdentNameNonNull=Name of PersonIdent must not be null.
postCommitHookFailed=Execution of post-commit hook failed: {0}.
+precedenceTrustConfig=Both core.trustFolderStat and core.trustStat are set, ignoring trustFolderStat since trustStat takes precedence. Remove core.trustFolderStat from your configuration.
prefixRemote=remote:
problemWithResolvingPushRefSpecsLocally=Problem with resolving push ref specs locally: {0}
progressMonUploading=Uploading {0}
@@ -837,7 +848,7 @@ unknownObjectInIndex=unknown object {0} found in index but not in pack file
unknownObjectType=Unknown object type {0}.
unknownObjectType2=unknown
unknownPackExtension=Unknown pack extension: {0}.{1}.{2}={3}
-unknownPositionEncoding=Unknown position encoding %s
+unknownPositionEncoding=Unknown position encoding {0}
unknownRefStorageFormat=Unknown ref storage format "{0}"
unknownRepositoryFormat=Unknown repository format
unknownRepositoryFormat2=Unknown repository format "{0}"; expected "0".
@@ -848,6 +859,7 @@ unmergedPath=Unmerged path: {0}
unmergedPaths=Repository contains unmerged paths
unpackException=Exception while parsing pack stream
unreadableCommitGraph=Unreadable commit-graph: {0}
+unreadableMIDX=Unreadable multi-pack-index: {0}
unreadableObjectSizeIndex=Unreadable object size index. First {0} bytes are ''{1}''
unreadablePackIndex=Unreadable pack index: {0}
unrecognizedPackExtension=Unrecognized pack extension: {0}
@@ -861,6 +873,7 @@ unsupportedEncryptionAlgorithm=Unsupported encryption algorithm: {0}
unsupportedEncryptionVersion=Unsupported encryption version: {0}
unsupportedGC=Unsupported garbage collector for repository type: {0}
unsupportedMark=Mark not supported
+unsupportedMIDXVersion=Unsupported MIDX version {0}
unsupportedObjectSizeIndexVersion=Unsupported object size index version {0}
unsupportedOperationNotAddAtEnd=Not add-at-end: {0}
unsupportedPackIndexVersion=Unsupported pack index version {0}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
index c895dc9aaa..b4d1cab513 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/AddCommand.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
- * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com> and others
+ * Copyright (C) 2010, 2025 Stefan Lay <stefan.lay@sap.com> 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
@@ -17,6 +17,7 @@ import static org.eclipse.jgit.lib.FileMode.TYPE_TREE;
import java.io.IOException;
import java.io.InputStream;
+import java.text.MessageFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -59,8 +60,15 @@ public class AddCommand extends GitCommand<DirCache> {
private WorkingTreeIterator workingTreeIterator;
+ // Update only known index entries, don't add new ones. If there's no file
+ // for an index entry, remove it: stage deletions.
private boolean update = false;
+ // If TRUE, also stage deletions, otherwise only update and add index
+ // entries.
+ // If not set explicitly
+ private Boolean all;
+
// This defaults to true because it's what JGit has been doing
// traditionally. The C git default would be false.
private boolean renormalize = true;
@@ -82,6 +90,17 @@ public class AddCommand extends GitCommand<DirCache> {
* A directory name (e.g. <code>dir</code> to add <code>dir/file1</code> and
* <code>dir/file2</code>) can also be given to add all files in the
* directory, recursively. Fileglobs (e.g. *.c) are not yet supported.
+ * </p>
+ * <p>
+ * If a pattern {@code "."} is added, all changes in the git repository's
+ * working tree will be added.
+ * </p>
+ * <p>
+ * File patterns are required unless {@code isUpdate() == true} or
+ * {@link #setAll(boolean)} is called. If so and no file patterns are given,
+ * all changes will be added (i.e., a file pattern of {@code "."} is
+ * implied).
+ * </p>
*
* @param filepattern
* repository-relative path of file/directory to add (with
@@ -113,15 +132,41 @@ public class AddCommand extends GitCommand<DirCache> {
* Executes the {@code Add} command. Each instance of this class should only
* be used for one invocation of the command. Don't call this method twice
* on an instance.
+ * </p>
+ *
+ * @throws JGitInternalException
+ * on errors, but also if {@code isUpdate() == true} _and_
+ * {@link #setAll(boolean)} had been called
+ * @throws NoFilepatternException
+ * if no file patterns are given if {@code isUpdate() == false}
+ * and {@link #setAll(boolean)} was not called
*/
@Override
public DirCache call() throws GitAPIException, NoFilepatternException {
-
- if (filepatterns.isEmpty())
- throw new NoFilepatternException(JGitText.get().atLeastOnePatternIsRequired);
checkCallable();
+
+ if (update && all != null) {
+ throw new JGitInternalException(MessageFormat.format(
+ JGitText.get().illegalCombinationOfArguments,
+ "--update", "--all/--no-all")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ boolean addAll;
+ if (filepatterns.isEmpty()) {
+ if (update || all != null) {
+ addAll = true;
+ } else {
+ throw new NoFilepatternException(
+ JGitText.get().atLeastOnePatternIsRequired);
+ }
+ } else {
+ addAll = filepatterns.contains("."); //$NON-NLS-1$
+ if (all == null && !update) {
+ all = Boolean.TRUE;
+ }
+ }
+ boolean stageDeletions = update || (all != null && all.booleanValue());
+
DirCache dc = null;
- boolean addAll = filepatterns.contains("."); //$NON-NLS-1$
try (ObjectInserter inserter = repo.newObjectInserter();
NameConflictTreeWalk tw = new NameConflictTreeWalk(repo)) {
@@ -181,7 +226,8 @@ public class AddCommand extends GitCommand<DirCache> {
if (f == null) { // working tree file does not exist
if (entry != null
- && (!update || GITLINK == entry.getFileMode())) {
+ && (!stageDeletions
+ || GITLINK == entry.getFileMode())) {
builder.add(entry);
}
continue;
@@ -252,7 +298,8 @@ public class AddCommand extends GitCommand<DirCache> {
}
/**
- * Set whether to only match against already tracked files
+ * Set whether to only match against already tracked files. If
+ * {@code update == true}, re-sets a previous {@link #setAll(boolean)}.
*
* @param update
* If set to true, the command only matches {@code filepattern}
@@ -314,4 +361,32 @@ public class AddCommand extends GitCommand<DirCache> {
public boolean isRenormalize() {
return renormalize;
}
+
+ /**
+ * Defines whether the command will use '--all' mode: update existing index
+ * entries, add new entries, and remove index entries for which there is no
+ * file. (In other words: also stage deletions.)
+ * <p>
+ * The setting is independent of {@link #setUpdate(boolean)}.
+ * </p>
+ *
+ * @param all
+ * whether to enable '--all' mode
+ * @return {@code this}
+ * @since 7.2
+ */
+ public AddCommand setAll(boolean all) {
+ this.all = Boolean.valueOf(all);
+ return this;
+ }
+
+ /**
+ * Tells whether '--all' has been set for this command.
+ *
+ * @return {@code true} if it was set; {@code false} otherwise
+ * @since 7.2
+ */
+ public boolean isAll() {
+ return all != null && all.booleanValue();
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
index 805a886392..d2526287f9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
@@ -15,11 +15,11 @@ import static org.eclipse.jgit.lib.TypedConfigGetter.UNSET_INT;
import java.io.IOException;
import java.text.MessageFormat;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -76,6 +76,11 @@ public class DescribeCommand extends GitCommand<String> {
private List<FileNameMatcher> matchers = new ArrayList<>();
/**
+ * Pattern matchers to be applied to tags for exclusion.
+ */
+ private List<FileNameMatcher> excludeMatchers = new ArrayList<>();
+
+ /**
* Whether to use all refs in the refs/ namespace
*/
private boolean useAll;
@@ -263,6 +268,27 @@ public class DescribeCommand extends GitCommand<String> {
return this;
}
+ /**
+ * Sets one or more {@code glob(7)} patterns that tags must not match to be
+ * considered. If multiple patterns are provided, they will all be applied.
+ *
+ * @param patterns
+ * the {@code glob(7)} pattern or patterns
+ * @return {@code this}
+ * @throws org.eclipse.jgit.errors.InvalidPatternException
+ * if the pattern passed in was invalid.
+ * @see <a href=
+ * "https://www.kernel.org/pub/software/scm/git/docs/git-describe.html"
+ * >Git documentation about describe</a>
+ * @since 7.2
+ */
+ public DescribeCommand setExclude(String... patterns) throws InvalidPatternException {
+ for (String p : patterns) {
+ excludeMatchers.add(new FileNameMatcher(p, null));
+ }
+ return this;
+ }
+
private final Comparator<Ref> TAG_TIE_BREAKER = new Comparator<>() {
@Override
@@ -274,25 +300,28 @@ public class DescribeCommand extends GitCommand<String> {
}
}
- private Date tagDate(Ref tag) throws IOException {
+ private Instant tagDate(Ref tag) throws IOException {
RevTag t = w.parseTag(tag.getObjectId());
w.parseBody(t);
- return t.getTaggerIdent().getWhen();
+ return t.getTaggerIdent().getWhenAsInstant();
}
};
private Optional<Ref> getBestMatch(List<Ref> tags) {
if (tags == null || tags.isEmpty()) {
return Optional.empty();
- } else if (matchers.isEmpty()) {
+ } else if (matchers.isEmpty() && excludeMatchers.isEmpty()) {
Collections.sort(tags, TAG_TIE_BREAKER);
return Optional.of(tags.get(0));
- } else {
+ }
+
+ Stream<Ref> matchingTags;
+ if (!matchers.isEmpty()) {
// Find the first tag that matches in the stream of all tags
// filtered by matchers ordered by tie break order
- Stream<Ref> matchingTags = Stream.empty();
+ matchingTags = Stream.empty();
for (FileNameMatcher matcher : matchers) {
- Stream<Ref> m = tags.stream().filter(
+ Stream<Ref> m = tags.stream().filter( //
tag -> {
matcher.append(formatRefName(tag.getName()));
boolean result = matcher.isMatch();
@@ -301,8 +330,22 @@ public class DescribeCommand extends GitCommand<String> {
});
matchingTags = Stream.of(matchingTags, m).flatMap(i -> i);
}
- return matchingTags.sorted(TAG_TIE_BREAKER).findFirst();
+ } else {
+ // If there are no matchers, there are only excluders
+ // Assume all tags match for now before applying excluders
+ matchingTags = tags.stream();
+ }
+
+ for (FileNameMatcher matcher : excludeMatchers) {
+ matchingTags = matchingTags.filter( //
+ tag -> {
+ matcher.append(formatRefName(tag.getName()));
+ boolean result = matcher.isMatch();
+ matcher.reset();
+ return !result;
+ });
}
+ return matchingTags.sorted(TAG_TIE_BREAKER).findFirst();
}
private ObjectId getObjectIdFromRef(Ref r) throws JGitInternalException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java
index 0713c38931..f24127bd51 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java
@@ -124,7 +124,7 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
FetchRecurseSubmodulesMode mode = repo.getConfig().getEnum(
FetchRecurseSubmodulesMode.values(),
ConfigConstants.CONFIG_SUBMODULE_SECTION, path,
- ConfigConstants.CONFIG_KEY_FETCH_RECURSE_SUBMODULES, null);
+ ConfigConstants.CONFIG_KEY_FETCH_RECURSE_SUBMODULES);
if (mode != null) {
return mode;
}
@@ -132,7 +132,7 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
// Fall back to fetch.recurseSubmodules, if set
mode = repo.getConfig().getEnum(FetchRecurseSubmodulesMode.values(),
ConfigConstants.CONFIG_FETCH_SECTION, null,
- ConfigConstants.CONFIG_KEY_RECURSE_SUBMODULES, null);
+ ConfigConstants.CONFIG_KEY_RECURSE_SUBMODULES);
if (mode != null) {
return mode;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
index 88d7e91860..f6935e1c67 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/GarbageCollectCommand.java
@@ -12,6 +12,7 @@ package org.eclipse.jgit.api;
import java.io.IOException;
import java.text.MessageFormat;
import java.text.ParseException;
+import java.time.Instant;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
@@ -59,7 +60,7 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
private ProgressMonitor monitor;
- private Date expire;
+ private Instant expire;
private PackConfig pconfig;
@@ -98,8 +99,29 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
* @param expire
* minimal age of objects to be pruned.
* @return this instance
+ * @deprecated use {@link #setExpire(Instant)} instead
*/
+ @Deprecated(since = "7.2")
public GarbageCollectCommand setExpire(Date expire) {
+ if (expire != null) {
+ this.expire = expire.toInstant();
+ }
+ return this;
+ }
+
+ /**
+ * During gc() or prune() each unreferenced, loose object which has been
+ * created or modified after <code>expire</code> will not be pruned. Only
+ * older objects may be pruned. If set to null then every object is a
+ * candidate for pruning. Use {@link org.eclipse.jgit.util.GitTimeParser} to
+ * parse time formats used by git gc.
+ *
+ * @param expire
+ * minimal age of objects to be pruned.
+ * @return this instance
+ * @since 7.2
+ */
+ public GarbageCollectCommand setExpire(Instant expire) {
this.expire = expire;
return this;
}
@@ -108,8 +130,8 @@ public class GarbageCollectCommand extends GitCommand<Properties> {
* Whether to use aggressive mode or not. If set to true JGit behaves more
* similar to native git's "git gc --aggressive". If set to
* <code>true</code> compressed objects found in old packs are not reused
- * but every object is compressed again. Configuration variables
- * pack.window and pack.depth are set to 250 for this GC.
+ * but every object is compressed again. Configuration variables pack.window
+ * and pack.depth are set to 250 for this GC.
*
* @since 3.6
* @param aggressive
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
index 555e351d32..2a8d34ed68 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
@@ -110,10 +110,10 @@ public class LogCommand extends GitCommand<Iterable<RevCommit>> {
}
if (!filters.isEmpty()) {
if (filters.size() == 1) {
- filters.add(TreeFilter.ANY_DIFF);
+ walk.setTreeFilter(filters.get(0));
+ } else {
+ walk.setTreeFilter(AndTreeFilter.create(filters));
}
- walk.setTreeFilter(AndTreeFilter.create(filters));
-
}
if (skip > -1 && maxCount > -1)
walk.setRevFilter(AndRevFilter.create(SkipRevFilter.create(skip),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
index 83ae0fc9d4..4b2cee45c2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
@@ -533,9 +533,9 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
Config config) {
BranchRebaseMode mode = config.getEnum(BranchRebaseMode.values(),
ConfigConstants.CONFIG_BRANCH_SECTION,
- branchName, ConfigConstants.CONFIG_KEY_REBASE, null);
+ branchName, ConfigConstants.CONFIG_KEY_REBASE);
if (mode == null) {
- mode = config.getEnum(BranchRebaseMode.values(),
+ mode = config.getEnum(
ConfigConstants.CONFIG_PULL_SECTION, null,
ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE);
}
@@ -549,7 +549,7 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
Config config = repo.getConfig();
Merge ffMode = config.getEnum(Merge.values(),
ConfigConstants.CONFIG_PULL_SECTION, null,
- ConfigConstants.CONFIG_KEY_FF, null);
+ ConfigConstants.CONFIG_KEY_FF);
return ffMode != null ? FastForwardMode.valueOf(ffMode) : null;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
index 858bd961cd..3ae7a6c81e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -18,6 +18,8 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.MessageFormat;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -1835,23 +1837,26 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
// the time is saved as <seconds since 1970> <timezone offset>
int timeStart = 0;
- if (time.startsWith("@")) //$NON-NLS-1$
+ if (time.startsWith("@")) { //$NON-NLS-1$
timeStart = 1;
- else
+ } else {
timeStart = 0;
- long when = Long
- .parseLong(time.substring(timeStart, time.indexOf(' '))) * 1000;
+ }
+ Instant when = Instant.ofEpochSecond(
+ Long.parseLong(time.substring(timeStart, time.indexOf(' '))));
String tzOffsetString = time.substring(time.indexOf(' ') + 1);
int multiplier = -1;
- if (tzOffsetString.charAt(0) == '+')
+ if (tzOffsetString.charAt(0) == '+') {
multiplier = 1;
+ }
int hours = Integer.parseInt(tzOffsetString.substring(1, 3));
int minutes = Integer.parseInt(tzOffsetString.substring(3, 5));
// this is in format (+/-)HHMM (hours and minutes)
- // we need to convert into minutes
- int tz = (hours * 60 + minutes) * multiplier;
- if (name != null && email != null)
+ ZoneOffset tz = ZoneOffset.ofHoursMinutes(hours * multiplier,
+ minutes * multiplier);
+ if (name != null && email != null) {
return new PersonIdent(name, email, when, tz);
+ }
return null;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java
index dead2749b7..a149649004 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ReflogCommand.java
@@ -68,7 +68,7 @@ public class ReflogCommand extends GitCommand<Collection<ReflogEntry>> {
checkCallable();
try {
- ReflogReader reader = repo.getReflogReader(ref);
+ ReflogReader reader = repo.getRefDatabase().getReflogReader(ref);
if (reader == null)
throw new RefNotFoundException(MessageFormat.format(
JGitText.get().refNotResolved, ref));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java
index 23fbe0197f..2dba0ef0f2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashDropCommand.java
@@ -165,7 +165,8 @@ public class StashDropCommand extends GitCommand<ObjectId> {
List<ReflogEntry> entries;
try {
- ReflogReader reader = repo.getReflogReader(R_STASH);
+ ReflogReader reader = repo.getRefDatabase()
+ .getReflogReader(R_STASH);
if (reader == null) {
throw new RefNotFoundException(MessageFormat
.format(JGitText.get().refNotResolved, stashRef));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
index 3524984347..5e4b2ee0b7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleUpdateCommand.java
@@ -28,6 +28,7 @@ import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
@@ -39,6 +40,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.submodule.SubmoduleWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.util.FileUtils;
/**
* A class used to execute a submodule update command.
@@ -62,6 +64,8 @@ public class SubmoduleUpdateCommand extends
private boolean fetch = false;
+ private boolean clonedRestored;
+
/**
* <p>
* Constructor for SubmoduleUpdateCommand.
@@ -116,26 +120,77 @@ public class SubmoduleUpdateCommand extends
return this;
}
+ private static boolean submoduleExists(File gitDir) {
+ if (gitDir != null && gitDir.isDirectory()) {
+ File[] files = gitDir.listFiles();
+ return files != null && files.length != 0;
+ }
+ return false;
+ }
+
+ private static void restoreSubmodule(File gitDir, File workingTree)
+ throws IOException {
+ LockFile dotGitLock = new LockFile(
+ new File(workingTree, Constants.DOT_GIT));
+ if (dotGitLock.lock()) {
+ String content = Constants.GITDIR
+ + getRelativePath(gitDir, workingTree);
+ dotGitLock.write(Constants.encode(content));
+ dotGitLock.commit();
+ }
+ }
+
+ private static String getRelativePath(File gitDir, File workingTree) {
+ File relPath;
+ try {
+ relPath = workingTree.toPath().relativize(gitDir.toPath())
+ .toFile();
+ } catch (IllegalArgumentException e) {
+ relPath = gitDir;
+ }
+ return FileUtils.pathToString(relPath);
+ }
+
+ private String determineUpdateMode(String mode) {
+ if (clonedRestored) {
+ return ConfigConstants.CONFIG_KEY_CHECKOUT;
+ }
+ return mode;
+ }
+
private Repository getOrCloneSubmodule(SubmoduleWalk generator, String url)
throws IOException, GitAPIException {
Repository repository = generator.getRepository();
+ boolean restored = false;
+ boolean cloned = false;
if (repository == null) {
- if (callback != null) {
- callback.cloningSubmodule(generator.getPath());
- }
- CloneCommand clone = Git.cloneRepository();
- configure(clone);
- clone.setURI(url);
- clone.setDirectory(generator.getDirectory());
- clone.setGitDir(new File(
+ File gitDir = new File(
new File(repo.getCommonDirectory(), Constants.MODULES),
- generator.getPath()));
- clone.setRelativePaths(true);
- if (monitor != null) {
- clone.setProgressMonitor(monitor);
+ generator.getPath());
+ if (submoduleExists(gitDir)) {
+ restoreSubmodule(gitDir, generator.getDirectory());
+ restored = true;
+ clonedRestored = true;
+ repository = generator.getRepository();
+ } else {
+ if (callback != null) {
+ callback.cloningSubmodule(generator.getPath());
+ }
+ CloneCommand clone = Git.cloneRepository();
+ configure(clone);
+ clone.setURI(url);
+ clone.setDirectory(generator.getDirectory());
+ clone.setGitDir(gitDir);
+ clone.setRelativePaths(true);
+ if (monitor != null) {
+ clone.setProgressMonitor(monitor);
+ }
+ repository = clone.call().getRepository();
+ cloned = true;
+ clonedRestored = true;
}
- repository = clone.call().getRepository();
- } else if (this.fetch) {
+ }
+ if ((this.fetch || restored) && !cloned) {
if (fetchCallback != null) {
fetchCallback.fetchingSubmodule(generator.getPath());
}
@@ -172,15 +227,17 @@ public class SubmoduleUpdateCommand extends
continue;
// Skip submodules not registered in parent repository's config
String url = generator.getConfigUrl();
- if (url == null)
+ if (url == null) {
continue;
-
+ }
+ clonedRestored = false;
try (Repository submoduleRepo = getOrCloneSubmodule(generator,
url); RevWalk walk = new RevWalk(submoduleRepo)) {
RevCommit commit = walk
.parseCommit(generator.getObjectId());
- String update = generator.getConfigUpdate();
+ String update = determineUpdateMode(
+ generator.getConfigUpdate());
if (ConfigConstants.CONFIG_KEY_MERGE.equals(update)) {
MergeCommand merge = new MergeCommand(submoduleRepo);
merge.include(commit);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
index 77967df2e5..979c8cef88 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameGenerator.java
@@ -28,6 +28,8 @@ import org.eclipse.jgit.blame.Candidate.BlobCandidate;
import org.eclipse.jgit.blame.Candidate.HeadCandidate;
import org.eclipse.jgit.blame.Candidate.ReverseCandidate;
import org.eclipse.jgit.blame.ReverseWalk.ReverseCommit;
+import org.eclipse.jgit.blame.cache.BlameCache;
+import org.eclipse.jgit.blame.cache.CacheRegion;
import org.eclipse.jgit.diff.DiffAlgorithm;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
@@ -129,8 +131,19 @@ public class BlameGenerator implements AutoCloseable {
/** Blame is currently assigned to this source. */
private Candidate outCandidate;
+
private Region outRegion;
+ private final BlameCache blameCache;
+
+ /**
+ * Blame in reverse order needs the source lines, but we don't have them in
+ * the cache. We need to ignore the cache in that case.
+ */
+ private boolean useCache = true;
+
+ private final Stats stats = new Stats();
+
/**
* Create a blame generator for the repository and path (relative to
* repository)
@@ -142,6 +155,25 @@ public class BlameGenerator implements AutoCloseable {
* repository).
*/
public BlameGenerator(Repository repository, String path) {
+ this(repository, path, null);
+ }
+
+ /**
+ * Create a blame generator for the repository and path (relative to
+ * repository)
+ *
+ * @param repository
+ * repository to access revision data from.
+ * @param path
+ * initial path of the file to start scanning (relative to the
+ * repository).
+ * @param blameCache
+ * previously calculated blames. This generator will *not*
+ * populate it, just consume it.
+ * @since 7.2
+ */
+ public BlameGenerator(Repository repository, String path,
+ @Nullable BlameCache blameCache) {
this.repository = repository;
this.resultPath = PathFilter.create(path);
@@ -150,6 +182,7 @@ public class BlameGenerator implements AutoCloseable {
initRevPool(false);
remaining = -1;
+ this.blameCache = blameCache;
}
private void initRevPool(boolean reverse) {
@@ -159,10 +192,12 @@ public class BlameGenerator implements AutoCloseable {
if (revPool != null)
revPool.close();
- if (reverse)
+ if (reverse) {
+ useCache = false;
revPool = new ReverseWalk(getRepository());
- else
+ } else {
revPool = new RevWalk(getRepository());
+ }
SEEN = revPool.newFlag("SEEN"); //$NON-NLS-1$
reader = revPool.getObjectReader();
@@ -245,6 +280,31 @@ public class BlameGenerator implements AutoCloseable {
}
/**
+ * Stats about this generator
+ *
+ * @return the stats of this generator
+ * @since 7.2
+ */
+ public Stats getStats() {
+ return stats;
+ }
+
+ /**
+ * Enable/disable the use of cache (if present). Enabled by default.
+ * <p>
+ * If caller need source line numbers, the generator cannot use the cache
+ * (source lines are not there). Use this method to disable the cache in
+ * that case.
+ *
+ * @param useCache
+ * should this generator use the cache.
+ * @since 7.2
+ */
+ public void setUseCache(boolean useCache) {
+ this.useCache = useCache;
+ }
+
+ /**
* Push a candidate blob onto the generator's traversal stack.
* <p>
* Candidates should be pushed in history order from oldest-to-newest.
@@ -591,6 +651,7 @@ public class BlameGenerator implements AutoCloseable {
Candidate n = pop();
if (n == null)
return done();
+ stats.candidatesVisited += 1;
int pCnt = n.getParentCount();
if (pCnt == 1) {
@@ -605,7 +666,7 @@ public class BlameGenerator implements AutoCloseable {
// Do not generate a tip of a reverse. The region
// survives and should not appear to be deleted.
- } else /* if (pCnt == 0) */{
+ } else /* if (pCnt == 0) */ {
// Root commit, with at least one surviving region.
// Assign the remaining blame here.
return result(n);
@@ -695,6 +756,27 @@ public class BlameGenerator implements AutoCloseable {
}
}
+ @Nullable
+ private Candidate blameFromCache(Candidate n) throws IOException {
+ if (blameCache == null || !useCache) {
+ return null;
+ }
+
+ List<CacheRegion> cachedBlame = blameCache.get(repository,
+ n.sourceCommit, n.sourcePath.getPath());
+ if (cachedBlame == null) {
+ return null;
+ }
+ BlameRegionMerger rb = new BlameRegionMerger(repository, revPool,
+ cachedBlame);
+ Candidate fullyBlamed = rb.mergeCandidate(n);
+ if (fullyBlamed == null) {
+ return null;
+ }
+ stats.cacheHit = true;
+ return fullyBlamed;
+ }
+
private boolean processOne(Candidate n) throws IOException {
RevCommit parent = n.getParent(0);
if (parent == null)
@@ -717,12 +799,17 @@ public class BlameGenerator implements AutoCloseable {
if (0 == r.getOldId().prefixCompare(n.sourceBlob)) {
// A 100% rename without any content change can also
// skip directly to the parent.
+ Candidate cached = blameFromCache(n);
+ if (cached != null) {
+ return result(cached);
+ }
n.sourceCommit = parent;
n.sourcePath = PathFilter.create(r.getOldPath());
push(n);
return false;
}
+
Candidate next = n.create(getRepository(), parent,
PathFilter.create(r.getOldPath()));
next.sourceBlob = r.getOldId().toObjectId();
@@ -759,6 +846,11 @@ public class BlameGenerator implements AutoCloseable {
return false;
}
+ Candidate cached = blameFromCache(source);
+ if (cached != null) {
+ return result(cached);
+ }
+
parent.takeBlame(editList, source);
if (parent.regionList != null)
push(parent);
@@ -846,8 +938,8 @@ public class BlameGenerator implements AutoCloseable {
editList = new EditList(0);
} else {
p.loadText(reader);
- editList = diffAlgorithm.diff(textComparator,
- p.sourceText, n.sourceText);
+ editList = diffAlgorithm.diff(textComparator, p.sourceText,
+ n.sourceText);
}
if (editList.isEmpty()) {
@@ -981,6 +1073,10 @@ public class BlameGenerator implements AutoCloseable {
/**
* Get first line of the source data that has been blamed for the current
* region
+ * <p>
+ * This value is not reliable when the generator is reusing cached values.
+ * Cache doesn't keep the source lines, the returned value is based on the
+ * result and can be off if the region moved in previous commits.
*
* @return first line of the source data that has been blamed for the
* current region. This is line number of where the region was added
@@ -994,6 +1090,10 @@ public class BlameGenerator implements AutoCloseable {
/**
* Get one past the range of the source data that has been blamed for the
* current region
+ * <p>
+ * This value is not reliable when the generator is reusing cached values.
+ * Cache doesn't keep the source lines, the returned value is based on the
+ * result and can be off if the region moved in previous commits.
*
* @return one past the range of the source data that has been blamed for
* the current region. This is line number of where the region was
@@ -1124,4 +1224,39 @@ public class BlameGenerator implements AutoCloseable {
return ent.getChangeType() == ChangeType.RENAME
|| ent.getChangeType() == ChangeType.COPY;
}
+
+ /**
+ * Stats about the work done by the generator
+ *
+ * @since 7.2
+ */
+ public static class Stats {
+
+ /** Candidates taken from the queue */
+ private int candidatesVisited;
+
+ private boolean cacheHit;
+
+ /**
+ * Number of candidates taken from the queue
+ * <p>
+ * The generator could signal it's done without exhausting all
+ * candidates if there is no more remaining lines or the last visited
+ * candidate is found in the cache.
+ *
+ * @return number of candidates taken from the queue
+ */
+ public int getCandidatesVisited() {
+ return candidatesVisited;
+ }
+
+ /**
+ * The generator found a blamed version in the cache
+ *
+ * @return true if we used results from the cache
+ */
+ public boolean isCacheHit() {
+ return cacheHit;
+ }
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameRegionMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameRegionMerger.java
new file mode 100644
index 0000000000..67bc6fb789
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/BlameRegionMerger.java
@@ -0,0 +1,158 @@
+/*
+ * 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.blame;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jgit.blame.cache.CacheRegion;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+
+/**
+ * Translates an unblamed region into one or more blamed regions, using the
+ * fully blamed data from cache.
+ * <p>
+ * Blamed and unblamed regions are not symmetrical: An unblamed region is just a
+ * range of lines over the file. A blamed region is a Candidate (with the commit
+ * info) with a region inside (the range blamed).
+ */
+class BlameRegionMerger {
+ private final Repository repo;
+
+ private final List<CacheRegion> cachedRegions;
+
+ private final RevWalk rw;
+
+ BlameRegionMerger(Repository repo, RevWalk rw,
+ List<CacheRegion> cachedRegions) {
+ this.repo = repo;
+ List<CacheRegion> sorted = new ArrayList<>(cachedRegions);
+ Collections.sort(sorted);
+ this.cachedRegions = sorted;
+ this.rw = rw;
+ }
+
+ /**
+ * Return one or more candidates blaming all the regions of the "unblamed"
+ * incoming candidate.
+ *
+ * @param candidate
+ * a candidate with a list of unblamed regions
+ * @return A linked list of Candidates with their blamed regions, null if
+ * there was any error.
+ */
+ Candidate mergeCandidate(Candidate candidate) {
+ List<Candidate> newCandidates = new ArrayList<>();
+ Region r = candidate.regionList;
+ while (r != null) {
+ try {
+ newCandidates.addAll(mergeOneRegion(r));
+ } catch (IOException e) {
+ return null;
+ }
+ r = r.next;
+ }
+ return asLinkedCandidate(newCandidates);
+ }
+
+ // Visible for testing
+ List<Candidate> mergeOneRegion(Region region) throws IOException {
+ List<CacheRegion> overlaps = findOverlaps(region);
+ if (overlaps.isEmpty()) {
+ throw new IOException(
+ "Cached blame should cover all lines");
+ }
+ /*
+ * Cached regions cover the whole file. We find first which ones overlap
+ * with our unblamed region. Then we take the overlapping portions with
+ * the corresponding blame.
+ */
+ List<Candidate> candidates = new ArrayList<>();
+ for (CacheRegion overlap : overlaps) {
+ Region blamedRegions = intersectRegions(region, overlap);
+ Candidate c = new Candidate(repo, parse(overlap.getSourceCommit()),
+ PathFilter.create(overlap.getSourcePath()));
+ c.regionList = blamedRegions;
+ candidates.add(c);
+ }
+ return candidates;
+ }
+
+ // Visible for testing
+ List<CacheRegion> findOverlaps(Region unblamed) {
+ int unblamedStart = unblamed.sourceStart;
+ int unblamedEnd = unblamedStart + unblamed.length;
+ List<CacheRegion> overlapping = new ArrayList<>();
+ for (CacheRegion blamed : cachedRegions) {
+ // End is not included
+ if (blamed.getEnd() <= unblamedStart) {
+ // Blamed region is completely before
+ continue;
+ }
+
+ if (blamed.getStart() >= unblamedEnd) {
+ // Blamed region is completely after
+ // Blamed regions are sorted by start position, nothing will
+ // match anymore
+ break;
+ }
+ overlapping.add(blamed);
+ }
+ return overlapping;
+ }
+
+ // Visible for testing
+ /**
+ * Calculate the intersection between a Region and a CacheRegion, adjusting
+ * the start if needed.
+ * <p>
+ * This should be called only if there is an overlap (filtering the cached
+ * regions with {@link #findOverlaps(Region)}), otherwise the result is
+ * meaningless.
+ *
+ * @param unblamed
+ * a region from the blame generator
+ * @param cached
+ * a cached region
+ * @return a new region with the intersection.
+ */
+ static Region intersectRegions(Region unblamed, CacheRegion cached) {
+ int blamedStart = Math.max(cached.getStart(), unblamed.sourceStart);
+ int blamedEnd = Math.min(cached.getEnd(),
+ unblamed.sourceStart + unblamed.length);
+ int length = blamedEnd - blamedStart;
+
+ // result start and source start should move together
+ int blameStartDelta = blamedStart - unblamed.sourceStart;
+ return new Region(unblamed.resultStart + blameStartDelta, blamedStart,
+ length);
+ }
+
+ // Tests can override this, so they don't need a real repo, commit and walk
+ protected RevCommit parse(ObjectId oid) throws IOException {
+ return rw.parseCommit(oid);
+ }
+
+ private static Candidate asLinkedCandidate(List<Candidate> c) {
+ Candidate head = c.get(0);
+ Candidate tail = head;
+ for (int i = 1; i < c.size(); i++) {
+ tail.queueNext = c.get(i);
+ tail = tail.queueNext;
+ }
+ return head;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/BlameCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/BlameCache.java
new file mode 100644
index 0000000000..d44fb5f62b
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/BlameCache.java
@@ -0,0 +1,46 @@
+/*
+ * 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.blame.cache;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Keeps the blame information for a path at certain commit.
+ * <p>
+ * If there is a result, it covers the whole file at that revision
+ *
+ * @since 7.2
+ */
+public interface BlameCache {
+ /**
+ * Gets the blame of a path at a given commit if available.
+ * <p>
+ * Since this cache is used in blame calculation, this get() method should
+ * only retrieve the cache value, and not re-trigger blame calculation. In
+ * other words, this acts as "getIfPresent", and not "computeIfAbsent".
+ *
+ * @param repo
+ * repository containing the commit
+ * @param commitId
+ * we are looking at the file in this revision
+ * @param path
+ * path a file in the repo
+ *
+ * @return the blame of a path at a given commit or null if not in cache
+ * @throws IOException
+ * error retrieving/parsing values from storage
+ */
+ List<CacheRegion> get(Repository repo, ObjectId commitId, String path)
+ throws IOException;
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/CacheRegion.java b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/CacheRegion.java
new file mode 100644
index 0000000000..cf3f978044
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/blame/cache/CacheRegion.java
@@ -0,0 +1,125 @@
+/*
+ * 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.blame.cache;
+
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * Region of the blame of a file.
+ * <p>
+ * Usually all parameters are non-null, except when the Region was created
+ * to fill an unblamed gap (to cover for bugs in the calculation). In that
+ * case, path, commit and author will be null.
+ *
+ * @since 7.2
+ **/
+public class CacheRegion implements Comparable<CacheRegion> {
+ private final String sourcePath;
+
+ private final ObjectId sourceCommit;
+
+ private final int end;
+
+ private final int start;
+
+ /**
+ * A blamed portion of a file
+ *
+ * @param path
+ * location of the file
+ * @param commit
+ * commit that is modifying this region
+ * @param start
+ * first line of this region (inclusive)
+ * @param end
+ * last line of this region (non-inclusive!)
+ */
+ public CacheRegion(String path, ObjectId commit,
+ int start, int end) {
+ allOrNoneNull(path, commit);
+ this.sourcePath = path;
+ this.sourceCommit = commit;
+ this.start = start;
+ this.end = end;
+ }
+
+ /**
+ * First line of this region. Starting by 0, inclusive
+ *
+ * @return first line of this region.
+ */
+ public int getStart() {
+ return start;
+ }
+
+ /**
+ * One after last line in this region (or: last line non-inclusive)
+ *
+ * @return one after last line in this region.
+ */
+ public int getEnd() {
+ return end;
+ }
+
+
+ /**
+ * Path of the file this region belongs to
+ *
+ * @return path in the repo/commit
+ */
+ public String getSourcePath() {
+ return sourcePath;
+ }
+
+ /**
+ * Commit this region belongs to
+ *
+ * @return commit for this region
+ */
+ public ObjectId getSourceCommit() {
+ return sourceCommit;
+ }
+
+ @Override
+ public int compareTo(CacheRegion o) {
+ return start - o.start;
+ }
+
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (sourceCommit != null) {
+ sb.append(sourceCommit.name(), 0, 7).append(' ')
+ .append(" (")
+ .append(sourcePath).append(')');
+ } else {
+ sb.append("<unblamed region>");
+ }
+ sb.append(' ').append("start=").append(start).append(", count=")
+ .append(end - start);
+ return sb.toString();
+ }
+
+ private static void allOrNoneNull(String path, ObjectId commit) {
+ if (path != null && commit != null) {
+ return;
+ }
+
+ if (path == null && commit == null) {
+ return;
+ }
+ throw new IllegalArgumentException(MessageFormat
+ .format(JGitText.get().cacheRegionAllOrNoneNull, path, commit));
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java
index accf732dc7..de02aecdb9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/Checkout.java
@@ -217,10 +217,18 @@ public class Checkout {
}
}
try {
- if (recursiveDelete && Files.isDirectory(f.toPath(),
- LinkOption.NOFOLLOW_LINKS)) {
+ boolean isDir = Files.isDirectory(f.toPath(),
+ LinkOption.NOFOLLOW_LINKS);
+ if (recursiveDelete && isDir) {
FileUtils.delete(f, FileUtils.RECURSIVE);
}
+ if (cache.getRepository().isWorkTreeCaseInsensitive() && !isDir) {
+ // We cannot rely on rename via Files.move() to work correctly
+ // if the target exists in a case variant. For instance with JDK
+ // 17 on Mac OS, the existing case-variant name is kept. On
+ // Windows 11 it would work and use the name given in 'f'.
+ FileUtils.delete(f, FileUtils.SKIP_MISSING);
+ }
FileUtils.rename(tmpFile, f, StandardCopyOption.ATOMIC_MOVE);
cachedParent.remove(f.getName());
} catch (IOException e) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
index 34dba0b5be..c650d6e8e7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
@@ -1037,7 +1037,12 @@ public class DirCache {
}
}
- enum DirCacheVersion implements ConfigEnum {
+ /**
+ * DirCache versions
+ *
+ * @since 7.2
+ */
+ public enum DirCacheVersion implements ConfigEnum {
/** Minimum index version on-disk format that we support. */
DIRC_VERSION_MINIMUM(2),
@@ -1060,6 +1065,9 @@ public class DirCache {
this.version = versionCode;
}
+ /**
+ * @return the version code for this version
+ */
public int getVersionCode() {
return version;
}
@@ -1078,6 +1086,13 @@ public class DirCache {
}
}
+ /**
+ * Create DirCacheVersion from integer value of the version code.
+ *
+ * @param val
+ * integer value of the version code.
+ * @return the DirCacheVersion instance of the version code.
+ */
public static DirCacheVersion fromInt(int val) {
for (DirCacheVersion v : DirCacheVersion.values()) {
if (val == v.getVersionCode()) {
@@ -1098,9 +1113,8 @@ public class DirCache {
boolean manyFiles = cfg.getBoolean(
ConfigConstants.CONFIG_FEATURE_SECTION,
ConfigConstants.CONFIG_KEY_MANYFILES, false);
- indexVersion = cfg.getEnum(DirCacheVersion.values(),
- ConfigConstants.CONFIG_INDEX_SECTION, null,
- ConfigConstants.CONFIG_KEY_VERSION,
+ indexVersion = cfg.getEnum(ConfigConstants.CONFIG_INDEX_SECTION,
+ null, ConfigConstants.CONFIG_KEY_VERSION,
manyFiles ? DirCacheVersion.DIRC_VERSION_PATHCOMPRESS
: DirCacheVersion.DIRC_VERSION_EXTENDED);
skipHash = cfg.getBoolean(ConfigConstants.CONFIG_INDEX_SECTION,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
index 4f78404f48..18d77482e0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -5,7 +5,7 @@
* Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2010, Chrisian Halstrick <christian.halstrick@sap.com>
* Copyright (C) 2019, 2020, Andre Bossert <andre.bossert@siemens.com>
- * Copyright (C) 2017, 2023, Thomas Wolf <twolf@apache.org> and others
+ * Copyright (C) 2017, 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
@@ -31,6 +31,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import org.eclipse.jgit.api.errors.CanceledException;
import org.eclipse.jgit.api.errors.FilterFailedException;
@@ -66,7 +67,6 @@ import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FS.ExecutionResult;
-import org.eclipse.jgit.util.IntList;
import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.io.EolStreamTypeUtil;
import org.slf4j.Logger;
@@ -113,9 +113,11 @@ public class DirCacheCheckout {
private Map<String, CheckoutMetadata> updated = new LinkedHashMap<>();
+ private Set<String> existing;
+
private ArrayList<String> conflicts = new ArrayList<>();
- private ArrayList<String> removed = new ArrayList<>();
+ private TreeSet<String> removed;
private ArrayList<String> kept = new ArrayList<>();
@@ -185,7 +187,7 @@ public class DirCacheCheckout {
* @return a list of all files removed by this checkout
*/
public List<String> getRemoved() {
- return removed;
+ return new ArrayList<>(removed);
}
/**
@@ -214,6 +216,14 @@ public class DirCacheCheckout {
this.mergeCommitTree = mergeCommitTree;
this.workingTree = workingTree;
this.initialCheckout = !repo.isBare() && !repo.getIndexFile().exists();
+ boolean caseInsensitive = !repo.isBare()
+ && repo.isWorkTreeCaseInsensitive();
+ this.removed = caseInsensitive
+ ? new TreeSet<>(String::compareToIgnoreCase)
+ : new TreeSet<>();
+ this.existing = caseInsensitive
+ ? new TreeSet<>(String::compareToIgnoreCase)
+ : null;
}
/**
@@ -400,9 +410,11 @@ public class DirCacheCheckout {
// content to be checked out.
update(m);
}
- } else
+ } else {
update(m);
- } else if (f == null || !m.idEqual(i)) {
+ }
+ } else if (f == null || !m.idEqual(i)
+ || m.getEntryRawMode() != i.getEntryRawMode()) {
// The working tree file is missing or the merge content differs
// from index content
update(m);
@@ -410,11 +422,11 @@ public class DirCacheCheckout {
// The index contains a file (and not a folder)
if (f.isModified(i.getDirCacheEntry(), true,
this.walk.getObjectReader())
- || i.getDirCacheEntry().getStage() != 0)
+ || i.getDirCacheEntry().getStage() != 0) {
// The working tree file is dirty or the index contains a
// conflict
update(m);
- else {
+ } else {
// update the timestamp of the index with the one from the
// file if not set, as we are sure to be in sync here.
DirCacheEntry entry = i.getDirCacheEntry();
@@ -424,9 +436,10 @@ public class DirCacheCheckout {
}
keep(i.getEntryPathString(), entry, f);
}
- } else
+ } else {
// The index contains a folder
keep(i.getEntryPathString(), i.getDirCacheEntry(), f);
+ }
} else {
// There is no entry in the merge commit. Means: we want to delete
// what's currently in the index and working tree
@@ -521,6 +534,13 @@ public class DirCacheCheckout {
// update our index
builder.finish();
+ // On case-insensitive file systems we may have a case variant kept
+ // and another one removed. In that case, don't remove it.
+ if (existing != null) {
+ removed.removeAll(existing);
+ existing.clear();
+ }
+
// init progress reporting
int numTotal = removed.size() + updated.size() + conflicts.size();
monitor.beginTask(JGitText.get().checkingOutFiles, numTotal);
@@ -531,9 +551,9 @@ public class DirCacheCheckout {
// when deleting files process them in the opposite order as they have
// been reported. This ensures the files are deleted before we delete
// their parent folders
- IntList nonDeleted = new IntList();
- for (int i = removed.size() - 1; i >= 0; i--) {
- String r = removed.get(i);
+ Iterator<String> iter = removed.descendingIterator();
+ while (iter.hasNext()) {
+ String r = iter.next();
file = new File(repo.getWorkTree(), r);
if (!file.delete() && repo.getFS().exists(file)) {
// The list of stuff to delete comes from the index
@@ -542,7 +562,7 @@ public class DirCacheCheckout {
// to delete it. A submodule is not empty, so it
// is safe to check this after a failed delete.
if (!repo.getFS().isDirectory(file)) {
- nonDeleted.add(i);
+ iter.remove();
toBeDeleted.add(r);
}
} else {
@@ -560,8 +580,6 @@ public class DirCacheCheckout {
if (file != null) {
removeEmptyParents(file);
}
- removed = filterOut(removed, nonDeleted);
- nonDeleted = null;
Iterator<Map.Entry<String, CheckoutMetadata>> toUpdate = updated
.entrySet().iterator();
Map.Entry<String, CheckoutMetadata> e = null;
@@ -633,36 +651,6 @@ public class DirCacheCheckout {
return toBeDeleted.isEmpty();
}
- private static ArrayList<String> filterOut(ArrayList<String> strings,
- IntList indicesToRemove) {
- int n = indicesToRemove.size();
- if (n == strings.size()) {
- return new ArrayList<>(0);
- }
- switch (n) {
- case 0:
- return strings;
- case 1:
- strings.remove(indicesToRemove.get(0));
- return strings;
- default:
- int length = strings.size();
- ArrayList<String> result = new ArrayList<>(length - n);
- // Process indicesToRemove from the back; we know that it
- // contains indices in descending order.
- int j = n - 1;
- int idx = indicesToRemove.get(j);
- for (int i = 0; i < length; i++) {
- if (i == idx) {
- idx = (--j >= 0) ? indicesToRemove.get(j) : -1;
- } else {
- result.add(strings.get(i));
- }
- }
- return result;
- }
- }
-
private static boolean isSamePrefix(String a, String b) {
int as = a.lastIndexOf('/');
int bs = b.lastIndexOf('/');
@@ -1233,6 +1221,9 @@ public class DirCacheCheckout {
if (!FileMode.TREE.equals(e.getFileMode())) {
builder.add(e);
}
+ if (existing != null) {
+ existing.add(path);
+ }
if (force) {
if (f == null || f.isModified(e, true, walk.getObjectReader())) {
kept.add(path);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java
index b033177e05..58b4d3dc56 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/gitrepo/ManifestParser.java
@@ -142,7 +142,17 @@ public class ManifestParser extends DefaultHandler {
xmlInRead++;
final XMLReader xr;
try {
- xr = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ spf.setFeature(
+ "http://xml.org/sax/features/external-general-entities", //$NON-NLS-1$
+ false);
+ spf.setFeature(
+ "http://xml.org/sax/features/external-parameter-entities", //$NON-NLS-1$
+ false);
+ spf.setFeature(
+ "http://apache.org/xml/features/disallow-doctype-decl", //$NON-NLS-1$
+ true);
+ xr = spf.newSAXParser().getXMLReader();
} catch (SAXException | ParserConfigurationException e) {
throw new IOException(JGitText.get().noXMLParserAvailable, e);
}
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 2d9d2c527c..8928f47290 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -94,8 +94,6 @@ public class JGitText extends TranslationBundle {
/***/ public String binaryHunkInvalidLength;
/***/ public String binaryHunkLineTooShort;
/***/ public String binaryHunkMissingNewline;
- /***/ public String bitmapAccessErrorForPackfile;
- /***/ public String bitmapFailedToGet;
/***/ public String bitmapMissingObject;
/***/ public String bitmapsMustBePrepared;
/***/ public String bitmapUseNoopNoListener;
@@ -108,6 +106,7 @@ public class JGitText extends TranslationBundle {
/***/ public String buildingBitmaps;
/***/ public String cachedPacksPreventsIndexCreation;
/***/ public String cachedPacksPreventsListingObjects;
+ /***/ public String cacheRegionAllOrNoneNull;
/***/ public String cannotAccessLastModifiedForSafeDeletion;
/***/ public String cannotBeCombined;
/***/ public String cannotBeRecursiveWhenTreesAreIncluded;
@@ -295,6 +294,7 @@ public class JGitText extends TranslationBundle {
/***/ public String deleteTagUnexpectedResult;
/***/ public String deletingBranches;
/***/ public String deletingNotSupported;
+ /***/ public String deprecatedTrustFolderStat;
/***/ public String depthMustBeAt1;
/***/ public String depthWithUnshallow;
/***/ public String destinationIsNotAWildcard;
@@ -493,6 +493,7 @@ public class JGitText extends TranslationBundle {
/***/ public String invalidTimeUnitValue2;
/***/ public String invalidTimeUnitValue3;
/***/ public String invalidTreeZeroLengthName;
+ /***/ public String invalidTrustStat;
/***/ public String invalidURL;
/***/ public String invalidWildcards;
/***/ public String invalidRefSpec;
@@ -525,6 +526,8 @@ public class JGitText extends TranslationBundle {
/***/ public String logLargerFiletimeDiff;
/***/ public String logSmallerFiletime;
/***/ public String logXDGConfigHomeInvalid;
+
+ /***/ public String logXDGCacheHomeInvalid;
/***/ public String looseObjectHandleIsStale;
/***/ public String maxCountMustBeNonNegative;
/***/ public String mergeConflictOnNonNoteEntries;
@@ -537,6 +540,9 @@ public class JGitText extends TranslationBundle {
/***/ public String mergeToolNotGivenError;
/***/ public String mergeToolNullError;
/***/ public String messageAndTaggerNotAllowedInUnannotatedTags;
+ /***/ public String midxChunkNeeded;
+ /***/ public String midxChunkRepeated;
+ /***/ public String midxChunkUnknown;
/***/ public String minutesAgo;
/***/ public String mismatchOffset;
/***/ public String mismatchCRC;
@@ -557,6 +563,10 @@ public class JGitText extends TranslationBundle {
/***/ public String month;
/***/ public String months;
/***/ public String monthsAgo;
+ /***/ public String multiPackIndexFileIsTooLargeForJgit;
+ /***/ public String multiPackIndexPackCountMismatch;
+ /***/ public String multiPackIndexUnexpectedSize;
+ /***/ public String multiPackIndexWritingCancelled;
/***/ public String multipleMergeBasesFor;
/***/ public String nameMustNotBeNullOrEmpty;
/***/ public String need2Arguments;
@@ -583,6 +593,7 @@ public class JGitText extends TranslationBundle {
/***/ public String notACommitGraph;
/***/ public String notADIRCFile;
/***/ public String notAGitDirectory;
+ /***/ public String notAMIDX;
/***/ public String notAPACKFile;
/***/ public String notARef;
/***/ public String notASCIIString;
@@ -645,6 +656,7 @@ public class JGitText extends TranslationBundle {
/***/ public String personIdentEmailNonNull;
/***/ public String personIdentNameNonNull;
/***/ public String postCommitHookFailed;
+ /***/ public String precedenceTrustConfig;
/***/ public String prefixRemote;
/***/ public String problemWithResolvingPushRefSpecsLocally;
/***/ public String progressMonUploading;
@@ -877,6 +889,7 @@ public class JGitText extends TranslationBundle {
/***/ public String unmergedPaths;
/***/ public String unpackException;
/***/ public String unreadableCommitGraph;
+ /***/ public String unreadableMIDX;
/***/ public String unreadableObjectSizeIndex;
/***/ public String unreadablePackIndex;
/***/ public String unrecognizedPackExtension;
@@ -890,6 +903,7 @@ public class JGitText extends TranslationBundle {
/***/ public String unsupportedEncryptionVersion;
/***/ public String unsupportedGC;
/***/ public String unsupportedMark;
+ /***/ public String unsupportedMIDXVersion;
/***/ public String unsupportedObjectIdVersion;
/***/ public String unsupportedObjectSizeIndexVersion;
/***/ public String unsupportedOperationNotAddAtEnd;
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 e6068a15ec..199481cf33 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
@@ -90,7 +90,7 @@ public class DfsGarbageCollector {
private long coalesceGarbageLimit = 50 << 20;
private long garbageTtlMillis = TimeUnit.DAYS.toMillis(1);
- private long startTimeMillis;
+ private Instant startTime;
private List<DfsPackFile> packsBefore;
private List<DfsReftable> reftablesBefore;
private List<DfsPackFile> expiredGarbagePacks;
@@ -352,7 +352,7 @@ public class DfsGarbageCollector {
throw new IllegalStateException(
JGitText.get().supportOnlyPackIndexVersion2);
- startTimeMillis = SystemReader.getInstance().getCurrentTime();
+ startTime = SystemReader.getInstance().now();
ctx = objdb.newReader();
try {
refdb.refresh();
@@ -435,7 +435,7 @@ public class DfsGarbageCollector {
packsBefore = new ArrayList<>(packs.length);
expiredGarbagePacks = new ArrayList<>(packs.length);
- long now = SystemReader.getInstance().getCurrentTime();
+ long now = SystemReader.getInstance().now().toEpochMilli();
for (DfsPackFile p : packs) {
DfsPackDescription d = p.getPackDescription();
if (d.getPackSource() != UNREACHABLE_GARBAGE) {
@@ -723,7 +723,7 @@ public class DfsGarbageCollector {
PackStatistics stats = pw.getStatistics();
pack.setPackStats(stats);
- pack.setLastModified(startTimeMillis);
+ pack.setLastModified(startTime.toEpochMilli());
newPackDesc.add(pack);
newPackStats.add(stats);
newPackObj.add(pw.getObjectSet());
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java
index 16315bf4f2..dd9e4b96a4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java
@@ -83,7 +83,6 @@ public class DfsInserter extends ObjectInserter {
DfsPackDescription packDsc;
PackStream packOut;
private boolean rollback;
- private boolean checkExisting = true;
/**
* Initialize a new inserter.
@@ -98,18 +97,6 @@ public class DfsInserter extends ObjectInserter {
ConfigConstants.CONFIG_KEY_MIN_BYTES_OBJ_SIZE_INDEX, -1);
}
- /**
- * Check existence
- *
- * @param check
- * if {@code false}, will write out possibly-duplicate objects
- * without first checking whether they exist in the repo; default
- * is true.
- */
- public void checkExisting(boolean check) {
- checkExisting = check;
- }
-
void setCompressionLevel(int compression) {
this.compression = compression;
}
@@ -130,8 +117,9 @@ public class DfsInserter extends ObjectInserter {
if (objectMap != null && objectMap.contains(id))
return id;
// Ignore unreachable (garbage) objects here.
- if (checkExisting && db.has(id, true))
+ if (db.has(id, true)) {
return id;
+ }
long offset = beginObject(type, len);
packOut.compress.write(data, off, len);
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 efd666ff27..1a873d1204 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
@@ -52,16 +52,6 @@ public abstract class DfsObjDatabase extends ObjectDatabase {
boolean dirty() {
return true;
}
-
- @Override
- void clearDirty() {
- // Always dirty.
- }
-
- @Override
- public void markDirty() {
- // Always dirty.
- }
};
/**
@@ -534,7 +524,7 @@ public abstract class DfsObjDatabase extends ObjectDatabase {
DfsPackFile[] packs = new DfsPackFile[1 + o.packs.length];
packs[0] = newPack;
System.arraycopy(o.packs, 0, packs, 1, o.packs.length);
- n = new PackListImpl(packs, o.reftables);
+ n = new PackList(packs, o.reftables);
} while (!packList.compareAndSet(o, n));
}
@@ -559,7 +549,7 @@ public abstract class DfsObjDatabase extends ObjectDatabase {
}
}
tables.add(new DfsReftable(add));
- n = new PackListImpl(o.packs, tables.toArray(new DfsReftable[0]));
+ n = new PackList(o.packs, tables.toArray(new DfsReftable[0]));
} while (!packList.compareAndSet(o, n));
}
@@ -613,13 +603,12 @@ public abstract class DfsObjDatabase extends ObjectDatabase {
}
if (newPacks.isEmpty() && newReftables.isEmpty())
- return new PackListImpl(NO_PACKS.packs, NO_PACKS.reftables);
+ return new PackList(NO_PACKS.packs, NO_PACKS.reftables);
if (!foundNew) {
- old.clearDirty();
return old;
}
Collections.sort(newReftables, reftableComparator());
- return new PackListImpl(
+ return new PackList(
newPacks.toArray(new DfsPackFile[0]),
newReftables.toArray(new DfsReftable[0]));
}
@@ -685,7 +674,7 @@ public abstract class DfsObjDatabase extends ObjectDatabase {
}
/** Snapshot of packs scanned in a single pass. */
- public abstract static class PackList {
+ public static class PackList {
/** All known packs, sorted. */
public final DfsPackFile[] packs;
@@ -715,39 +704,8 @@ public abstract class DfsObjDatabase extends ObjectDatabase {
return lastModified;
}
- abstract boolean dirty();
- abstract void clearDirty();
-
- /**
- * Mark pack list as dirty.
- * <p>
- * Used when the caller knows that new data might have been written to the
- * repository that could invalidate open readers depending on this pack list,
- * for example if refs are newly scanned.
- */
- public abstract void markDirty();
- }
-
- private static final class PackListImpl extends PackList {
- private volatile boolean dirty;
-
- PackListImpl(DfsPackFile[] packs, DfsReftable[] reftables) {
- super(packs, reftables);
- }
-
- @Override
boolean dirty() {
- return dirty;
- }
-
- @Override
- void clearDirty() {
- dirty = false;
- }
-
- @Override
- public void markDirty() {
- dirty = true;
+ return false;
}
}
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 f9c01b9d6e..6339b0326a 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
@@ -405,7 +405,7 @@ public class DfsPackCompactor {
pw.addObject(obj);
obj.add(added);
- src.representation(rep, id.offset, ctx, rev);
+ src.fillRepresentation(rep, id.offset, ctx, rev);
if (rep.getFormat() != PACK_DELTA)
continue;
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 48ed47a77c..05b63eaca1 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
@@ -27,6 +27,9 @@ import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -49,6 +52,7 @@ import org.eclipse.jgit.internal.storage.file.PackObjectSizeIndexLoader;
import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
import org.eclipse.jgit.internal.storage.file.PackReverseIndexFactory;
import org.eclipse.jgit.internal.storage.pack.BinaryDelta;
+import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
import org.eclipse.jgit.internal.storage.pack.StoredObjectRepresentation;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
@@ -59,6 +63,7 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.util.BlockList;
import org.eclipse.jgit.util.LongList;
/**
@@ -71,6 +76,10 @@ public final class DfsPackFile extends BlockBasedFile {
private static final long REF_POSITION = 0;
+ private static final Comparator<DfsObjectToPack> OFFSET_SORT = (
+ DfsObjectToPack a,
+ DfsObjectToPack b) -> Long.signum(a.getOffset() - b.getOffset());
+
/**
* Loader for the default file-based {@link PackBitmapIndex} implementation.
*/
@@ -139,11 +148,15 @@ public final class DfsPackFile extends BlockBasedFile {
*
* @param ctx
* reader to find the raw bytes
+ * @param idx
+ * primary index for this reverse index (probably loaded
+ * via #index(DfsReader))
* @return the reverse index of the pack
* @throws IOException
* a problem finding/parsing the reverse index
*/
- PackReverseIndex reverseIndex(DfsReader ctx) throws IOException;
+ PackReverseIndex reverseIndex(DfsReader ctx, PackIndex idx)
+ throws IOException;
}
/**
@@ -364,7 +377,7 @@ public final class DfsPackFile extends BlockBasedFile {
return reverseIndex;
}
- reverseIndex = indexFactory.getPackIndexes().reverseIndex(ctx);
+ reverseIndex = indexFactory.getPackIndexes().reverseIndex(ctx, idx(ctx));
if (reverseIndex == null) {
throw new IOException(
"Couldn't get a reference to the reverse index"); //$NON-NLS-1$
@@ -429,6 +442,10 @@ public final class DfsPackFile extends BlockBasedFile {
return 0 < offset && !isCorrupt(offset);
}
+ int findIdxPosition(DfsReader ctx, AnyObjectId id) throws IOException {
+ return idx(ctx).findPosition(id);
+ }
+
/**
* Get an object from this pack.
*
@@ -451,23 +468,43 @@ public final class DfsPackFile extends BlockBasedFile {
return idx(ctx).findOffset(id);
}
- void resolve(DfsReader ctx, Set<ObjectId> matches, AbbreviatedObjectId id,
- int matchLimit) throws IOException {
- idx(ctx).resolve(matches, id, matchLimit);
- }
-
/**
- * Obtain the total number of objects available in this pack. This method
- * relies on pack index, giving number of effectively available objects.
+ * Return objects in the list available in this pack, sorted in (pack,
+ * offset) order.
*
* @param ctx
- * current reader for the calling thread.
- * @return number of objects in index of this pack, likewise in this pack
+ * a reader
+ * @param objects
+ * objects we are looking for
+ * @param skipFound
+ * ignore objects already found.
+ * @return list of objects with pack and offset set.
* @throws IOException
- * the index file cannot be loaded into memory.
+ * an error occurred
*/
- long getObjectCount(DfsReader ctx) throws IOException {
- return idx(ctx).getObjectCount();
+ List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
+ Iterable<ObjectToPack> objects, boolean skipFound)
+ throws IOException {
+ List<DfsObjectToPack> tmp = new BlockList<>();
+ for (ObjectToPack obj : objects) {
+ DfsObjectToPack otp = (DfsObjectToPack) obj;
+ if (skipFound && otp.isFound()) {
+ continue;
+ }
+ long p = idx(ctx).findOffset(otp);
+ if (p <= 0 || isCorrupt(p)) {
+ continue;
+ }
+ otp.setOffset(p);
+ tmp.add(otp);
+ }
+ Collections.sort(tmp, OFFSET_SORT);
+ return tmp;
+ }
+
+ void resolve(DfsReader ctx, Set<ObjectId> matches, AbbreviatedObjectId id,
+ int matchLimit) throws IOException {
+ idx(ctx).resolve(matches, id, matchLimit);
}
private byte[] decompress(long position, int sz, DfsReader ctx)
@@ -1131,31 +1168,29 @@ public final class DfsPackFile extends BlockBasedFile {
/**
* Return the size of the object from the object-size index. The object
* should be a blob. Any other type is not indexed and returns -1.
- *
- * Caller MUST be sure that the object is in the pack (e.g. with
- * {@link #hasObject(DfsReader, AnyObjectId)}) and the pack has object size
- * index (e.g. with {@link #hasObjectSizeIndex(DfsReader)}) before asking
- * the indexed size.
+ * <p>
+ * Caller MUST pass a valid index position, as returned by
+ * {@link #findIdxPosition(DfsReader, AnyObjectId)} and verify the pack has
+ * object size index (e.g. with {@link #hasObjectSizeIndex(DfsReader)})
+ * before asking the indexed size.
*
* @param ctx
* reader context to support reading from the backing store if
* the object size index is not already loaded in memory.
- * @param id
- * object id of an object in the pack
+ * @param idxPosition
+ * position in the primary index of the object we are looking
+ * for, as returned by findIdxPosition
* @return size of the object from the index. Negative if object is not in
* the index (below threshold or not a blob)
* @throws IOException
* could not read the object size index. IO problem or the pack
* doesn't have it.
*/
- long getIndexedObjectSize(DfsReader ctx, AnyObjectId id)
+ long getIndexedObjectSize(DfsReader ctx, int idxPosition)
throws IOException {
- int idxPosition = idx(ctx).findPosition(id);
if (idxPosition < 0) {
- throw new IllegalArgumentException(
- "Cannot get size from index since object is not in pack"); //$NON-NLS-1$
+ throw new IllegalArgumentException("Invalid index position"); //$NON-NLS-1$
}
-
PackObjectSizeIndex sizeIdx = getObjectSizeIndex(ctx);
if (sizeIdx == null) {
throw new IllegalStateException(
@@ -1165,12 +1200,47 @@ public final class DfsPackFile extends BlockBasedFile {
return sizeIdx.getSize(idxPosition);
}
- void representation(DfsObjectRepresentation r, final long pos,
+ /**
+ * 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).
+ *
+ * @param r
+ * represention object to carry data
+ * @param offset
+ * offset in this pack of the object
+ * @param ctx
+ * a reader
+ * @throws IOException
+ * an error reading the object from disk
+ */
+ void fillRepresentation(DfsObjectRepresentation r, long offset,
+ DfsReader ctx) throws IOException {
+ fillRepresentation(r, offset, ctx, getReverseIdx(ctx));
+ }
+
+ /**
+ * 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).
+ *
+ * @param r
+ * represention object to carry data
+ * @param offset
+ * offset in this pack of the object
+ * @param ctx
+ * a reader
+ * @param rev
+ * reverse index of this pack
+ * @throws IOException
+ * an error reading the object from disk
+ */
+ void fillRepresentation(DfsObjectRepresentation r, long offset,
DfsReader ctx, PackReverseIndex rev)
throws IOException {
- r.offset = pos;
+ r.offset = offset;
final byte[] ib = ctx.tempId;
- readFully(pos, ib, 0, 20, ctx);
+ readFully(offset, ib, 0, 20, ctx);
int c = ib[0] & 0xff;
int p = 1;
final int typeCode = (c >> 4) & 7;
@@ -1178,7 +1248,7 @@ public final class DfsPackFile extends BlockBasedFile {
c = ib[p++] & 0xff;
}
- long len = rev.findNextOffset(pos, length - 20) - pos;
+ long len = rev.findNextOffset(offset, length - 20) - offset;
switch (typeCode) {
case Constants.OBJ_COMMIT:
case Constants.OBJ_TREE:
@@ -1199,13 +1269,13 @@ public final class DfsPackFile extends BlockBasedFile {
ofs += (c & 127);
}
r.format = StoredObjectRepresentation.PACK_DELTA;
- r.baseId = rev.findObject(pos - ofs);
+ r.baseId = rev.findObject(offset - ofs);
r.length = len - p;
return;
}
case Constants.OBJ_REF_DELTA: {
- readFully(pos + p, ib, 0, 20, ctx);
+ readFully(offset + p, ib, 0, 20, ctx);
r.format = StoredObjectRepresentation.PACK_DELTA;
r.baseId = ObjectId.fromRaw(ib);
r.length = len - p - 20;
@@ -1540,8 +1610,8 @@ public final class DfsPackFile extends BlockBasedFile {
}
@Override
- public PackReverseIndex reverseIndex(DfsReader ctx) throws IOException {
- PackIndex idx = index(ctx);
+ public PackReverseIndex reverseIndex(DfsReader ctx, PackIndex idx)
+ throws IOException {
DfsStreamKey revKey = desc.getStreamKey(REVERSE_INDEX);
// Keep the value parsed in the loader, in case the Ref<> is
// nullified in ClockBlockCacheTable#reserveSpace
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 62f6753e5d..f50cd597e5 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
@@ -38,8 +38,6 @@ import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
import org.eclipse.jgit.internal.storage.dfs.DfsReader.PackLoadListener.DfsBlockData;
import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl;
import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
-import org.eclipse.jgit.internal.storage.file.PackIndex;
-import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
import org.eclipse.jgit.internal.storage.pack.CachedPack;
import org.eclipse.jgit.internal.storage.pack.ObjectReuseAsIs;
import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
@@ -58,7 +56,6 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.util.BlockList;
/**
* Reader to access repository content through.
@@ -190,31 +187,44 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
@Override
public boolean has(AnyObjectId objectId) throws IOException {
+ return findPack(objectId) >= 0;
+ }
+
+ private int findPack(AnyObjectId objectId) throws IOException {
if (last != null
- && !skipGarbagePack(last)
- && last.hasObject(this, objectId))
- return true;
+ && !skipGarbagePack(last)) {
+ int idxPos = last.findIdxPosition(this, objectId);
+ if (idxPos >= 0) {
+ return idxPos;
+ }
+ }
+
PackList packList = db.getPackList();
- if (hasImpl(packList, objectId)) {
- return true;
+ int idxPos = findInPackList(packList, objectId);
+ if (idxPos >= 0) {
+ return idxPos;
} else if (packList.dirty()) {
stats.scanPacks++;
- return hasImpl(db.scanPacks(packList), objectId);
+ idxPos = findInPackList(db.scanPacks(packList), objectId);
+ return idxPos;
}
- return false;
+ return -1;
}
- private boolean hasImpl(PackList packList, AnyObjectId objectId)
+ // Leave "last" pointing to the pack and return the idx position of the
+ // object (-1 if not found)
+ private int findInPackList(PackList packList, AnyObjectId objectId)
throws IOException {
for (DfsPackFile pack : packList.packs) {
if (pack == last || skipGarbagePack(pack))
continue;
- if (pack.hasObject(this, objectId)) {
+ int idxPos = pack.findIdxPosition(this, objectId);
+ if (idxPos >= 0) {
last = pack;
- return true;
+ return idxPos;
}
}
- return false;
+ return -1;
}
@Override
@@ -502,8 +512,8 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
public long getObjectSize(AnyObjectId objectId, int typeHint)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
- DfsPackFile pack = findPackWithObject(objectId);
- if (pack == null) {
+ int idxPos = findPack(objectId);
+ if (idxPos < 0) {
if (typeHint == OBJ_ANY) {
throw new MissingObjectException(objectId.copy(),
JGitText.get().unknownObjectType2);
@@ -511,16 +521,15 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
throw new MissingObjectException(objectId.copy(), typeHint);
}
- if (typeHint != Constants.OBJ_BLOB || !safeHasObjectSizeIndex(pack)) {
- return pack.getObjectSize(this, objectId);
+ if (typeHint != Constants.OBJ_BLOB || !safeHasObjectSizeIndex(last)) {
+ return last.getObjectSize(this, objectId);
}
- Optional<Long> maybeSz = safeGetIndexedObjectSize(pack, objectId);
- long sz = maybeSz.orElse(-1L);
+ long sz = safeGetIndexedObjectSize(last, idxPos);
if (sz >= 0) {
return sz;
}
- return pack.getObjectSize(this, objectId);
+ return last.getObjectSize(this, objectId);
}
@@ -528,8 +537,8 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
public boolean isNotLargerThan(AnyObjectId objectId, int typeHint,
long limit) throws MissingObjectException,
IncorrectObjectTypeException, IOException {
- DfsPackFile pack = findPackWithObject(objectId);
- if (pack == null) {
+ int idxPos = findPack(objectId);
+ if (idxPos < 0) {
if (typeHint == OBJ_ANY) {
throw new MissingObjectException(objectId.copy(),
JGitText.get().unknownObjectType2);
@@ -538,28 +547,22 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
}
stats.isNotLargerThanCallCount += 1;
- if (typeHint != Constants.OBJ_BLOB || !safeHasObjectSizeIndex(pack)) {
- return pack.getObjectSize(this, objectId) <= limit;
+ if (typeHint != Constants.OBJ_BLOB || !safeHasObjectSizeIndex(last)) {
+ return last.getObjectSize(this, objectId) <= limit;
}
- Optional<Long> maybeSz = safeGetIndexedObjectSize(pack, objectId);
- if (maybeSz.isEmpty()) {
- // Exception in object size index
- return pack.getObjectSize(this, objectId) <= limit;
- }
-
- long sz = maybeSz.get();
+ long sz = safeGetIndexedObjectSize(last, idxPos);
if (sz >= 0) {
return sz <= limit;
}
- if (isLimitInsideIndexThreshold(pack, limit)) {
+ if (isLimitInsideIndexThreshold(last, limit)) {
// With threshold T, not-found means object < T
// If limit L > T, then object < T < L
return true;
}
- return pack.getObjectSize(this, objectId) <= limit;
+ return last.getObjectSize(this, objectId) <= limit;
}
private boolean safeHasObjectSizeIndex(DfsPackFile pack) {
@@ -570,21 +573,22 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
}
}
- private Optional<Long> safeGetIndexedObjectSize(DfsPackFile pack,
- AnyObjectId objectId) {
+ private long safeGetIndexedObjectSize(DfsPackFile pack,
+ int idxPos) {
long sz;
try {
- sz = pack.getIndexedObjectSize(this, objectId);
+ sz = pack.getIndexedObjectSize(this, idxPos);
} catch (IOException e) {
- // Do not count the exception as an index miss
- return Optional.empty();
+ // If there is any error in the index, we should have seen it
+ // on hasObjectSizeIndex.
+ throw new IllegalStateException(e);
}
if (sz < 0) {
stats.objectSizeIndexMiss += 1;
} else {
stats.objectSizeIndexHit += 1;
}
- return Optional.of(sz);
+ return sz;
}
private boolean isLimitInsideIndexThreshold(DfsPackFile pack, long limit) {
@@ -595,34 +599,11 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
}
}
- private DfsPackFile findPackWithObject(AnyObjectId objectId)
- throws IOException {
- if (last != null && !skipGarbagePack(last)
- && last.hasObject(this, objectId)) {
- return last;
- }
- PackList packList = db.getPackList();
- // hasImpl doesn't check "last", but leaves "last" pointing to the pack
- // with the object
- if (hasImpl(packList, objectId)) {
- return last;
- } else if (packList.dirty()) {
- if (hasImpl(db.getPackList(), objectId)) {
- return last;
- }
- }
- return null;
- }
-
@Override
public DfsObjectToPack newObjectToPack(AnyObjectId objectId, int type) {
return new DfsObjectToPack(objectId, type);
}
- private static final Comparator<DfsObjectToPack> OFFSET_SORT = (
- DfsObjectToPack a,
- DfsObjectToPack b) -> Long.signum(a.getOffset() - b.getOffset());
-
@Override
public void selectObjectRepresentation(PackWriter packer,
ProgressMonitor monitor, Iterable<ObjectToPack> objects)
@@ -642,16 +623,15 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
ProgressMonitor monitor, Iterable<ObjectToPack> objects,
List<DfsPackFile> packs, boolean skipFound) throws IOException {
for (DfsPackFile pack : packs) {
- List<DfsObjectToPack> tmp = findAllFromPack(pack, objects, skipFound);
- if (tmp.isEmpty())
+ List<DfsObjectToPack> inPack = pack.findAllFromPack(this, objects, skipFound);
+ if (inPack.isEmpty())
continue;
- Collections.sort(tmp, OFFSET_SORT);
- PackReverseIndex rev = pack.getReverseIdx(this);
DfsObjectRepresentation rep = new DfsObjectRepresentation(pack);
- for (DfsObjectToPack otp : tmp) {
- pack.representation(rep, otp.getOffset(), this, rev);
+ for (DfsObjectToPack otp : inPack) {
+ // Populate rep.{offset,length} from the pack
+ pack.fillRepresentation(rep, otp.getOffset(), this);
otp.setOffset(0);
- packer.select(otp, rep);
+ packer.select(otp, rep); // Set otp.offset from rep
if (!otp.isFound()) {
otp.setFound();
monitor.update(1);
@@ -698,24 +678,7 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
return false;
}
- private List<DfsObjectToPack> findAllFromPack(DfsPackFile pack,
- Iterable<ObjectToPack> objects, boolean skipFound)
- throws IOException {
- List<DfsObjectToPack> tmp = new BlockList<>();
- PackIndex idx = pack.getPackIndex(this);
- for (ObjectToPack obj : objects) {
- DfsObjectToPack otp = (DfsObjectToPack) obj;
- if (skipFound && otp.isFound()) {
- continue;
- }
- long p = idx.findOffset(otp);
- if (0 < p && !pack.isCorrupt(p)) {
- otp.setOffset(p);
- tmp.add(otp);
- }
- }
- return tmp;
- }
+
@Override
public void copyObjectAsIs(PackOutputStream out, ObjectToPack otp,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
index 3ba74b26fc..2751cd2969 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java
@@ -28,6 +28,7 @@ import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.util.RefList;
@@ -177,6 +178,11 @@ public class DfsReftableDatabase extends DfsRefDatabase {
}
@Override
+ public ReflogReader getReflogReader(Ref ref) throws IOException {
+ return reftableDatabase.getReflogReader(ref.getName());
+ }
+
+ @Override
public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
if (!getReftableConfig().isIndexObjects()) {
return super.getTipsWithSha1(id);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
index 25b7583b95..559d5a4339 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java
@@ -16,6 +16,7 @@ import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
import java.io.File;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -37,6 +38,7 @@ import org.eclipse.jgit.internal.storage.reftable.ReftableBatchRefUpdate;
import org.eclipse.jgit.internal.storage.reftable.ReftableDatabase;
import org.eclipse.jgit.internal.storage.reftable.ReftableWriter;
import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
@@ -70,14 +72,14 @@ public class FileReftableDatabase extends RefDatabase {
private final FileReftableStack reftableStack;
- FileReftableDatabase(FileRepository repo) throws IOException {
- this(repo, new File(new File(repo.getCommonDirectory(), Constants.REFTABLE),
- Constants.TABLES_LIST));
- }
+ private volatile boolean autoRefresh;
- FileReftableDatabase(FileRepository repo, File refstackName) throws IOException {
+ FileReftableDatabase(FileRepository repo) throws IOException {
this.fileRepository = repo;
- this.reftableStack = new FileReftableStack(refstackName,
+ this.autoRefresh = repo.getConfig().getBoolean(
+ ConfigConstants.CONFIG_REFTABLE_SECTION,
+ ConfigConstants.CONFIG_KEY_AUTOREFRESH, false);
+ this.reftableStack = new FileReftableStack(
new File(fileRepository.getCommonDirectory(), Constants.REFTABLE),
() -> fileRepository.fireEvent(new RefsChangedEvent()),
() -> fileRepository.getConfig());
@@ -90,7 +92,13 @@ public class FileReftableDatabase extends RefDatabase {
};
}
- ReflogReader getReflogReader(String refname) throws IOException {
+ @Override
+ public ReflogReader getReflogReader(Ref ref) throws IOException {
+ return reftableDatabase.getReflogReader(ref.getName());
+ }
+
+ @Override
+ public ReflogReader getReflogReader(String refname) throws IOException {
return reftableDatabase.getReflogReader(refname);
}
@@ -177,6 +185,7 @@ public class FileReftableDatabase extends RefDatabase {
@Override
public Ref exactRef(String name) throws IOException {
+ autoRefresh();
return reftableDatabase.exactRef(name);
}
@@ -187,6 +196,7 @@ public class FileReftableDatabase extends RefDatabase {
@Override
public Map<String, Ref> getRefs(String prefix) throws IOException {
+ autoRefresh();
List<Ref> refs = reftableDatabase.getRefsByPrefix(prefix);
RefList.Builder<Ref> builder = new RefList.Builder<>(refs.size());
for (Ref r : refs) {
@@ -199,6 +209,7 @@ public class FileReftableDatabase extends RefDatabase {
@Override
public List<Ref> getRefsByPrefixWithExclusions(String include, Set<String> excludes)
throws IOException {
+ autoRefresh();
return reftableDatabase.getRefsByPrefixWithExclusions(include, excludes);
}
@@ -217,6 +228,50 @@ public class FileReftableDatabase extends RefDatabase {
}
+ /**
+ * Whether to auto-refresh the reftable stack if it is out of date.
+ *
+ * @param autoRefresh
+ * whether to auto-refresh the reftable stack if it is out of
+ * date.
+ */
+ public void setAutoRefresh(boolean autoRefresh) {
+ this.autoRefresh = autoRefresh;
+ }
+
+ /**
+ * Whether the reftable stack is auto-refreshed if it is out of date.
+ *
+ * @return whether the reftable stack is auto-refreshed if it is out of
+ * date.
+ */
+ public boolean isAutoRefresh() {
+ return autoRefresh;
+ }
+
+ private void autoRefresh() {
+ if (autoRefresh) {
+ refresh();
+ }
+ }
+
+ /**
+ * Check if the reftable stack is up to date, and if not, reload it.
+ * <p>
+ * {@inheritDoc}
+ */
+ @Override
+ public void refresh() {
+ try {
+ if (!reftableStack.isUpToDate()) {
+ reftableDatabase.clearCache();
+ reftableStack.reload();
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
private Ref doPeel(Ref leaf) throws IOException {
try (RevWalk rw = new RevWalk(fileRepository)) {
RevObject obj = rw.parseAny(leaf.getObjectId());
@@ -557,9 +612,10 @@ public class FileReftableDatabase extends RefDatabase {
boolean writeLogs) throws IOException {
int size = 0;
List<Ref> refs = repo.getRefDatabase().getRefs();
+ RefDatabase refDb = repo.getRefDatabase();
if (writeLogs) {
for (Ref r : refs) {
- ReflogReader rlr = repo.getReflogReader(r.getName());
+ ReflogReader rlr = refDb.getReflogReader(r);
if (rlr != null) {
size = Math.max(rlr.getReverseEntries().size(), size);
}
@@ -582,10 +638,7 @@ public class FileReftableDatabase extends RefDatabase {
if (writeLogs) {
for (Ref r : refs) {
long idx = size;
- ReflogReader reader = repo.getReflogReader(r.getName());
- if (reader == null) {
- continue;
- }
+ ReflogReader reader = refDb.getReflogReader(r);
for (ReflogEntry e : reader.getReverseEntries()) {
w.writeLog(r.getName(), idx, e.getWho(), e.getOldId(),
e.getNewId(), e.getComment());
@@ -625,32 +678,20 @@ public class FileReftableDatabase extends RefDatabase {
* the repository
* @param writeLogs
* whether to write reflogs
- * @return a reftable based RefDB from an existing repository.
* @throws IOException
* on IO error
*/
- public static FileReftableDatabase convertFrom(FileRepository repo,
- boolean writeLogs) throws IOException {
- FileReftableDatabase newDb = null;
- File reftableList = null;
- try {
- File reftableDir = new File(repo.getCommonDirectory(),
- Constants.REFTABLE);
- reftableList = new File(reftableDir, Constants.TABLES_LIST);
- if (!reftableDir.isDirectory()) {
- reftableDir.mkdir();
- }
+ public static void convertFrom(FileRepository repo, boolean writeLogs)
+ throws IOException {
+ File reftableDir = new File(repo.getCommonDirectory(),
+ Constants.REFTABLE);
+ if (!reftableDir.isDirectory()) {
+ reftableDir.mkdir();
+ }
- try (FileReftableStack stack = new FileReftableStack(reftableList,
- reftableDir, null, () -> repo.getConfig())) {
- stack.addReftable(rw -> writeConvertTable(repo, rw, writeLogs));
- }
- reftableList = null;
- } finally {
- if (reftableList != null) {
- reftableList.delete();
- }
+ try (FileReftableStack stack = new FileReftableStack(reftableDir, null,
+ () -> repo.getConfig())) {
+ stack.addReftable(rw -> writeConvertTable(repo, rw, writeLogs));
}
- return newDb;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java
index 0f5ff0f9f7..6658575fc5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableStack.java
@@ -18,8 +18,10 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.StandardCopyOption;
import java.security.SecureRandom;
import java.util.ArrayList;
@@ -27,6 +29,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -39,6 +42,9 @@ import org.eclipse.jgit.internal.storage.reftable.ReftableConfig;
import org.eclipse.jgit.internal.storage.reftable.ReftableReader;
import org.eclipse.jgit.internal.storage.reftable.ReftableWriter;
import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig;
+import org.eclipse.jgit.lib.CoreConfig.TrustStat;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.SystemReader;
@@ -59,9 +65,12 @@ public class FileReftableStack implements AutoCloseable {
private List<StackEntry> stack;
+ private AtomicReference<FileSnapshot> snapshot = new AtomicReference<>(
+ FileSnapshot.DIRTY);
+
private long lastNextUpdateIndex;
- private final File stackPath;
+ private final File tablesListFile;
private final File reftableDir;
@@ -98,11 +107,11 @@ public class FileReftableStack implements AutoCloseable {
private final CompactionStats stats;
+ private final TrustStat trustTablesListStat;
+
/**
* Creates a stack corresponding to the list of reftables in the argument
*
- * @param stackPath
- * the filename for the stack.
* @param reftableDir
* the dir holding the tables.
* @param onChange
@@ -112,10 +121,10 @@ public class FileReftableStack implements AutoCloseable {
* @throws IOException
* on I/O problems
*/
- public FileReftableStack(File stackPath, File reftableDir,
+ public FileReftableStack(File reftableDir,
@Nullable Runnable onChange, Supplier<Config> configSupplier)
throws IOException {
- this.stackPath = stackPath;
+ this.tablesListFile = new File(reftableDir, Constants.TABLES_LIST);
this.reftableDir = reftableDir;
this.stack = new ArrayList<>();
this.configSupplier = configSupplier;
@@ -126,6 +135,8 @@ public class FileReftableStack implements AutoCloseable {
reload();
stats = new CompactionStats();
+ trustTablesListStat = configSupplier.get().get(CoreConfig.KEY)
+ .getTrustTablesListStat();
}
CompactionStats getStats() {
@@ -232,7 +243,7 @@ public class FileReftableStack implements AutoCloseable {
}
if (!success) {
- throw new LockFailedException(stackPath);
+ throw new LockFailedException(tablesListFile);
}
mergedReftable = new MergedReftable(stack.stream()
@@ -272,18 +283,21 @@ public class FileReftableStack implements AutoCloseable {
}
private List<String> readTableNames() throws IOException {
+ FileSnapshot old;
List<String> names = new ArrayList<>(stack.size() + 1);
-
+ old = snapshot.get();
try (BufferedReader br = new BufferedReader(
- new InputStreamReader(new FileInputStream(stackPath), UTF_8))) {
+ new InputStreamReader(new FileInputStream(tablesListFile), UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
if (!line.isEmpty()) {
names.add(line);
}
}
+ snapshot.compareAndSet(old, FileSnapshot.save(tablesListFile));
} catch (FileNotFoundException e) {
// file isn't there: empty repository.
+ snapshot.compareAndSet(old, FileSnapshot.MISSING_FILE);
}
return names;
}
@@ -294,9 +308,29 @@ public class FileReftableStack implements AutoCloseable {
* on IO problem
*/
boolean isUpToDate() throws IOException {
- // We could use FileSnapshot to avoid reading the file, but the file is
- // small so it's probably a minor optimization.
try {
+ switch (trustTablesListStat) {
+ case NEVER:
+ break;
+ case AFTER_OPEN:
+ try (InputStream stream = Files
+ .newInputStream(reftableDir.toPath())) {
+ // open the refs/reftable/ directory to refresh attributes
+ // of reftable files and the tables.list file listing their
+ // names (on some NFS clients)
+ } catch (FileNotFoundException | NoSuchFileException e) {
+ // ignore
+ }
+ //$FALL-THROUGH$
+ case ALWAYS:
+ if (!snapshot.get().isModified(tablesListFile)) {
+ return true;
+ }
+ break;
+ case INHERIT:
+ // only used in CoreConfig internally
+ throw new IllegalStateException();
+ }
List<String> names = readTableNames();
if (names.size() != stack.size()) {
return false;
@@ -353,7 +387,7 @@ public class FileReftableStack implements AutoCloseable {
*/
@SuppressWarnings("nls")
public boolean addReftable(Writer w) throws IOException {
- LockFile lock = new LockFile(stackPath);
+ LockFile lock = new LockFile(tablesListFile);
try {
if (!lock.lockForAppend()) {
return false;
@@ -364,8 +398,7 @@ public class FileReftableStack implements AutoCloseable {
String fn = filename(nextUpdateIndex(), nextUpdateIndex());
- File tmpTable = File.createTempFile(fn + "_", ".ref",
- stackPath.getParentFile());
+ File tmpTable = File.createTempFile(fn + "_", ".ref", reftableDir);
ReftableWriter.Stats s;
try (FileOutputStream fos = new FileOutputStream(tmpTable)) {
@@ -419,7 +452,7 @@ public class FileReftableStack implements AutoCloseable {
String fn = filename(first, last);
File tmpTable = File.createTempFile(fn + "_", ".ref", //$NON-NLS-1$//$NON-NLS-2$
- stackPath.getParentFile());
+ reftableDir);
try (FileOutputStream fos = new FileOutputStream(tmpTable)) {
ReftableCompactor c = new ReftableCompactor(fos)
.setConfig(reftableConfig())
@@ -463,7 +496,7 @@ public class FileReftableStack implements AutoCloseable {
if (first >= last) {
return true;
}
- LockFile lock = new LockFile(stackPath);
+ LockFile lock = new LockFile(tablesListFile);
File tmpTable = null;
List<LockFile> subtableLocks = new ArrayList<>();
@@ -492,7 +525,7 @@ public class FileReftableStack implements AutoCloseable {
tmpTable = compactLocked(first, last);
- lock = new LockFile(stackPath);
+ lock = new LockFile(tablesListFile);
if (!lock.lock()) {
return false;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
index c5c36565d9..bcf9f1efdf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java
@@ -31,7 +31,6 @@ import java.util.Locale;
import java.util.Objects;
import java.util.Set;
-import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
@@ -543,29 +542,6 @@ public class FileRepository extends Repository {
}
@Override
- public ReflogReader getReflogReader(String refName) throws IOException {
- if (refs instanceof FileReftableDatabase) {
- // Cannot use findRef: reftable stores log data for deleted or renamed
- // branches.
- return ((FileReftableDatabase)refs).getReflogReader(refName);
- }
-
- // TODO: use exactRef here, which offers more predictable and therefore preferable
- // behavior.
- Ref ref = findRef(refName);
- if (ref == null) {
- return null;
- }
- return new ReflogReaderImpl(this, ref.getName());
- }
-
- @Override
- public @NonNull ReflogReader getReflogReader(@NonNull Ref ref)
- throws IOException {
- return new ReflogReaderImpl(this, ref.getName());
- }
-
- @Override
public AttributesNodeProvider createAttributesNodeProvider() {
return new AttributesNodeProviderImpl(this);
}
@@ -697,8 +673,8 @@ public class FileRepository extends Repository {
}
if (writeLogs) {
- List<ReflogEntry> logs = oldDb.getReflogReader(r.getName())
- .getReverseEntries();
+ ReflogReader reflogReader = oldDb.getReflogReader(r);
+ List<ReflogEntry> logs = reflogReader.getReverseEntries();
Collections.reverse(logs);
for (ReflogEntry e : logs) {
logWriter.log(r.getName(), e);
@@ -743,6 +719,8 @@ public class FileRepository extends Repository {
}
repoConfig.unset(ConfigConstants.CONFIG_EXTENSIONS_SECTION, null,
ConfigConstants.CONFIG_KEY_REF_STORAGE);
+ repoConfig.setLong(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 0);
repoConfig.save();
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
index 7f3369364b..c08a92e5a7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
@@ -102,7 +102,7 @@ import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FS.LockToken;
import org.eclipse.jgit.util.FileUtils;
-import org.eclipse.jgit.util.GitDateParser;
+import org.eclipse.jgit.util.GitTimeParser;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
@@ -160,11 +160,11 @@ public class GC {
private long expireAgeMillis = -1;
- private Date expire;
+ private Instant expire;
private long packExpireAgeMillis = -1;
- private Date packExpire;
+ private Instant packExpire;
private Boolean packKeptObjects;
@@ -183,7 +183,7 @@ public class GC {
* prune() to inspect only those reflog entries which have been added since
* last repack().
*/
- private long lastRepackTime;
+ private Instant lastRepackTime;
/**
* Whether gc should do automatic housekeeping
@@ -698,16 +698,18 @@ public class GC {
if (expire == null && expireAgeMillis == -1) {
String pruneExpireStr = getPruneExpireStr();
- if (pruneExpireStr == null)
+ if (pruneExpireStr == null) {
pruneExpireStr = PRUNE_EXPIRE_DEFAULT;
- expire = GitDateParser.parse(pruneExpireStr, null, SystemReader
- .getInstance().getLocale());
+ }
+ expire = GitTimeParser.parseInstant(pruneExpireStr);
expireAgeMillis = -1;
}
- if (expire != null)
- expireDate = expire.getTime();
- if (expireAgeMillis != -1)
+ if (expire != null) {
+ expireDate = expire.toEpochMilli();
+ }
+ if (expireAgeMillis != -1) {
expireDate = System.currentTimeMillis() - expireAgeMillis;
+ }
return expireDate;
}
@@ -724,16 +726,18 @@ public class GC {
String prunePackExpireStr = repo.getConfig().getString(
ConfigConstants.CONFIG_GC_SECTION, null,
ConfigConstants.CONFIG_KEY_PRUNEPACKEXPIRE);
- if (prunePackExpireStr == null)
+ if (prunePackExpireStr == null) {
prunePackExpireStr = PRUNE_PACK_EXPIRE_DEFAULT;
- packExpire = GitDateParser.parse(prunePackExpireStr, null,
- SystemReader.getInstance().getLocale());
+ }
+ packExpire = GitTimeParser.parseInstant(prunePackExpireStr);
packExpireAgeMillis = -1;
}
- if (packExpire != null)
- packExpireDate = packExpire.getTime();
- if (packExpireAgeMillis != -1)
+ if (packExpire != null) {
+ packExpireDate = packExpire.toEpochMilli();
+ }
+ if (packExpireAgeMillis != -1) {
packExpireDate = System.currentTimeMillis() - packExpireAgeMillis;
+ }
return packExpireDate;
}
@@ -802,7 +806,7 @@ public class GC {
public Collection<Pack> repack() throws IOException {
Collection<Pack> toBeDeleted = repo.getObjectDatabase().getPacks();
- long time = System.currentTimeMillis();
+ Instant time = SystemReader.getInstance().now();
Collection<Ref> refsBefore = getAllRefs();
Set<ObjectId> allHeadsAndTags = new HashSet<>();
@@ -818,7 +822,7 @@ public class GC {
for (Ref ref : refsBefore) {
checkCancelled();
- nonHeads.addAll(listRefLogObjects(ref, 0));
+ nonHeads.addAll(listRefLogObjects(ref, Instant.EPOCH));
if (ref.isSymbolic() || ref.getObjectId() == null) {
continue;
}
@@ -1148,21 +1152,23 @@ public class GC {
* @param ref
* the ref which log should be inspected
* @param minTime
- * only reflog entries not older then this time are processed
+ * only reflog entries equal or younger than this time are
+ * processed
* @return the {@link ObjectId}s contained in the reflog
* @throws IOException
* if an IO error occurred
*/
- private Set<ObjectId> listRefLogObjects(Ref ref, long minTime) throws IOException {
- ReflogReader reflogReader = repo.getReflogReader(ref);
+ private Set<ObjectId> listRefLogObjects(Ref ref, Instant minTime) throws IOException {
+ ReflogReader reflogReader = repo.getRefDatabase().getReflogReader(ref);
List<ReflogEntry> rlEntries = reflogReader
.getReverseEntries();
if (rlEntries == null || rlEntries.isEmpty())
return Collections.emptySet();
Set<ObjectId> ret = new HashSet<>();
for (ReflogEntry e : rlEntries) {
- if (e.getWho().getWhen().getTime() < minTime)
+ if (e.getWho().getWhenAsInstant().isBefore(minTime)) {
break;
+ }
ObjectId newId = e.getNewId();
if (newId != null && !ObjectId.zeroId().equals(newId))
ret.add(newId);
@@ -1548,7 +1554,7 @@ public class GC {
public RepoStatistics getStatistics() throws IOException {
RepoStatistics ret = new RepoStatistics();
Collection<Pack> packs = repo.getObjectDatabase().getPacks();
- long latestBitmapTime = Long.MIN_VALUE;
+ long latestBitmapTime = 0L;
for (Pack p : packs) {
long packedObjects = p.getIndex().getObjectCount();
ret.numberOfPackedObjects += packedObjects;
@@ -1556,9 +1562,11 @@ public class GC {
ret.sizeOfPackedObjects += p.getPackFile().length();
if (p.getBitmapIndex() != null) {
ret.numberOfBitmaps += p.getBitmapIndex().getBitmapCount();
- latestBitmapTime = p.getFileSnapshot().lastModifiedInstant()
- .toEpochMilli();
- } else {
+ if (latestBitmapTime == 0L) {
+ latestBitmapTime = p.getFileSnapshot().lastModifiedInstant().toEpochMilli();
+ }
+ }
+ else if (latestBitmapTime == 0L) {
ret.numberOfPackFilesSinceBitmap++;
ret.numberOfObjectsSinceBitmap += packedObjects;
}
@@ -1655,12 +1663,31 @@ public class GC {
* candidate for pruning.
*
* @param expire
- * instant in time which defines object expiration
- * objects with modification time before this instant are expired
- * objects with modification time newer or equal to this instant
- * are not expired
+ * instant in time which defines object expiration objects with
+ * modification time before this instant are expired objects with
+ * modification time newer or equal to this instant are not
+ * expired
+ * @deprecated use {@link #setExpire(Instant)} instead
*/
+ @Deprecated(since = "7.2")
public void setExpire(Date expire) {
+ this.expire = expire.toInstant();
+ expireAgeMillis = -1;
+ }
+
+ /**
+ * During gc() or prune() each unreferenced, loose object which has been
+ * created or modified after or at <code>expire</code> will not be pruned.
+ * Only older objects may be pruned. If set to null then every object is a
+ * candidate for pruning.
+ *
+ * @param expire
+ * instant in time which defines object expiration objects with
+ * modification time before this instant are expired objects with
+ * modification time newer or equal to this instant are not
+ * expired
+ */
+ public void setExpire(Instant expire) {
this.expire = expire;
expireAgeMillis = -1;
}
@@ -1673,8 +1700,24 @@ public class GC {
*
* @param packExpire
* instant in time which defines packfile expiration
+ * @deprecated use {@link #setPackExpire(Instant)} instead
*/
+ @Deprecated(since = "7.2")
public void setPackExpire(Date packExpire) {
+ this.packExpire = packExpire.toInstant();
+ packExpireAgeMillis = -1;
+ }
+
+ /**
+ * During gc() or prune() packfiles which are created or modified after or
+ * at <code>packExpire</code> will not be deleted. Only older packfiles may
+ * be deleted. If set to null then every packfile is a candidate for
+ * deletion.
+ *
+ * @param packExpire
+ * instant in time which defines packfile expiration
+ */
+ public void setPackExpire(Instant packExpire) {
this.packExpire = packExpire;
packExpireAgeMillis = -1;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java
index 8647b3e664..862aaab0ee 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java
@@ -23,8 +23,7 @@ import java.time.Instant;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.util.FileUtils;
-import org.eclipse.jgit.util.GitDateParser;
-import org.eclipse.jgit.util.SystemReader;
+import org.eclipse.jgit.util.GitTimeParser;
/**
* This class manages the gc.log file for a {@link FileRepository}.
@@ -62,8 +61,7 @@ class GcLog {
if (logExpiryStr == null) {
logExpiryStr = LOG_EXPIRY_DEFAULT;
}
- gcLogExpire = GitDateParser.parse(logExpiryStr, null,
- SystemReader.getInstance().getLocale()).toInstant();
+ gcLogExpire = GitTimeParser.parseInstant(logExpiryStr);
}
return gcLogExpire;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java
index b4bb2a9293..909b3e3082 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LooseObjects.java
@@ -26,8 +26,9 @@ import org.eclipse.jgit.internal.storage.file.FileObjectDatabase.InsertLooseObje
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig;
+import org.eclipse.jgit.lib.CoreConfig.TrustStat;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.util.FileUtils;
@@ -49,13 +50,13 @@ class LooseObjects {
* Maximum number of attempts to read a loose object for which a stale file
* handle exception is thrown
*/
- private final static int MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS = 5;
+ private final static int MAX_STALE_READ_RETRIES = 5;
private final File directory;
private final UnpackedObjectCache unpackedObjectCache;
- private final boolean trustFolderStat;
+ private final TrustStat trustLooseObjectStat;
/**
* Initialize a reference to an on-disk object directory.
@@ -68,9 +69,8 @@ class LooseObjects {
LooseObjects(Config config, File dir) {
directory = dir;
unpackedObjectCache = new UnpackedObjectCache();
- trustFolderStat = config.getBoolean(
- ConfigConstants.CONFIG_CORE_SECTION,
- ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true);
+ trustLooseObjectStat = config.get(CoreConfig.KEY)
+ .getTrustLooseObjectStat();
}
/**
@@ -108,7 +108,8 @@ class LooseObjects {
*/
boolean has(AnyObjectId objectId) {
boolean exists = hasWithoutRefresh(objectId);
- if (trustFolderStat || exists) {
+ if (trustLooseObjectStat == TrustStat.ALWAYS
+ || exists) {
return exists;
}
try (InputStream stream = Files.newInputStream(directory.toPath())) {
@@ -163,13 +164,31 @@ class LooseObjects {
}
ObjectLoader open(WindowCursor curs, AnyObjectId id) throws IOException {
- int readAttempts = 0;
- while (readAttempts < MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS) {
- readAttempts++;
- File path = fileFor(id);
- if (trustFolderStat && !path.exists()) {
+ File path = fileFor(id);
+ for (int retries = 0; retries < MAX_STALE_READ_RETRIES; retries++) {
+ boolean reload = true;
+ switch (trustLooseObjectStat) {
+ case NEVER:
break;
+ case AFTER_OPEN:
+ try (InputStream stream = Files
+ .newInputStream(path.getParentFile().toPath())) {
+ // open the loose object's fanout directory to refresh
+ // attributes (on some NFS clients)
+ } catch (FileNotFoundException | NoSuchFileException e) {
+ // ignore
+ }
+ //$FALL-THROUGH$
+ case ALWAYS:
+ if (!path.exists()) {
+ reload = false;
+ }
+ break;
+ case INHERIT:
+ // only used in CoreConfig internally
+ throw new IllegalStateException();
}
+ if (reload) {
try {
return getObjectLoader(curs, path, id);
} catch (FileNotFoundException noFile) {
@@ -183,9 +202,10 @@ class LooseObjects {
}
if (LOG.isDebugEnabled()) {
LOG.debug(MessageFormat.format(
- JGitText.get().looseObjectHandleIsStale, id.name(),
- Integer.valueOf(readAttempts), Integer.valueOf(
- MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS)));
+ JGitText.get().looseObjectHandleIsStale,
+ id.name(), Integer.valueOf(retries),
+ Integer.valueOf(MAX_STALE_READ_RETRIES)));
+ }
}
}
}
@@ -211,7 +231,7 @@ class LooseObjects {
try {
return getObjectLoaderWithoutRefresh(curs, path, id);
} catch (FileNotFoundException e) {
- if (trustFolderStat) {
+ if (trustLooseObjectStat == TrustStat.ALWAYS) {
throw e;
}
try (InputStream stream = Files
@@ -248,7 +268,7 @@ class LooseObjects {
return getSizeWithoutRefresh(curs, id);
} catch (FileNotFoundException noFile) {
try {
- if (trustFolderStat) {
+ if (trustLooseObjectStat == TrustStat.ALWAYS) {
throw noFile;
}
try (InputStream stream = Files
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
index 9f21481a13..3a6de4e8e2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
@@ -200,6 +200,7 @@ public class ObjectDirectory extends FileObjectDatabase {
loose.close();
packed.close();
+ preserved.close();
// Fully close all loaded alternates and clear the alternate list.
AlternateHandle[] alt = alternates.get();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java
index 8d2a86386f..5813d39e9a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java
@@ -95,6 +95,9 @@ public class Pack implements Iterable<PackIndex.MutableEntry> {
private RandomAccessFile fd;
+ /** For managing open/close accounting of {@link #fd}. */
+ private final Object activeLock = new Object();
+
/** Serializes reads performed against {@link #fd}. */
private final Object readLock = new Object();
@@ -113,7 +116,7 @@ public class Pack implements Iterable<PackIndex.MutableEntry> {
private volatile Exception invalidatingCause;
@Nullable
- private PackFile bitmapIdxFile;
+ private volatile PackFile bitmapIdxFile;
private AtomicInteger transientErrorCount = new AtomicInteger();
@@ -645,42 +648,53 @@ public class Pack implements Iterable<PackIndex.MutableEntry> {
throw new EOFException();
}
- private synchronized void beginCopyAsIs()
+ private void beginCopyAsIs()
throws StoredObjectRepresentationNotAvailableException {
- if (++activeCopyRawData == 1 && activeWindows == 0) {
- try {
- doOpen();
- } catch (IOException thisPackNotValid) {
- throw new StoredObjectRepresentationNotAvailableException(
- thisPackNotValid);
+ synchronized (activeLock) {
+ if (++activeCopyRawData == 1 && activeWindows == 0) {
+ try {
+ doOpen();
+ } catch (IOException thisPackNotValid) {
+ throw new StoredObjectRepresentationNotAvailableException(
+ thisPackNotValid);
+ }
}
}
}
- private synchronized void endCopyAsIs() {
- if (--activeCopyRawData == 0 && activeWindows == 0)
- doClose();
+ private void endCopyAsIs() {
+ synchronized (activeLock) {
+ if (--activeCopyRawData == 0 && activeWindows == 0) {
+ doClose();
+ }
+ }
}
- synchronized boolean beginWindowCache() throws IOException {
- if (++activeWindows == 1) {
- if (activeCopyRawData == 0)
- doOpen();
- return true;
+ boolean beginWindowCache() throws IOException {
+ synchronized (activeLock) {
+ if (++activeWindows == 1) {
+ if (activeCopyRawData == 0) {
+ doOpen();
+ }
+ return true;
+ }
+ return false;
}
- return false;
}
- synchronized boolean endWindowCache() {
- final boolean r = --activeWindows == 0;
- if (r && activeCopyRawData == 0)
- doClose();
- return r;
+ boolean endWindowCache() {
+ synchronized (activeLock) {
+ boolean r = --activeWindows == 0;
+ if (r && activeCopyRawData == 0) {
+ doClose();
+ }
+ return r;
+ }
}
private void doOpen() throws IOException {
if (invalid) {
- openFail(true, invalidatingCause);
+ openFail(invalidatingCause);
throw new PackInvalidException(packFile, invalidatingCause);
}
try {
@@ -691,39 +705,41 @@ public class Pack implements Iterable<PackIndex.MutableEntry> {
}
} catch (InterruptedIOException e) {
// don't invalidate the pack, we are interrupted from another thread
- openFail(false, e);
+ openFail(e);
throw e;
} catch (FileNotFoundException fn) {
- // don't invalidate the pack if opening an existing file failed
- // since it may be related to a temporary lack of resources (e.g.
- // max open files)
- openFail(!packFile.exists(), fn);
+ if (!packFile.exists()) {
+ // Failure to open an existing file may be related to a temporary lack of resources
+ // (e.g. max open files)
+ invalid = true;
+ }
+ openFail(fn);
throw fn;
} catch (EOFException | AccessDeniedException | NoSuchFileException
| CorruptObjectException | NoPackSignatureException
| PackMismatchException | UnpackException
| UnsupportedPackIndexVersionException
| UnsupportedPackVersionException pe) {
- // exceptions signaling permanent problems with a pack
- openFail(true, pe);
+ invalid = true; // exceptions signaling permanent problems with a pack
+ openFail(pe);
throw pe;
} catch (IOException ioe) {
- // mark this packfile as invalid when NFS stale file handle error
- // occur
- openFail(FileUtils.isStaleFileHandleInCausalChain(ioe), ioe);
+ if (FileUtils.isStaleFileHandleInCausalChain(ioe)) {
+ invalid = true;
+ }
+ openFail(ioe);
throw ioe;
} catch (RuntimeException ge) {
// generic exceptions could be transient so we should not mark the
// pack invalid to avoid false MissingObjectExceptions
- openFail(false, ge);
+ openFail(ge);
throw ge;
}
}
- private void openFail(boolean invalidate, Exception cause) {
+ private void openFail(Exception cause) {
activeWindows = 0;
activeCopyRawData = 0;
- invalid = invalidate;
invalidatingCause = cause;
doClose();
}
@@ -1197,17 +1213,8 @@ public class Pack implements Iterable<PackIndex.MutableEntry> {
return null;
}
- synchronized void refreshBitmapIndex(PackFile bitmapIndexFile) {
- this.bitmapIdx = Optionally.empty();
- this.invalid = false;
+ void setBitmapIndexFile(PackFile bitmapIndexFile) {
this.bitmapIdxFile = bitmapIndexFile;
- try {
- getBitmapIndex();
- } catch (IOException e) {
- LOG.warn(JGitText.get().bitmapFailedToGet, bitmapIdxFile, e);
- this.bitmapIdx = Optionally.empty();
- this.bitmapIdxFile = null;
- }
}
private synchronized PackReverseIndex getReverseIdx() throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
index e31126f027..f50c17eafa 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
@@ -17,6 +17,8 @@ import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -42,7 +44,8 @@ import org.eclipse.jgit.internal.storage.pack.PackWriter;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.CoreConfig;
+import org.eclipse.jgit.lib.CoreConfig.TrustStat;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.util.FileUtils;
@@ -72,7 +75,7 @@ class PackDirectory {
private final AtomicReference<PackList> packList;
- private final boolean trustFolderStat;
+ private final TrustStat trustPackStat;
/**
* Initialize a reference to an on-disk 'pack' directory.
@@ -86,14 +89,7 @@ class PackDirectory {
this.config = config;
this.directory = directory;
packList = new AtomicReference<>(NO_PACKS);
-
- // Whether to trust the pack folder's modification time. If set to false
- // we will always scan the .git/objects/pack folder to check for new
- // pack files. If set to true (default) we use the folder's size,
- // modification time, and key (inode) and assume that no new pack files
- // can be in this folder if these attributes have not changed.
- trustFolderStat = config.getBoolean(ConfigConstants.CONFIG_CORE_SECTION,
- ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true);
+ trustPackStat = config.get(CoreConfig.KEY).getTrustPackStat();
}
/**
@@ -313,38 +309,42 @@ class PackDirectory {
}
private void handlePackError(IOException e, Pack p) {
- String warnTmpl = null;
+ String warnTemplate = null;
+ String debugTemplate = null;
int transientErrorCount = 0;
- String errTmpl = JGitText.get().exceptionWhileReadingPack;
+ String errorTemplate = JGitText.get().exceptionWhileReadingPack;
if ((e instanceof CorruptObjectException)
|| (e instanceof PackInvalidException)) {
- warnTmpl = JGitText.get().corruptPack;
- LOG.warn(MessageFormat.format(warnTmpl,
+ warnTemplate = JGitText.get().corruptPack;
+ LOG.warn(MessageFormat.format(warnTemplate,
p.getPackFile().getAbsolutePath()), e);
// Assume the pack is corrupted, and remove it from the list.
remove(p);
} else if (e instanceof FileNotFoundException) {
if (p.getPackFile().exists()) {
- errTmpl = JGitText.get().packInaccessible;
+ errorTemplate = JGitText.get().packInaccessible;
transientErrorCount = p.incrementTransientErrorCount();
} else {
- warnTmpl = JGitText.get().packWasDeleted;
+ debugTemplate = JGitText.get().packWasDeleted;
remove(p);
}
} else if (FileUtils.isStaleFileHandleInCausalChain(e)) {
- warnTmpl = JGitText.get().packHandleIsStale;
+ warnTemplate = JGitText.get().packHandleIsStale;
remove(p);
} else {
transientErrorCount = p.incrementTransientErrorCount();
}
- if (warnTmpl != null) {
- LOG.warn(MessageFormat.format(warnTmpl,
+ if (warnTemplate != null) {
+ LOG.warn(MessageFormat.format(warnTemplate,
p.getPackFile().getAbsolutePath()), e);
+ } else if (debugTemplate != null) {
+ LOG.debug(MessageFormat.format(debugTemplate,
+ p.getPackFile().getAbsolutePath()), e);
} else {
if (doLogExponentialBackoff(transientErrorCount)) {
// Don't remove the pack from the list, as the error may be
// transient.
- LOG.error(MessageFormat.format(errTmpl,
+ LOG.error(MessageFormat.format(errorTemplate,
p.getPackFile().getAbsolutePath(),
Integer.valueOf(transientErrorCount)), e);
}
@@ -361,8 +361,26 @@ class PackDirectory {
}
boolean searchPacksAgain(PackList old) {
- return (!trustFolderStat || old.snapshot.isModified(directory))
- && old != scanPacks(old);
+ switch (trustPackStat) {
+ case NEVER:
+ break;
+ case AFTER_OPEN:
+ try (InputStream stream = Files
+ .newInputStream(directory.toPath())) {
+ // open the pack directory to refresh attributes (on some NFS clients)
+ } catch (IOException e) {
+ // ignore
+ }
+ //$FALL-THROUGH$
+ case ALWAYS:
+ if (!old.snapshot.isModified(directory)) {
+ return false;
+ }
+ break;
+ case INHERIT:
+ // only used in CoreConfig internally
+ }
+ return old != scanPacks(old);
}
void insert(Pack pack) {
@@ -459,12 +477,9 @@ class PackDirectory {
&& !oldPack.getFileSnapshot().isModified(packFile)) {
forReuse.remove(packFile.getName());
list.add(oldPack);
- try {
- if(oldPack.getBitmapIndex() == null) {
- oldPack.refreshBitmapIndex(packFilesByExt.get(BITMAP_INDEX));
- }
- } catch (IOException e) {
- LOG.warn(JGitText.get().bitmapAccessErrorForPackfile, oldPack.getPackName(), e);
+ PackFile bitMaps = packFilesByExt.get(BITMAP_INDEX);
+ if (bitMaps != null) {
+ oldPack.setBitmapIndexFile(bitMaps);
}
continue;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java
index c9b05ad025..5f2015b834 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java
@@ -185,7 +185,11 @@ public class PackFile extends File {
private static PackExt getPackExt(String endsWithExtension) {
for (PackExt ext : PackExt.values()) {
- if (endsWithExtension.endsWith(ext.getExtension())) {
+ if (endsWithExtension.equals(ext.getExtension())) {
+ return ext;
+ }
+
+ if (endsWithExtension.equals("old-" + ext.getExtension())) {
return ext;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
index 7189ce20a6..b3e4efb4fc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
@@ -286,7 +286,7 @@ public interface PackIndex
* the index cannot be read.
*/
void resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
- int matchLimit) throws IOException;
+ int matchLimit) throws IOException;
/**
* Get pack checksum
@@ -304,6 +304,7 @@ public interface PackIndex
class MutableEntry {
/** Buffer of the ObjectId visited by the EntriesIterator. */
final MutableObjectId idBuffer = new MutableObjectId();
+
/** Offset into the packfile of the current object. */
long offset;
@@ -345,6 +346,34 @@ public interface PackIndex
r.offset = offset;
return r;
}
+
+ /**
+ * Similar to {@link Comparable#compareTo(Object)}, using only the
+ * object id in the entry.
+ *
+ * @param other
+ * Another mutable entry (probably from another index)
+ *
+ * @return a negative integer, zero, or a positive integer as this
+ * object is less than, equal to, or greater than the specified
+ * object.
+ */
+ public int compareBySha1To(MutableEntry other) {
+ return idBuffer.compareTo(other.idBuffer);
+ }
+
+ /**
+ * Copy the current ObjectId to dest
+ * <p>
+ * Like {@link #toObjectId()}, but reusing the destination instead of
+ * creating a new ObjectId instance.
+ *
+ * @param dest
+ * destination for the object id
+ */
+ public void copyOidTo(MutableObjectId dest) {
+ dest.fromObjectId(idBuffer);
+ }
}
/**
@@ -368,7 +397,6 @@ public interface PackIndex
this.objectCount = objectCount;
}
-
@Override
public boolean hasNext() {
return returnedNumber < objectCount;
@@ -393,7 +421,6 @@ public interface PackIndex
*/
protected abstract void readNext();
-
/**
* Copies to the entry an {@link ObjectId} from the int buffer and
* position idx
@@ -423,7 +450,8 @@ public interface PackIndex
/**
* Sets the {@code offset} to the entry
*
- * @param offset the offset in the pack file
+ * @param offset
+ * the offset in the pack file
*/
protected void setOffset(long offset) {
entry.offset = offset;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index 6aa1157e37..319a9ed710 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -64,10 +64,9 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.ObjectWritingException;
import org.eclipse.jgit.events.RefsChangedEvent;
import org.eclipse.jgit.internal.JGitText;
-import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.CoreConfig.TrustLooseRefStat;
-import org.eclipse.jgit.lib.CoreConfig.TrustPackedRefsStat;
+import org.eclipse.jgit.lib.CoreConfig;
+import org.eclipse.jgit.lib.CoreConfig.TrustStat;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ProgressMonitor;
@@ -76,6 +75,7 @@ import org.eclipse.jgit.lib.RefComparator;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefWriter;
+import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.SymbolicRef;
import org.eclipse.jgit.revwalk.RevObject;
@@ -184,11 +184,7 @@ public class RefDirectory extends RefDatabase {
private List<Integer> retrySleepMs = RETRY_SLEEP_MS;
- private final boolean trustFolderStat;
-
- private final TrustPackedRefsStat trustPackedRefsStat;
-
- private final TrustLooseRefStat trustLooseRefStat;
+ private final CoreConfig coreConfig;
RefDirectory(RefDirectory refDb) {
parent = refDb.parent;
@@ -200,9 +196,7 @@ public class RefDirectory extends RefDatabase {
packedRefsFile = refDb.packedRefsFile;
looseRefs.set(refDb.looseRefs.get());
packedRefs.set(refDb.packedRefs.get());
- trustFolderStat = refDb.trustFolderStat;
- trustPackedRefsStat = refDb.trustPackedRefsStat;
- trustLooseRefStat = refDb.trustLooseRefStat;
+ coreConfig = refDb.coreConfig;
inProcessPackedRefsLock = refDb.inProcessPackedRefsLock;
}
@@ -218,17 +212,7 @@ public class RefDirectory extends RefDatabase {
looseRefs.set(RefList.<LooseRef> emptyList());
packedRefs.set(NO_PACKED_REFS);
- trustFolderStat = db.getConfig()
- .getBoolean(ConfigConstants.CONFIG_CORE_SECTION,
- ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true);
- trustPackedRefsStat = db.getConfig()
- .getEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_TRUST_PACKED_REFS_STAT,
- TrustPackedRefsStat.UNSET);
- trustLooseRefStat = db.getConfig()
- .getEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
- ConfigConstants.CONFIG_KEY_TRUST_LOOSE_REF_STAT,
- TrustLooseRefStat.ALWAYS);
+ coreConfig = db.getConfig().get(CoreConfig.KEY);
inProcessPackedRefsLock = new ReentrantLock(true);
}
@@ -456,6 +440,11 @@ public class RefDirectory extends RefDatabase {
return ret;
}
+ @Override
+ public ReflogReader getReflogReader(Ref ref) throws IOException {
+ return new ReflogReaderImpl(getRepository(), ref.getName());
+ }
+
@SuppressWarnings("unchecked")
private RefList<Ref> upcast(RefList<? extends Ref> loose) {
return (RefList<Ref>) loose;
@@ -712,41 +701,47 @@ public class RefDirectory extends RefDatabase {
}
String name = dst.getName();
- // Write the packed-refs file using an atomic update. We might
- // wind up reading it twice, before and after the lock, to ensure
- // we don't miss an edit made externally.
- PackedRefList packed = getPackedRefs();
- if (packed.contains(name)) {
- inProcessPackedRefsLock.lock();
+ // Get and keep the packed-refs lock while updating packed-refs and
+ // removing any loose ref
+ inProcessPackedRefsLock.lock();
+ try {
+ LockFile lck = lockPackedRefsOrThrow();
try {
- LockFile lck = lockPackedRefsOrThrow();
- try {
+ // Write the packed-refs file using an atomic update. We might
+ // wind up reading it twice, before and after checking if the
+ // ref to delete is included or not, to ensure
+ // we don't rely on a PackedRefList that is a result of in-memory
+ // or NFS caching.
+ PackedRefList packed = getPackedRefs();
+ if (packed.contains(name)) {
+ // Force update our packed-refs snapshot before writing
packed = refreshPackedRefs();
int idx = packed.find(name);
if (0 <= idx) {
commitPackedRefs(lck, packed.remove(idx), packed, true);
}
- } finally {
- lck.unlock();
}
- } finally {
- inProcessPackedRefsLock.unlock();
- }
- }
- RefList<LooseRef> curLoose, newLoose;
- do {
- curLoose = looseRefs.get();
- int idx = curLoose.find(name);
- if (idx < 0)
- break;
- newLoose = curLoose.remove(idx);
- } while (!looseRefs.compareAndSet(curLoose, newLoose));
+ RefList<LooseRef> curLoose, newLoose;
+ do {
+ curLoose = looseRefs.get();
+ int idx = curLoose.find(name);
+ if (idx < 0) {
+ break;
+ }
+ newLoose = curLoose.remove(idx);
+ } while (!looseRefs.compareAndSet(curLoose, newLoose));
- int levels = levelsIn(name) - 2;
- delete(logFor(name), levels);
- if (dst.getStorage().isLoose()) {
- deleteAndUnlock(fileFor(name), levels, update);
+ int levels = levelsIn(name) - 2;
+ delete(logFor(name), levels);
+ if (dst.getStorage().isLoose()) {
+ deleteAndUnlock(fileFor(name), levels, update);
+ }
+ } finally {
+ lck.unlock();
+ }
+ } finally {
+ inProcessPackedRefsLock.unlock();
}
modCnt.incrementAndGet();
@@ -973,7 +968,7 @@ public class RefDirectory extends RefDatabase {
PackedRefList getPackedRefs() throws IOException {
final PackedRefList curList = packedRefs.get();
- switch (trustPackedRefsStat) {
+ switch (coreConfig.getTrustPackedRefsStat()) {
case NEVER:
break;
case AFTER_OPEN:
@@ -989,12 +984,8 @@ public class RefDirectory extends RefDatabase {
return curList;
}
break;
- case UNSET:
- if (trustFolderStat
- && !curList.snapshot.isModified(packedRefsFile)) {
- return curList;
- }
- break;
+ case INHERIT:
+ // only used in CoreConfig internally
}
return refreshPackedRefs(curList);
@@ -1180,7 +1171,7 @@ public class RefDirectory extends RefDatabase {
LooseRef scanRef(LooseRef ref, String name) throws IOException {
final File path = fileFor(name);
- if (trustLooseRefStat.equals(TrustLooseRefStat.AFTER_OPEN)) {
+ if (coreConfig.getTrustLooseRefStat() == TrustStat.AFTER_OPEN) {
refreshPathToLooseRef(Paths.get(name));
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java
index fd80faf4ed..15c125c684 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java
@@ -790,7 +790,9 @@ public class WindowCache {
}
numRemovers++;
}
- for (int numRemoved = 0; removeNextBlock(numRemoved); numRemoved++);
+ for (int numRemoved = 0; removeNextBlock(numRemoved); numRemoved++) {
+ // empty
+ }
synchronized (this) {
if (numRemovers > 0) {
numRemovers--;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java
new file mode 100644
index 0000000000..15b52391b8
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndex.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024, GerritForge Inc. 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.midx;
+
+import java.util.Set;
+
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * An index over multiple packs
+ */
+public interface MultiPackIndex {
+
+ /**
+ * Obtain the array of packfiles in the MultiPackIndex.
+ * <p>
+ * The pack ids correspond to positions in this list.
+ *
+ * @return array of packnames refered in this multipak index
+ */
+ String[] getPackNames();
+
+ /**
+ * Does this index contains the object
+ *
+ * @param oid
+ * object id
+ * @return true of the index knows this the object
+ */
+ boolean hasObject(AnyObjectId oid);
+
+ /**
+ * Obtain the location of the object.
+ * <p>
+ * The returned object can be reused by the implementations. Callers
+ * must create a #copy() if they want to keep a reference.
+ *
+ * @param objectId
+ * objectId to read.
+ * @return mutable instance with the location or null if not found.
+ */
+ PackOffset find(AnyObjectId objectId);
+
+ /**
+ * Find objects matching the prefix abbreviation.
+ *
+ * @param matches
+ * set to add any located ObjectIds to. This is an output
+ * parameter.
+ * @param id
+ * prefix to search for.
+ * @param matchLimit
+ * maximum number of results to return. At most this many
+ * ObjectIds should be added to matches before returning.
+ */
+ void resolve(Set<ObjectId> matches, AbbreviatedObjectId id, int matchLimit);
+
+ /**
+ * Memory size of this multipack index
+ *
+ * @return size of this multipack index in memory, in bytes
+ */
+ long getMemorySize();
+
+ /**
+ * (packId, offset) coordinates of an object
+ */
+ class PackOffset {
+
+ int packId;
+
+ long offset;
+
+ protected PackOffset setValues(int packId, long offset) {
+ this.packId = packId;
+ this.offset = offset;
+ return this;
+ }
+
+ public int getPackId() {
+ return packId;
+ }
+
+ public long getOffset() {
+ return offset;
+ }
+
+ public PackOffset copy() {
+ PackOffset copy = new PackOffset();
+ return copy.setValues(this.packId, this.offset);
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexConstants.java
new file mode 100644
index 0000000000..5d86f44baf
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexConstants.java
@@ -0,0 +1,58 @@
+/*
+ * 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.midx;
+
+class MultiPackIndexConstants {
+ static final int MIDX_SIGNATURE = 0x4d494458; /* MIDX */
+
+ static final byte MIDX_VERSION = 1;
+
+ /**
+ * We infer the length of object IDs (OIDs) from this value:
+ *
+ * <pre>
+ * 1 => SHA-1
+ * 2 => SHA-256
+ * </pre>
+ */
+ static final byte OID_HASH_VERSION = 1;
+
+ static final int MULTIPACK_INDEX_FANOUT_SIZE = 4 * 256;
+
+ /**
+ * First 4 bytes describe the chunk id. Value 0 is a terminating label.
+ * Other 8 bytes provide the byte-offset in current file for chunk to start.
+ */
+ static final int CHUNK_LOOKUP_WIDTH = 12;
+
+ /** "PNAM" chunk */
+ static final int MIDX_CHUNKID_PACKNAMES = 0x504e414d;
+
+ /** "OIDF" chunk */
+ static final int MIDX_CHUNKID_OIDFANOUT = 0x4f494446;
+
+ /** "OIDL" chunk */
+ static final int MIDX_CHUNKID_OIDLOOKUP = 0x4f49444c;
+
+ /** "OOFF" chunk */
+ static final int MIDX_CHUNKID_OBJECTOFFSETS = 0x4f4f4646;
+
+ /** "LOFF" chunk */
+ static final int MIDX_CHUNKID_LARGEOFFSETS = 0x4c4f4646;
+
+ /** "RIDX" chunk */
+ static final int MIDX_CHUNKID_REVINDEX = 0x52494458;
+
+ /** "BTMP" chunk */
+ static final int MIDX_CHUNKID_BITMAPPEDPACKS = 0x42544D50;
+
+ private MultiPackIndexConstants() {
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java
new file mode 100644
index 0000000000..61caddc221
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexLoader.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2024, GerritForge Inc. 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.midx;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_BITMAPPEDPACKS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_LARGEOFFSETS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDLOOKUP;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_PACKNAMES;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_REVINDEX;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_SIGNATURE;
+import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.NB;
+import org.eclipse.jgit.util.io.SilentFileInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The loader returns the representation of the MultiPackIndex file content.
+ */
+public class MultiPackIndexLoader {
+ private final static Logger LOG = LoggerFactory
+ .getLogger(MultiPackIndexLoader.class);
+
+ /**
+ * Open an existing MultiPackIndex file for reading.
+ * <p>
+ * The format of the file will be automatically detected and a proper access
+ * implementation for that format will be constructed and returned to the
+ * caller. The file may or may not be held open by the returned instance.
+ *
+ * @param midxFile
+ * existing multi-pack-index to read.
+ * @return a copy of the multi-pack-index file in memory
+ * @throws FileNotFoundException
+ * the file does not exist.
+ * @throws MultiPackIndexFormatException
+ * MultiPackIndex file's format is different from we expected.
+ * @throws java.io.IOException
+ * the file exists but could not be read due to security errors
+ * or unexpected data corruption.
+ */
+ public static MultiPackIndex open(File midxFile)
+ throws FileNotFoundException, MultiPackIndexFormatException,
+ IOException {
+ try (SilentFileInputStream fd = new SilentFileInputStream(midxFile)) {
+ try {
+ return read(fd);
+ } catch (MultiPackIndexFormatException fe) {
+ throw fe;
+ } catch (IOException ioe) {
+ throw new IOException(
+ MessageFormat.format(JGitText.get().unreadableMIDX,
+ midxFile.getAbsolutePath()),
+ ioe);
+ }
+ }
+ }
+
+ /**
+ * Read an existing MultiPackIndex file from a buffered stream.
+ * <p>
+ * The format of the file will be automatically detected and a proper access
+ * implementation for that format will be constructed and returned to the
+ * caller. The file may or may not be held open by the returned instance.
+ *
+ * @param fd
+ * stream to read the multipack-index file from. The stream must be
+ * buffered as some small IOs are performed against the stream.
+ * The caller is responsible for closing the stream.
+ * @return a copy of the MultiPackIndex file in memory
+ * @throws MultiPackIndexFormatException
+ * the MultiPackIndex file's format is different from we
+ * expected.
+ * @throws java.io.IOException
+ * the stream cannot be read.
+ */
+ public static MultiPackIndex read(InputStream fd)
+ throws MultiPackIndexFormatException, IOException {
+ byte[] hdr = new byte[12];
+ IO.readFully(fd, hdr, 0, hdr.length);
+
+ int magic = NB.decodeInt32(hdr, 0);
+
+ if (magic != MIDX_SIGNATURE) {
+ throw new MultiPackIndexFormatException(JGitText.get().notAMIDX);
+ }
+
+ // Check MultiPackIndex version
+ int v = hdr[4];
+ if (v != 1) {
+ throw new MultiPackIndexFormatException(MessageFormat
+ .format(JGitText.get().unsupportedMIDXVersion, v));
+ }
+
+ // Read the object Id version (1 byte)
+ // 1 => SHA-1
+ // 2 => SHA-256
+ // TODO: If the hash type does not match the repository's hash
+ // algorithm,
+ // the multi-pack-index file should be ignored with a warning
+ // presented to the user.
+ int commitIdVersion = hdr[5];
+ if (commitIdVersion != 1) {
+ throw new MultiPackIndexFormatException(
+ JGitText.get().incorrectOBJECT_ID_LENGTH);
+ }
+
+ // Read the number of "chunkOffsets" (1 byte)
+ int chunkCount = hdr[6];
+
+ // Read the number of multi-pack-index files (1 byte)
+ // This value is currently always zero.
+ // TODO populate this
+ // int numberOfMultiPackIndexFiles = hdr[7];
+
+ // Number of packfiles (4 bytes)
+ int packCount = NB.decodeInt32(hdr, 8);
+
+ byte[] lookupBuffer = new byte[CHUNK_LOOKUP_WIDTH * (chunkCount + 1)];
+
+ IO.readFully(fd, lookupBuffer, 0, lookupBuffer.length);
+
+ List<ChunkSegment> chunks = new ArrayList<>(chunkCount + 1);
+ for (int i = 0; i <= chunkCount; i++) {
+ // chunks[chunkCount] is just a marker, in order to record the
+ // length of the last chunk.
+ int id = NB.decodeInt32(lookupBuffer, i * 12);
+ long offset = NB.decodeInt64(lookupBuffer, i * 12 + 4);
+ chunks.add(new ChunkSegment(id, offset));
+ }
+
+ MultiPackIndexBuilder builder = MultiPackIndexBuilder.builder();
+ builder.setPackCount(packCount);
+ for (int i = 0; i < chunkCount; i++) {
+ long chunkOffset = chunks.get(i).offset;
+ int chunkId = chunks.get(i).id;
+ long len = chunks.get(i + 1).offset - chunkOffset;
+
+ if (len > Integer.MAX_VALUE - 8) { // http://stackoverflow.com/a/8381338
+ throw new MultiPackIndexFormatException(
+ JGitText.get().multiPackIndexFileIsTooLargeForJgit);
+ }
+
+ byte[] buffer = new byte[(int) len];
+ IO.readFully(fd, buffer, 0, buffer.length);
+
+ switch (chunkId) {
+ case MIDX_CHUNKID_OIDFANOUT:
+ builder.addOidFanout(buffer);
+ break;
+ case MIDX_CHUNKID_OIDLOOKUP:
+ builder.addOidLookUp(buffer);
+ break;
+ case MIDX_CHUNKID_PACKNAMES:
+ builder.addPackNames(buffer);
+ break;
+ case MIDX_CHUNKID_BITMAPPEDPACKS:
+ builder.addBitmappedPacks(buffer);
+ break;
+ case MIDX_CHUNKID_OBJECTOFFSETS:
+ builder.addObjectOffsets(buffer);
+ break;
+ case MIDX_CHUNKID_LARGEOFFSETS:
+ builder.addObjectLargeOffsets(buffer);
+ break;
+ default:
+ LOG.warn(MessageFormat.format(JGitText.get().midxChunkUnknown,
+ Integer.toHexString(chunkId)));
+ }
+ }
+ return builder.build();
+ }
+
+ private record ChunkSegment(int id, long offset) {}
+
+ /**
+ * Accumulate byte[] of the different chunks, to build a multipack index
+ */
+ // Visible for testing
+ static class MultiPackIndexBuilder {
+
+ private final int hashLength;
+
+ private int packCount;
+
+ private byte[] oidFanout;
+
+ private byte[] oidLookup;
+
+ private String[] packNames;
+
+ private byte[] bitmappedPackfiles;
+
+ private byte[] objectOffsets;
+
+ // Optional
+ private byte[] largeObjectOffsets;
+
+ // Optional
+ private byte[] bitmapPackOrder;
+
+ private MultiPackIndexBuilder(int hashLength) {
+ this.hashLength = hashLength;
+ }
+
+ /**
+ * Create builder
+ *
+ * @return A builder of {@link MultiPackIndex}.
+ */
+ static MultiPackIndexBuilder builder() {
+ return new MultiPackIndexBuilder(OBJECT_ID_LENGTH);
+ }
+
+ MultiPackIndexBuilder setPackCount(int packCount) {
+ this.packCount = packCount;
+ return this;
+ }
+
+ MultiPackIndexBuilder addOidFanout(byte[] buffer)
+ throws MultiPackIndexFormatException {
+ assertChunkNotSeenYet(oidFanout, MIDX_CHUNKID_OIDFANOUT);
+ oidFanout = buffer;
+ return this;
+ }
+
+ MultiPackIndexBuilder addOidLookUp(byte[] buffer)
+ throws MultiPackIndexFormatException {
+ assertChunkNotSeenYet(oidLookup, MIDX_CHUNKID_OIDLOOKUP);
+ oidLookup = buffer;
+ return this;
+ }
+
+ MultiPackIndexBuilder addPackNames(byte[] buffer)
+ throws MultiPackIndexFormatException {
+ assertChunkNotSeenYet(packNames, MIDX_CHUNKID_PACKNAMES);
+ packNames = new String(buffer, UTF_8).split("\u0000"); //$NON-NLS-1$
+ return this;
+ }
+
+ MultiPackIndexBuilder addBitmappedPacks(byte[] buffer)
+ throws MultiPackIndexFormatException {
+ assertChunkNotSeenYet(bitmappedPackfiles,
+ MIDX_CHUNKID_BITMAPPEDPACKS);
+ bitmappedPackfiles = buffer;
+ return this;
+ }
+
+ MultiPackIndexBuilder addObjectOffsets(byte[] buffer)
+ throws MultiPackIndexFormatException {
+ assertChunkNotSeenYet(objectOffsets, MIDX_CHUNKID_OBJECTOFFSETS);
+ objectOffsets = buffer;
+ return this;
+ }
+
+ MultiPackIndexBuilder addObjectLargeOffsets(byte[] buffer)
+ throws MultiPackIndexFormatException {
+ assertChunkNotSeenYet(largeObjectOffsets,
+ MIDX_CHUNKID_LARGEOFFSETS);
+ largeObjectOffsets = buffer;
+ return this;
+ }
+
+ MultiPackIndexBuilder addReverseIndex(byte[] buffer)
+ throws MultiPackIndexFormatException {
+ assertChunkNotSeenYet(bitmapPackOrder, MIDX_CHUNKID_REVINDEX);
+ bitmapPackOrder = buffer;
+ return this;
+ }
+
+ MultiPackIndex build() throws MultiPackIndexFormatException {
+ assertChunkNotNull(oidFanout, MIDX_CHUNKID_OIDFANOUT);
+ assertChunkNotNull(oidLookup, MIDX_CHUNKID_OIDLOOKUP);
+ assertChunkNotNull(packNames, MIDX_CHUNKID_PACKNAMES);
+ assertChunkNotNull(objectOffsets, MIDX_CHUNKID_OBJECTOFFSETS);
+
+ assertPackCounts(packCount, packNames.length);
+ return new MultiPackIndexV1(hashLength, oidFanout, oidLookup,
+ packNames, bitmappedPackfiles, objectOffsets, largeObjectOffsets);
+ }
+
+ private static void assertChunkNotNull(Object object, int chunkId)
+ throws MultiPackIndexFormatException {
+ if (object == null) {
+ throw new MultiPackIndexFormatException(
+ MessageFormat.format(JGitText.get().midxChunkNeeded,
+ Integer.toHexString(chunkId)));
+ }
+ }
+
+ private static void assertChunkNotSeenYet(Object object, int chunkId)
+ throws MultiPackIndexFormatException {
+ if (object != null) {
+ throw new MultiPackIndexFormatException(
+ MessageFormat.format(JGitText.get().midxChunkRepeated,
+ Integer.toHexString(chunkId)));
+ }
+ }
+
+ private static void assertPackCounts(int headerCount,
+ int packfileNamesCount) throws MultiPackIndexFormatException {
+ if (headerCount != packfileNamesCount) {
+ throw new MultiPackIndexFormatException(MessageFormat.format(
+ JGitText.get().multiPackIndexPackCountMismatch,
+ headerCount, packfileNamesCount));
+ }
+ }
+ }
+
+ /**
+ * Thrown when a MultiPackIndex file's format is different from we expected
+ */
+ public static class MultiPackIndexFormatException extends IOException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct an exception.
+ *
+ * @param why
+ * description of the type of error.
+ */
+ MultiPackIndexFormatException(String why) {
+ super(why);
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexPrettyPrinter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexPrettyPrinter.java
new file mode 100644
index 0000000000..948b7bc174
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexPrettyPrinter.java
@@ -0,0 +1,156 @@
+/*
+ * 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.midx;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.util.NB;
+
+/**
+ * Prints a multipack index file in a human-readable format.
+ *
+ * @since 7.2
+ */
+@SuppressWarnings({ "boxing", "nls" })
+public class MultiPackIndexPrettyPrinter {
+
+ /**
+ * Writes to out, in human-readable format, the multipack index in rawMidx
+ *
+ * @param rawMidx the bytes of a multipack index
+ * @param out a writer
+ */
+ public static void prettyPrint(byte[] rawMidx, PrintWriter out) {
+ // Header (12 bytes)
+ out.println("[ 0] Magic: " + new String(rawMidx, 0, 4, UTF_8));
+ out.println("[ 4] Version number: " + (int) rawMidx[4]);
+ out.println("[ 5] OID version: " + (int) rawMidx[5]);
+ int chunkCount = rawMidx[6];
+ out.println("[ 6] # of chunks: " + chunkCount);
+ out.println("[ 7] # of bases: " + (int) rawMidx[7]);
+ int numberOfPacks = NB.decodeInt32(rawMidx, 8);
+ out.println("[ 8] # of packs: " + numberOfPacks);
+
+ // Chunk lookup table
+ List<ChunkSegment> chunkSegments = new ArrayList<>();
+ int current = printChunkLookup(out, rawMidx, chunkCount, chunkSegments);
+
+ for (int i = 0; i < chunkSegments.size() - 1; i++) {
+ ChunkSegment segment = chunkSegments.get(i);
+ if (current != segment.startOffset()) {
+ throw new IllegalStateException(String.format(
+ "We are at byte %d, but segment should start at %d",
+ current, segment.startOffset()));
+ }
+ out.printf("Starting chunk: %s @ %d%n", segment.chunkName(),
+ segment.startOffset());
+ switch (segment.chunkName()) {
+ case "OIDF" -> current = printOIDF(out, rawMidx, current);
+ case "OIDL" -> current = printOIDL(out, rawMidx, current,
+ chunkSegments.get(i + 1).startOffset);
+ case "OOFF" -> current = printOOFF(out, rawMidx, current,
+ chunkSegments.get(i + 1).startOffset);
+ case "PNAM" -> current = printPNAM(out, rawMidx, current,
+ chunkSegments.get(i + 1).startOffset);
+ case "RIDX" -> current = printRIDX(out, rawMidx, current,
+ chunkSegments.get(i + 1).startOffset);
+ default -> {
+ out.printf(
+ "Skipping %s (don't know how to print it yet)%n",
+ segment.chunkName());
+ current = (int) chunkSegments.get(i + 1).startOffset();
+ }
+ }
+ }
+ // Checksum is a SHA-1, use ObjectId to parse it
+ out.printf("[ %d] Checksum %s%n", current,
+ ObjectId.fromRaw(rawMidx, current).name());
+ out.printf("Total size: " + (current + 20));
+ }
+
+ private static int printChunkLookup(PrintWriter out, byte[] rawMidx, int chunkCount,
+ List<ChunkSegment> chunkSegments) {
+ out.println("Starting chunk lookup @ 12");
+ int current = 12;
+ for (int i = 0; i < chunkCount; i++) {
+ String chunkName = new String(rawMidx, current, 4, UTF_8);
+ long offset = NB.decodeInt64(rawMidx, current + 4);
+ out.printf("[ %d] |%8s|%8d|%n", current, chunkName, offset);
+ current += CHUNK_LOOKUP_WIDTH;
+ chunkSegments.add(new ChunkSegment(chunkName, offset));
+ }
+ String chunkName = "0000";
+ long offset = NB.decodeInt64(rawMidx, current + 4);
+ out.printf("[ %d] |%8s|%8d|%n", current, chunkName, offset);
+ current += CHUNK_LOOKUP_WIDTH;
+ chunkSegments.add(new ChunkSegment(chunkName, offset));
+ return current;
+ }
+
+ private static int printOIDF(PrintWriter out, byte[] rawMidx, int start) {
+ int current = start;
+ for (short i = 0; i < 256; i++) {
+ out.printf("[ %d] (%02X) %d%n", current, i,
+ NB.decodeInt32(rawMidx, current));
+ current += 4;
+ }
+ return current;
+ }
+
+ private static int printOIDL(PrintWriter out, byte[] rawMidx, int start, long end) {
+ int i = start;
+ while (i < end) {
+ out.printf("[ %d] %s%n", i,
+ ObjectId.fromRaw(rawMidx, i).name());
+ i += 20;
+ }
+ return i;
+ }
+
+ private static int printOOFF(PrintWriter out, byte[] rawMidx, int start, long end) {
+ int i = start;
+ while (i < end) {
+ out.printf("[ %d] %d %d%n", i, NB.decodeInt32(rawMidx, i),
+ NB.decodeInt32(rawMidx, i + 4));
+ i += 8;
+ }
+ return i;
+ }
+
+ private static int printRIDX(PrintWriter out, byte[] rawMidx, int start, long end) {
+ int i = start;
+ while (i < end) {
+ out.printf("[ %d] %d%n", i, NB.decodeInt32(rawMidx, i));
+ i += 4;
+ }
+ return (int) end;
+ }
+
+ private static int printPNAM(PrintWriter out, byte[] rawMidx, int start, long end) {
+ int nameStart = start;
+ for (int i = start; i < end; i++) {
+ if (rawMidx[i] == 0) {
+ out
+ .println(new String(rawMidx, nameStart, i - nameStart));
+ nameStart = i + 1;
+ }
+ }
+ return (int) end;
+ }
+
+ private record ChunkSegment(String chunkName, long startOffset) {
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java
new file mode 100644
index 0000000000..be752cc4b5
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexV1.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2024, GerritForge Inc. 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.internal.storage.midx;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Set;
+
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.midx.MultiPackIndexLoader.MultiPackIndexFormatException;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.util.NB;
+
+/**
+ * Support for the MultiPackIndex v1 format.
+ *
+ * @see MultiPackIndex
+ */
+class MultiPackIndexV1 implements MultiPackIndex {
+
+ private final OidLookup idx;
+
+ private final String[] packNames;
+
+ private final byte[] bitmappedPackfiles;
+
+ private final OffsetLookup offsets;
+
+ private final PackOffset result = new PackOffset();
+
+ MultiPackIndexV1(int hashLength, @NonNull byte[] oidFanout,
+ @NonNull byte[] oidLookup, String[] packNames,
+ byte[] bitmappedPackfiles, byte[] objectOffsets,
+ byte[] largeObjectOffsets) throws MultiPackIndexFormatException {
+ this.bitmappedPackfiles = bitmappedPackfiles;
+ this.idx = new OidLookup(hashLength, oidFanout, oidLookup);
+ this.offsets = new OffsetLookup(objectOffsets, largeObjectOffsets);
+ this.packNames = packNames;
+ }
+
+ @Override
+ public String[] getPackNames() {
+ return packNames;
+ }
+
+ @Override
+ public boolean hasObject(AnyObjectId oid) {
+ return idx.findMultiPackIndexPosition(oid) != -1;
+ }
+
+ @Override
+ @Nullable
+ public PackOffset find(AnyObjectId objectId) {
+ int position = idx.findMultiPackIndexPosition(objectId);
+ if (position == -1) {
+ return null;
+ }
+ offsets.getObjectOffset(position, result);
+ return result;
+ }
+
+ @Override
+ public void resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
+ int matchLimit) {
+ idx.resolve(matches, id, matchLimit);
+ }
+
+ @Override
+ public long getMemorySize() {
+ int packNamesSize = Arrays.stream(packNames)
+ .mapToInt(s -> s.getBytes(StandardCharsets.UTF_8).length).sum();
+ return packNamesSize + byteArrayLengh(bitmappedPackfiles)
+ + idx.getMemorySize() + offsets.getMemorySize();
+ }
+
+ @Override
+ public String toString() {
+ return "MultiPackIndexV1 {idx=" + idx + ", packfileNames=" //$NON-NLS-1$ //$NON-NLS-2$
+ + Arrays.toString(packNames) + ", bitmappedPackfiles=" //$NON-NLS-1$
+ + byteArrayToString(bitmappedPackfiles) + ", objectOffsets=" //$NON-NLS-1$
+ + offsets + '}';
+ }
+
+ private static String byteArrayToString(byte[] array) {
+ return array == null ? "null" : new String(array); //$NON-NLS-1$
+ }
+
+ private static int byteArrayLengh(byte[] array) {
+ return array == null ? 0 : array.length;
+ }
+
+ /**
+ * Wraps the small and large offset chunks (if exists), to lookup offsets.
+ */
+ private static class OffsetLookup {
+ private static final int OBJECT_OFFSETS_DATA_WIDTH = 8;
+
+ private static final int BIT_31_ON = 0x80000000;
+
+ private static final int TOGGLE_BIT_31 = 0x7fff_ffff;
+
+ private final byte[] offsets;
+
+ private final byte[] largeOffsets;
+
+ /**
+ * Initialize the ObjectOffsets.
+ *
+ * @param offsets
+ * content of ObjectOffset Chunk.
+ * @param largeOffsets
+ * content of largo offsets chunks (can be null).
+ */
+ OffsetLookup(@NonNull byte[] offsets, byte[] largeOffsets) {
+ this.offsets = offsets;
+ this.largeOffsets = largeOffsets;
+ }
+
+ /**
+ * Get the metadata of a commit。
+ *
+ * @param position
+ * the position in the multi-pack-index of the object.
+ * @param result
+ * an instance of PackOffset to populate with the result.
+ */
+ void getObjectOffset(int position, PackOffset result) {
+ int offsetInChunk = position * OBJECT_OFFSETS_DATA_WIDTH;
+ int packId = NB.decodeInt32(offsets, offsetInChunk);
+ int offset = NB.decodeInt32(offsets, offsetInChunk + 4);
+ if ((offset & BIT_31_ON) != 0) {
+ long bigOffset;
+ if (largeOffsets == null) {
+ bigOffset = NB.decodeUInt32(offsets, offsetInChunk + 4);
+ } else {
+ int bigOffsetPos = (offset & TOGGLE_BIT_31);
+ bigOffset = NB.decodeInt64(largeOffsets, bigOffsetPos * 8);
+ }
+ result.setValues(packId, bigOffset);
+ return;
+ }
+ result.setValues(packId, offset);
+ }
+
+ long getMemorySize() {
+ return (long) byteArrayLengh(offsets)
+ + byteArrayLengh(largeOffsets);
+ }
+ }
+
+ /**
+ * Combines the fanout and oid list chunks, to lookup Oids with an efficient
+ * binary search
+ */
+ private static class OidLookup {
+
+ private static final int FANOUT = 256;
+
+ private final int hashLength;
+
+ private final int[] fanoutTable;
+
+ private final byte[] oidLookup;
+
+ /**
+ * Initialize the MultiPackIndexIndex.
+ *
+ * @param hashLength
+ * length of object hash.
+ * @param oidFanout
+ * content of OID Fanout Chunk.
+ * @param oidLookup
+ * content of OID Lookup Chunk.
+ * @throws MultiPackIndexFormatException
+ * MultiPackIndex file's format is different from we
+ * expected.
+ */
+ OidLookup(int hashLength, @NonNull byte[] oidFanout,
+ @NonNull byte[] oidLookup)
+ throws MultiPackIndexFormatException {
+ this.hashLength = hashLength;
+ this.oidLookup = oidLookup;
+
+ int[] table = new int[FANOUT];
+ long uint32;
+ for (int k = 0; k < table.length; k++) {
+ uint32 = NB.decodeUInt32(oidFanout, k * 4);
+ if (uint32 > Integer.MAX_VALUE) {
+ throw new MultiPackIndexFormatException(
+ JGitText.get().multiPackIndexFileIsTooLargeForJgit);
+ }
+ table[k] = (int) uint32;
+ }
+ this.fanoutTable = table;
+ }
+
+ /**
+ * Find the position in the MultiPackIndex file of the specified id.
+ *
+ * @param id
+ * the id for which the multi-pack-index position will be
+ * found.
+ * @return the MultiPackIndex position or -1 if the object was not
+ * found.
+ */
+ int findMultiPackIndexPosition(AnyObjectId id) {
+ int levelOne = id.getFirstByte();
+ int high = fanoutTable[levelOne];
+ int low = 0;
+ if (levelOne > 0) {
+ low = fanoutTable[levelOne - 1];
+ }
+ while (low < high) {
+ int mid = (low + high) >>> 1;
+ int cmp = id.compareTo(oidLookup, hashLength * mid);
+ if (cmp < 0) {
+ high = mid;
+ } else if (cmp == 0) {
+ return mid;
+ } else {
+ low = mid + 1;
+ }
+ }
+ return -1;
+ }
+
+ void resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
+ int matchLimit) {
+ if (matches.size() >= matchLimit) {
+ return;
+ }
+
+ if (oidLookup.length == 0) {
+ return;
+ }
+
+ int high = fanoutTable[id.getFirstByte()];
+ int low = id.getFirstByte() == 0 ? 0
+ : fanoutTable[id.getFirstByte() - 1];
+ do {
+ int p = (low + high) >>> 1;
+ int cmp = id.prefixCompare(oidLookup, idOffset(p));
+ if (cmp < 0) {
+ high = p;
+ continue;
+ }
+
+ if (cmp > 0) {
+ low = p + 1;
+ continue;
+ }
+
+ // Got a match.
+ // We may have landed in the middle of the matches. Move
+ // backwards to the start of matches, then walk forwards.
+ while (0 < p
+ && id.prefixCompare(oidLookup, idOffset(p - 1)) == 0) {
+ p--;
+ }
+ while (p < high && id.prefixCompare(oidLookup, idOffset(p)) == 0
+ && matches.size() < matchLimit) {
+ matches.add(ObjectId.fromRaw(oidLookup, idOffset(p)));
+ p++;
+ }
+ return;
+ } while (low < high);
+ }
+
+ private int idOffset(int position) {
+ return position * hashLength;
+ }
+
+ long getMemorySize() {
+ return 4L + byteArrayLengh(oidLookup) + (FANOUT * 4);
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java
new file mode 100644
index 0000000000..b42c821a44
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/MultiPackIndexWriter.java
@@ -0,0 +1,428 @@
+/*
+ * 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.midx;
+
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.CHUNK_LOOKUP_WIDTH;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_LARGEOFFSETS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OBJECTOFFSETS;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDFANOUT;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_OIDLOOKUP;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_PACKNAMES;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_CHUNKID_REVINDEX;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_SIGNATURE;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MIDX_VERSION;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.MULTIPACK_INDEX_FANOUT_SIZE;
+import static org.eclipse.jgit.internal.storage.midx.MultiPackIndexConstants.OID_HASH_VERSION;
+import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.file.PackIndex;
+import org.eclipse.jgit.internal.storage.io.CancellableDigestOutputStream;
+import org.eclipse.jgit.internal.storage.midx.PackIndexMerger.MidxMutableEntry;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.util.NB;
+
+/**
+ * Writes a collection of indexes as a multipack index.
+ * <p>
+ * See <a href=
+ * "https://git-scm.com/docs/pack-format#_multi_pack_index_midx_files_have_the_following_format">multipack
+ * index format spec</a>
+ *
+ * @since 7.2
+ */
+public class MultiPackIndexWriter {
+
+ private static final int LIMIT_31_BITS = (1 << 31) - 1;
+
+ private static final int MIDX_HEADER_SIZE = 12;
+
+ /**
+ * Writes the inputs in the multipack index format in the outputStream.
+ *
+ * @param monitor
+ * progress monitor
+ * @param outputStream
+ * stream to write the multipack index file
+ * @param inputs
+ * pairs of name and index for each pack to include in the
+ * multipack index.
+ * @return bytes written into the stream
+ * @throws IOException
+ * Error writing to the stream
+ */
+ public long write(ProgressMonitor monitor, OutputStream outputStream,
+ Map<String, PackIndex> inputs) throws IOException {
+ PackIndexMerger data = new PackIndexMerger(inputs);
+
+ // List of chunks in the order they need to be written
+ List<ChunkHeader> chunkHeaders = createChunkHeaders(data);
+ long expectedSize = calculateExpectedSize(chunkHeaders);
+ try (CancellableDigestOutputStream out = new CancellableDigestOutputStream(
+ monitor, outputStream)) {
+ writeHeader(out, chunkHeaders.size(), data.getPackCount());
+ writeChunkLookup(out, chunkHeaders);
+
+ WriteContext ctx = new WriteContext(out, data);
+ for (ChunkHeader chunk : chunkHeaders) {
+ chunk.writerFn.write(ctx);
+ }
+ writeCheckSum(out);
+ if (expectedSize != out.length()) {
+ throw new IllegalStateException(String.format(
+ JGitText.get().multiPackIndexUnexpectedSize,
+ Long.valueOf(expectedSize),
+ Long.valueOf(out.length())));
+ }
+ return expectedSize;
+ } catch (InterruptedIOException e) {
+ throw new IOException(JGitText.get().multiPackIndexWritingCancelled,
+ e);
+ }
+ }
+
+ private static long calculateExpectedSize(List<ChunkHeader> chunks) {
+ int chunkLookup = (chunks.size() + 1) * CHUNK_LOOKUP_WIDTH;
+ long chunkContent = chunks.stream().mapToLong(c -> c.size).sum();
+ return /* header */ 12 + chunkLookup + chunkContent + /* CRC */ 20;
+ }
+
+ private List<ChunkHeader> createChunkHeaders(PackIndexMerger data) {
+ List<ChunkHeader> chunkHeaders = new ArrayList<>();
+ chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_OIDFANOUT,
+ MULTIPACK_INDEX_FANOUT_SIZE, this::writeFanoutTable));
+ chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_OIDLOOKUP,
+ (long) data.getUniqueObjectCount() * OBJECT_ID_LENGTH,
+ this::writeOidLookUp));
+ chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_OBJECTOFFSETS,
+ 8L * data.getUniqueObjectCount(), this::writeObjectOffsets));
+ if (data.needsLargeOffsetsChunk()) {
+ chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_LARGEOFFSETS,
+ 8L * data.getOffsetsOver31BitsCount(),
+ this::writeObjectLargeOffsets));
+ }
+ chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_REVINDEX,
+ 4L * data.getUniqueObjectCount(), this::writeRidx));
+
+ int packNamesSize = data.getPackNames().stream()
+ .mapToInt(String::length).map(i -> i + 1 /* null at the end */)
+ .sum();
+ chunkHeaders.add(new ChunkHeader(MIDX_CHUNKID_PACKNAMES, packNamesSize,
+ this::writePackfileNames));
+ return chunkHeaders;
+ }
+
+ /**
+ * Write the first 12 bytes of the multipack index.
+ * <p>
+ * These bytes include things like magic number, version, number of
+ * chunks...
+ *
+ * @param out
+ * output stream to write
+ * @param numChunks
+ * number of chunks this multipack index is going to have
+ * @param packCount
+ * number of packs covered by this multipack index
+ * @throws IOException
+ * error writing to the output stream
+ */
+ private void writeHeader(CancellableDigestOutputStream out, int numChunks,
+ int packCount) throws IOException {
+ byte[] headerBuffer = new byte[MIDX_HEADER_SIZE];
+ NB.encodeInt32(headerBuffer, 0, MIDX_SIGNATURE);
+ byte[] buff = { MIDX_VERSION, OID_HASH_VERSION, (byte) numChunks,
+ (byte) 0 };
+ System.arraycopy(buff, 0, headerBuffer, 4, 4);
+ NB.encodeInt32(headerBuffer, 8, packCount);
+ out.write(headerBuffer, 0, headerBuffer.length);
+ out.flush();
+ }
+
+ /**
+ * Write a table of "chunkId, start-offset", with a special value "0,
+ * end-of-previous_chunk", to mark the end.
+ *
+ * @param out
+ * output stream to write
+ * @param chunkHeaders
+ * list of chunks in the order they are expected to be written
+ * @throws IOException
+ * error writing to the output stream
+ */
+ private void writeChunkLookup(CancellableDigestOutputStream out,
+ List<ChunkHeader> chunkHeaders) throws IOException {
+
+ // first chunk will start at header + this lookup block
+ long chunkStart = MIDX_HEADER_SIZE
+ + (long) (chunkHeaders.size() + 1) * CHUNK_LOOKUP_WIDTH;
+ byte[] chunkEntry = new byte[CHUNK_LOOKUP_WIDTH];
+ for (ChunkHeader chunkHeader : chunkHeaders) {
+ NB.encodeInt32(chunkEntry, 0, chunkHeader.chunkId);
+ NB.encodeInt64(chunkEntry, 4, chunkStart);
+ out.write(chunkEntry);
+ chunkStart += chunkHeader.size;
+ }
+ // Terminating label for the block
+ // (chunkid 0, offset where the next block would start)
+ NB.encodeInt32(chunkEntry, 0, 0);
+ NB.encodeInt64(chunkEntry, 4, chunkStart);
+ out.write(chunkEntry);
+ }
+
+ /**
+ * Write the fanout table for the object ids
+ * <p>
+ * Table with 256 entries (one byte), where the ith entry, F[i], stores the
+ * number of OIDs with first byte at most i. Thus, F[255] stores the total
+ * number of objects.
+ *
+ * @param ctx
+ * write context
+ * @throws IOException
+ * error writing to the output stream
+ */
+
+ private void writeFanoutTable(WriteContext ctx) throws IOException {
+ byte[] tmp = new byte[4];
+ int[] fanout = new int[256];
+ Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+ while (iterator.hasNext()) {
+ MidxMutableEntry e = iterator.next();
+ fanout[e.getObjectId().getFirstByte() & 0xff]++;
+ }
+ for (int i = 1; i < fanout.length; i++) {
+ fanout[i] += fanout[i - 1];
+ }
+ for (int n : fanout) {
+ NB.encodeInt32(tmp, 0, n);
+ ctx.out.write(tmp, 0, 4);
+ }
+ }
+
+ /**
+ * Write the OID lookup chunk
+ * <p>
+ * A list of OIDs in sha1 order.
+ *
+ * @param ctx
+ * write context
+ * @throws IOException
+ * error writing to the output stream
+ */
+ private void writeOidLookUp(WriteContext ctx) throws IOException {
+ byte[] tmp = new byte[OBJECT_ID_LENGTH];
+
+ Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+ while (iterator.hasNext()) {
+ MidxMutableEntry e = iterator.next();
+ e.getObjectId().copyRawTo(tmp, 0);
+ ctx.out.write(tmp, 0, OBJECT_ID_LENGTH);
+ }
+ }
+
+ /**
+ * Write the object offsets chunk
+ * <p>
+ * A list of offsets, parallel to the list of OIDs. If the offset is too
+ * large (see {@link #fitsIn31bits(long)}), this contains the position in
+ * the large offsets list (marked with a 1 in the most significant bit).
+ *
+ * @param ctx
+ * write context
+ * @throws IOException
+ * error writing to the output stream
+ */
+ private void writeObjectOffsets(WriteContext ctx) throws IOException {
+ byte[] entry = new byte[8];
+ Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+ while (iterator.hasNext()) {
+ MidxMutableEntry e = iterator.next();
+ NB.encodeInt32(entry, 0, e.getPackId());
+ if (!ctx.data.needsLargeOffsetsChunk()
+ || fitsIn31bits(e.getOffset())) {
+ NB.encodeInt32(entry, 4, (int) e.getOffset());
+ } else {
+ int offloadedPosition = ctx.largeOffsets.append(e.getOffset());
+ NB.encodeInt32(entry, 4, offloadedPosition | (1 << 31));
+ }
+ ctx.out.write(entry);
+ }
+ }
+
+ /**
+ * Writes the reverse index chunk
+ * <p>
+ * This stores the position of the objects in the main index, ordered first
+ * by pack and then by offset
+ *
+ * @param ctx
+ * write context
+ * @throws IOException
+ * erorr writing to the output stream
+ */
+ private void writeRidx(WriteContext ctx) throws IOException {
+ Map<Integer, List<OffsetPosition>> packOffsets = new HashMap<>(
+ ctx.data.getPackCount());
+ // TODO(ifrade): Brute force solution loading all offsets/packs in
+ // memory. We could also iterate reverse indexes looking up
+ // their position in the midx (and discarding if the pack doesn't
+ // match).
+ Iterator<MidxMutableEntry> iterator = ctx.data.bySha1Iterator();
+ int midxPosition = 0;
+ while (iterator.hasNext()) {
+ MidxMutableEntry e = iterator.next();
+ OffsetPosition op = new OffsetPosition(e.getOffset(), midxPosition);
+ midxPosition++;
+ packOffsets.computeIfAbsent(Integer.valueOf(e.getPackId()),
+ k -> new ArrayList<>()).add(op);
+ }
+
+ for (int i = 0; i < ctx.data.getPackCount(); i++) {
+ List<OffsetPosition> offsetsForPack = packOffsets
+ .get(Integer.valueOf(i));
+ if (offsetsForPack == null) {
+ continue;
+ }
+ offsetsForPack.sort(Comparator.comparing(OffsetPosition::offset));
+ byte[] ridxForPack = new byte[4 * offsetsForPack.size()];
+ for (int j = 0; j < offsetsForPack.size(); j++) {
+ NB.encodeInt32(ridxForPack, j * 4,
+ offsetsForPack.get(j).position);
+ }
+ ctx.out.write(ridxForPack);
+ }
+ }
+
+ /**
+ * Write the large offset chunk
+ * <p>
+ * A list of large offsets (long). The regular offset chunk will point to a
+ * position here.
+ *
+ * @param ctx
+ * writer context
+ * @throws IOException
+ * error writing to the output stream
+ */
+ private void writeObjectLargeOffsets(WriteContext ctx) throws IOException {
+ ctx.out.write(ctx.largeOffsets.offsets, 0,
+ ctx.largeOffsets.bytePosition);
+ }
+
+ /**
+ * Write the list of packfiles chunk
+ * <p>
+ * List of packfiles (in lexicographical order) with an \0 at the end
+ *
+ * @param ctx
+ * writer context
+ * @throws IOException
+ * error writing to the output stream
+ */
+ private void writePackfileNames(WriteContext ctx) throws IOException {
+ for (String packName : ctx.data.getPackNames()) {
+ // Spec doesn't talk about encoding.
+ ctx.out.write(packName.getBytes(StandardCharsets.UTF_8));
+ ctx.out.write(0);
+ }
+ }
+
+ /**
+ * Write final checksum of the data written to the stream
+ *
+ * @param out
+ * output stream used to write
+ * @throws IOException
+ * error writing to the output stream
+ */
+ private void writeCheckSum(CancellableDigestOutputStream out)
+ throws IOException {
+ out.write(out.getDigest());
+ out.flush();
+ }
+
+ private record OffsetPosition(long offset, int position) {
+ }
+
+ /**
+ * If there is at least one offset value larger than 2^32-1, then the large
+ * offset chunk must exist, and offsets larger than 2^31-1 must be stored in
+ * it instead
+ *
+ * @param offset
+ * object offset
+ *
+ * @return true if the offset fits in 31 bits
+ */
+ private static boolean fitsIn31bits(long offset) {
+ return offset <= LIMIT_31_BITS;
+ }
+
+ private static class LargeOffsets {
+ private final byte[] offsets;
+
+ private int bytePosition;
+
+ LargeOffsets(int largeOffsetsCount) {
+ offsets = new byte[largeOffsetsCount * 8];
+ bytePosition = 0;
+ }
+
+ /**
+ * Add an offset to the large offset chunk
+ *
+ * @param largeOffset
+ * a large offset
+ * @return the position of the just inserted offset (as in number of
+ * offsets, NOT in bytes)
+ */
+ int append(long largeOffset) {
+ int at = bytePosition;
+ NB.encodeInt64(offsets, at, largeOffset);
+ bytePosition += 8;
+ return at / 8;
+ }
+ }
+
+ private record ChunkHeader(int chunkId, long size, ChunkWriter writerFn) {
+ }
+
+ @FunctionalInterface
+ private interface ChunkWriter {
+ void write(WriteContext ctx) throws IOException;
+ }
+
+ private static class WriteContext {
+ final CancellableDigestOutputStream out;
+
+ final PackIndexMerger data;
+
+ final LargeOffsets largeOffsets;
+
+ WriteContext(CancellableDigestOutputStream out, PackIndexMerger data) {
+ this.out = out;
+ this.data = data;
+ this.largeOffsets = new LargeOffsets(
+ data.getOffsetsOver31BitsCount());
+ }
+ }
+}
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
new file mode 100644
index 0000000000..f23665849e
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/midx/PackIndexMerger.java
@@ -0,0 +1,337 @@
+/*
+ * 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.midx;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+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;
+import org.eclipse.jgit.lib.MutableObjectId;
+
+/**
+ * Collect the stats and offers an iterator over the union of n-pack indexes.
+ * <p>
+ * The multipack index is a list of (sha1, packid, offset) ordered by sha1. We
+ * can build it from the individual pack indexes (sha1, offset) ordered by sha1,
+ * with a simple merge ignoring duplicates.
+ * <p>
+ * This class encapsulates the merging logic and precalculates the stats that
+ * the index needs (like total count of objects). To limit memory consumption,
+ * it does the merge as it goes during the iteration and iterators use mutable
+ * entries. The stats of the combined index are calculated in an iteration at
+ * construction time.
+ */
+class PackIndexMerger {
+
+ private static final int LIMIT_31_BITS = (1 << 31) - 1;
+
+ private static final long LIMIT_32_BITS = (1L << 32) - 1;
+
+ /**
+ * Object returned by the iterator.
+ * <p>
+ * The iterator returns (on each next()) the same instance with different
+ * values, to avoid allocating many short-lived objects. Callers should not
+ * keep a reference to that returned value.
+ */
+ static class MidxMutableEntry {
+ // The object id
+ private final MutableObjectId oid = new MutableObjectId();
+
+ // Position of the pack in the ordered list of pack in this merger
+ private int packId;
+
+ // Offset in its pack
+ private long offset;
+
+ public AnyObjectId getObjectId() {
+ return oid;
+ }
+
+ public int getPackId() {
+ return packId;
+ }
+
+ public long getOffset() {
+ return offset;
+ }
+
+ /**
+ * Copy values from another mutable entry
+ *
+ * @param packId
+ * packId
+ * @param other
+ * another mutable entry
+ */
+ private void fill(int packId, PackIndex.MutableEntry other) {
+ other.copyOidTo(oid);
+ this.packId = packId;
+ this.offset = other.getOffset();
+ }
+ }
+
+ private final List<String> packNames;
+
+ private final List<PackIndex> indexes;
+
+ private final boolean needsLargeOffsetsChunk;
+
+ private final int offsetsOver31BitsCount;
+
+ private final int uniqueObjectCount;
+
+ PackIndexMerger(Map<String, PackIndex> packs) {
+ this.packNames = packs.keySet().stream().sorted()
+ .collect(Collectors.toUnmodifiableList());
+
+ this.indexes = packNames.stream().map(packs::get)
+ .collect(Collectors.toUnmodifiableList());
+
+ // Iterate for duplicates
+ int objectCount = 0;
+ boolean hasLargeOffsets = false;
+ int over31bits = 0;
+ MutableObjectId lastSeen = new MutableObjectId();
+ MultiIndexIterator it = new MultiIndexIterator(indexes);
+ while (it.hasNext()) {
+ MidxMutableEntry entry = it.next();
+ if (lastSeen.equals(entry.oid)) {
+ continue;
+ }
+ // If there is at least one offset value larger than 2^32-1, then
+ // the large offset chunk must exist, and offsets larger than
+ // 2^31-1 must be stored in it instead
+ if (entry.offset > LIMIT_32_BITS) {
+ hasLargeOffsets = true;
+ }
+ if (entry.offset > LIMIT_31_BITS) {
+ over31bits++;
+ }
+
+ lastSeen.fromObjectId(entry.oid);
+ objectCount++;
+ }
+ uniqueObjectCount = objectCount;
+ offsetsOver31BitsCount = over31bits;
+ needsLargeOffsetsChunk = hasLargeOffsets;
+ }
+
+ /**
+ * Object count of the merged index (i.e. without duplicates)
+ *
+ * @return object count of the merged index
+ */
+ int getUniqueObjectCount() {
+ return uniqueObjectCount;
+ }
+
+ /**
+ * If any object in any of the indexes has an offset over 2^32-1
+ *
+ * @return true if there is any object with offset > 2^32 -1
+ */
+ boolean needsLargeOffsetsChunk() {
+ return needsLargeOffsetsChunk;
+ }
+
+ /**
+ * How many object have offsets over 2^31-1
+ * <p>
+ * Per multipack index spec, IF there is large offset chunk, all this
+ * offsets should be there.
+ *
+ * @return number of objects with offsets over 2^31-1
+ */
+ int getOffsetsOver31BitsCount() {
+ return offsetsOver31BitsCount;
+ }
+
+ /**
+ * List of pack names in alphabetical order.
+ * <p>
+ * Order matters: In case of duplicates, the multipack index prefers the
+ * first package with it. This is in the same order we are using to
+ * prioritize duplicates.
+ *
+ * @return List of pack names, in the order used by the merge.
+ */
+ List<String> getPackNames() {
+ return packNames;
+ }
+
+ /**
+ * How many packs are being merged
+ *
+ * @return count of packs merged
+ */
+ int getPackCount() {
+ return packNames.size();
+ }
+
+ /**
+ * Iterator over the merged indexes in sha1 order without duplicates
+ * <p>
+ * The returned entry in the iterator is mutable, callers should NOT keep a
+ * reference to it.
+ *
+ * @return an iterator in sha1 order without duplicates.
+ */
+ Iterator<MidxMutableEntry> bySha1Iterator() {
+ return new DedupMultiIndexIterator(new MultiIndexIterator(indexes),
+ getUniqueObjectCount());
+ }
+
+ /**
+ * For testing. Iterate all entries, not skipping duplicates (stable order)
+ *
+ * @return an iterator of all objects in sha1 order, including duplicates.
+ */
+ Iterator<MidxMutableEntry> rawIterator() {
+ return new MultiIndexIterator(indexes);
+ }
+
+ /**
+ * Iterator over n-indexes in ObjectId order.
+ * <p>
+ * It returns duplicates if the same object id is in different indexes. Wrap
+ * it with {@link DedupMultiIndexIterator (Iterator, int)} to avoid
+ * duplicates.
+ */
+ private static final class MultiIndexIterator
+ implements Iterator<MidxMutableEntry> {
+
+ private final List<PackIndexPeekIterator> indexIterators;
+
+ private final MidxMutableEntry mutableEntry = new MidxMutableEntry();
+
+ MultiIndexIterator(List<PackIndex> indexes) {
+ this.indexIterators = new ArrayList<>(indexes.size());
+ for (int i = 0; i < indexes.size(); i++) {
+ PackIndexPeekIterator it = new PackIndexPeekIterator(i,
+ indexes.get(i));
+ // Position in the first element
+ if (it.next() != null) {
+ indexIterators.add(it);
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !indexIterators.isEmpty();
+ }
+
+ @Override
+ public MidxMutableEntry next() {
+ PackIndexPeekIterator winner = null;
+ for (int index = 0; index < indexIterators.size(); index++) {
+ PackIndexPeekIterator current = indexIterators.get(index);
+ if (winner == null
+ || current.peek().compareBySha1To(winner.peek()) < 0) {
+ winner = current;
+ }
+ }
+
+ if (winner == null) {
+ throw new NoSuchElementException();
+ }
+
+ mutableEntry.fill(winner.getPackId(), winner.peek());
+ if (winner.next() == null) {
+ indexIterators.remove(winner);
+ };
+ return mutableEntry;
+ }
+ }
+
+ private static class DedupMultiIndexIterator
+ implements Iterator<MidxMutableEntry> {
+ private final MultiIndexIterator src;
+
+ private int remaining;
+
+ private final MutableObjectId lastOid = new MutableObjectId();
+
+ DedupMultiIndexIterator(MultiIndexIterator src, int totalCount) {
+ this.src = src;
+ this.remaining = totalCount;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return remaining > 0;
+ }
+
+ @Override
+ public MidxMutableEntry next() {
+ MidxMutableEntry next = src.next();
+ while (next != null && lastOid.equals(next.oid)) {
+ next = src.next();
+ }
+
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+
+ lastOid.fromObjectId(next.oid);
+ remaining--;
+ return next;
+ }
+ }
+
+ /**
+ * Convenience around the PackIndex iterator to read the current value
+ * multiple times without consuming it.
+ * <p>
+ * This is used to merge indexes in the multipack index, where we need to
+ * compare the current value between indexes multiple times to find the
+ * next.
+ * <p>
+ * We could also implement this keeping the position (int) and
+ * MutableEntry#getObjectId, but that would create an ObjectId per entry.
+ * This implementation reuses the MutableEntry and avoid instantiations.
+ */
+ // Visible for testing
+ static class PackIndexPeekIterator {
+ private final Iterator<PackIndex.MutableEntry> it;
+
+ private final int packId;
+
+ PackIndex.MutableEntry current;
+
+ PackIndexPeekIterator(int packId, PackIndex index) {
+ it = index.iterator();
+ this.packId = packId;
+ }
+
+ PackIndex.MutableEntry next() {
+ if (it.hasNext()) {
+ current = it.next();
+ } else {
+ current = null;
+ }
+ return current;
+ }
+
+ PackIndex.MutableEntry peek() {
+ return current;
+ }
+
+ int getPackId() {
+ return packId;
+ }
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java
index e6daaeaca9..d5bb5f2e2f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackExt.java
@@ -36,7 +36,10 @@ public enum PackExt {
COMMIT_GRAPH("graph"), //$NON-NLS-1$
/** An object size index. */
- OBJECT_SIZE_INDEX("objsize"); //$NON-NLS-1$
+ OBJECT_SIZE_INDEX("objsize"), //$NON-NLS-1$
+
+ /** Multi pack index */
+ MULTI_PACK_INDEX("midx"); //$NON-NLS-1$
private final String ext;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java
index dabc1f0c5f..bf87c4c9d6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java
@@ -14,6 +14,7 @@ import static org.eclipse.jgit.internal.storage.file.PackBitmapIndex.FLAG_REUSE;
import static org.eclipse.jgit.revwalk.RevFlag.SEEN;
import java.io.IOException;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -28,16 +29,16 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.revwalk.AddUnseenToBitmapFilter;
import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl;
+import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl.CompressedBitmap;
import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder;
import org.eclipse.jgit.internal.storage.file.PackBitmapIndexRemapper;
-import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl.CompressedBitmap;
import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
import org.eclipse.jgit.revwalk.BitmapWalker;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -99,10 +100,10 @@ class PackWriterBitmapPreparer {
this.excessiveBranchCount = config.getBitmapExcessiveBranchCount();
this.excessiveBranchTipCount = Math.max(excessiveBranchCount,
config.getBitmapExcessiveBranchTipCount());
- long now = SystemReader.getInstance().getCurrentTime();
+ Instant now = SystemReader.getInstance().now();
long ageInSeconds = (long) config.getBitmapInactiveBranchAgeInDays()
* DAY_IN_SECONDS;
- this.inactiveBranchTimestamp = (now / 1000) - ageInSeconds;
+ this.inactiveBranchTimestamp = now.getEpochSecond() - ageInSeconds;
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
index d07713db8e..e9ff02700d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockReader.java
@@ -32,6 +32,8 @@ import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
@@ -245,9 +247,9 @@ class BlockReader {
private PersonIdent readPersonIdent() {
String name = readValueString();
String email = readValueString();
- long ms = readVarint64() * 1000;
- int tz = readInt16();
- return new PersonIdent(name, email, ms, tz);
+ long epochSeconds = readVarint64();
+ ZoneOffset tz = ZoneOffset.ofTotalSeconds(readInt16() * 60);
+ return new PersonIdent(name, email, Instant.ofEpochSecond(epochSeconds), tz);
}
void readBlock(BlockSource src, long pos, int fileBlockSize)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockWriter.java
index c70f2e4914..0ddfa5798a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/BlockWriter.java
@@ -524,8 +524,8 @@ class BlockWriter {
this.oldId = oldId;
this.newId = newId;
- this.timeSecs = who.getWhen().getTime() / 1000L;
- this.tz = (short) who.getTimeZoneOffset();
+ this.timeSecs = who.getWhenAsInstant().getEpochSecond();
+ this.tz = (short) (who.getZoneOffset().getTotalSeconds() / 60);
this.name = who.getName().getBytes(UTF_8);
this.email = who.getEmailAddress().getBytes(UTF_8);
this.msg = message.getBytes(UTF_8);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java
index 3c4bc75792..7e5f4ebbd4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/ReftableCompactor.java
@@ -12,6 +12,7 @@ package org.eclipse.jgit.internal.storage.reftable;
import java.io.IOException;
import java.io.OutputStream;
+import java.time.Instant;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
@@ -28,20 +29,26 @@ import org.eclipse.jgit.lib.ReflogEntry;
* to shadow any lower reftable that may have the reference present.
* <p>
* By default all log entries within the range defined by
- * {@link #setReflogExpireMinUpdateIndex(long)} and {@link #setReflogExpireMaxUpdateIndex(long)} are
- * copied, even if no references in the output file match the log records.
- * Callers may truncate the log to a more recent time horizon with
- * {@link #setReflogExpireOldestReflogTimeMillis(long)}, or disable the log altogether with
- * {@code setOldestReflogTimeMillis(Long.MAX_VALUE)}.
+ * {@link #setReflogExpireMinUpdateIndex(long)} and
+ * {@link #setReflogExpireMaxUpdateIndex(long)} are copied, even if no
+ * references in the output file match the log records. Callers may truncate the
+ * log to a more recent time horizon with
+ * {@link #setReflogExpireOlderThan(Instant)}, or disable the log
+ * altogether with {@code setReflogExpireOldestReflogTime(Instant.MAX)}.
*/
public class ReftableCompactor {
private final ReftableWriter writer;
+
private final ArrayDeque<ReftableReader> tables = new ArrayDeque<>();
private boolean includeDeletes;
+
private long reflogExpireMinUpdateIndex = 0;
+
private long reflogExpireMaxUpdateIndex = Long.MAX_VALUE;
- private long reflogExpireOldestReflogTimeMillis;
+
+ private Instant reflogExpireOldestReflogTime = Instant.EPOCH;
+
private Stats stats;
/**
@@ -122,9 +129,29 @@ public class ReftableCompactor {
* entries that predate {@code timeMillis} will be discarded.
* Specified in Java standard milliseconds since the epoch.
* @return {@code this}
+ *
+ * @deprecated Use {@link #setReflogExpireOlderThan(Instant)} instead
+ */
+ @Deprecated(since="7.3")
+ public ReftableCompactor setReflogExpireOldestReflogTimeMillis(
+ long timeMillis) {
+ return setReflogExpireOlderThan(timeMillis == Long.MAX_VALUE
+ ? Instant.MAX
+ : Instant.ofEpochMilli(timeMillis));
+ }
+
+ /**
+ * Set oldest reflog time to preserve.
+ *
+ * @param cutTime
+ * oldest log time to preserve. Entries whose timestamps are
+ * {@code >= cutTime} will be copied into the output file. Log
+ * entries that predate {@code cutTime} will be discarded.
+ * @return {@code this}
*/
- public ReftableCompactor setReflogExpireOldestReflogTimeMillis(long timeMillis) {
- reflogExpireOldestReflogTimeMillis = timeMillis;
+ public ReftableCompactor setReflogExpireOlderThan(
+ Instant cutTime) {
+ reflogExpireOldestReflogTime = cutTime;
return this;
}
@@ -182,14 +209,15 @@ public class ReftableCompactor {
}
private void mergeLogs(MergedReftable mr) throws IOException {
- if (reflogExpireOldestReflogTimeMillis == Long.MAX_VALUE) {
+ if (reflogExpireOldestReflogTime == Instant.MAX) {
return;
}
try (LogCursor lc = mr.allLogs()) {
while (lc.next()) {
long updateIndex = lc.getUpdateIndex();
- if (updateIndex > reflogExpireMaxUpdateIndex || updateIndex < reflogExpireMinUpdateIndex) {
+ if (updateIndex > reflogExpireMaxUpdateIndex
+ || updateIndex < reflogExpireMinUpdateIndex) {
continue;
}
@@ -203,14 +231,9 @@ public class ReftableCompactor {
}
PersonIdent who = log.getWho();
- if (who.getWhen().getTime() >= reflogExpireOldestReflogTimeMillis) {
- writer.writeLog(
- refName,
- updateIndex,
- who,
- log.getOldId(),
- log.getNewId(),
- log.getComment());
+ if (who.getWhenAsInstant().compareTo(reflogExpireOldestReflogTime) >= 0) {
+ writer.writeLog(refName, updateIndex, who, log.getOldId(),
+ log.getNewId(), log.getComment());
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
index e15c7af932..7921052aaa 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BranchConfig.java
@@ -187,8 +187,7 @@ public class BranchConfig {
* @since 4.5
*/
public BranchRebaseMode getRebaseMode() {
- return config.getEnum(BranchRebaseMode.values(),
- ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
+ return config.getEnum(ConfigConstants.CONFIG_BRANCH_SECTION, branchName,
ConfigConstants.CONFIG_KEY_REBASE, BranchRebaseMode.NONE);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
index f701a41d67..b1ba5dfa28 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitConfig.java
@@ -119,7 +119,7 @@ public class CommitConfig {
if (!StringUtils.isEmptyOrNull(comment)) {
if ("auto".equalsIgnoreCase(comment)) { //$NON-NLS-1$
autoCommentChar = true;
- } else {
+ } else if (comment != null) {
char first = comment.charAt(0);
if (first > ' ' && first < 127) {
commentCharacter = first;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
index 07c5fa4500..345cb22f80 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
@@ -34,6 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.events.ConfigChangedEvent;
import org.eclipse.jgit.events.ConfigChangedListener;
@@ -254,9 +255,8 @@ public class Config {
* default value to return if no value was present.
* @return an integer value from the configuration, or defaultValue.
*/
- public int getInt(final String section, final String name,
- final int defaultValue) {
- return typedGetter.getInt(this, section, null, name, defaultValue);
+ public int getInt(String section, String name, int defaultValue) {
+ return getInt(section, null, name, defaultValue);
}
/**
@@ -264,6 +264,23 @@ public class Config {
*
* @param section
* section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getInt(String section, String name) {
+ return getInt(section, null, name);
+ }
+
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
* @param subsection
* subsection name, such a remote or branch name.
* @param name
@@ -272,10 +289,30 @@ public class Config {
* default value to return if no value was present.
* @return an integer value from the configuration, or defaultValue.
*/
- public int getInt(final String section, String subsection,
- final String name, final int defaultValue) {
+ public int getInt(String section, String subsection, String name,
+ int defaultValue) {
+ Integer v = typedGetter.getInt(this, section, subsection, name,
+ Integer.valueOf(defaultValue));
+ return v == null ? defaultValue : v.intValue();
+ }
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getInt(String section, String subsection, String name) {
return typedGetter.getInt(this, section, subsection, name,
- defaultValue);
+ null);
}
/**
@@ -297,8 +334,30 @@ public class Config {
*/
public int getIntInRange(String section, String name, int minValue,
int maxValue, int defaultValue) {
- return typedGetter.getIntInRange(this, section, null, name, minValue,
- maxValue, defaultValue);
+ return getIntInRange(section, null, name,
+ minValue, maxValue, defaultValue);
+ }
+
+ /**
+ * Obtain an integer value from the configuration which must be inside given
+ * range.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @param minValue
+ * minimum value
+ * @param maxValue
+ * maximum value
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getIntInRange(String section, String name, int minValue,
+ int maxValue) {
+ return getIntInRange(section, null, name, minValue, maxValue);
}
/**
@@ -322,8 +381,34 @@ public class Config {
*/
public int getIntInRange(String section, String subsection, String name,
int minValue, int maxValue, int defaultValue) {
+ Integer v = typedGetter.getIntInRange(this, section, subsection, name,
+ minValue, maxValue, Integer.valueOf(defaultValue));
+ return v == null ? defaultValue : v.intValue();
+ }
+
+ /**
+ * Obtain an integer value from the configuration which must be inside given
+ * range.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param minValue
+ * minimum value
+ * @param maxValue
+ * maximum value
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Integer getIntInRange(String section, String subsection, String name,
+ int minValue, int maxValue) {
return typedGetter.getIntInRange(this, section, subsection, name,
- minValue, maxValue, defaultValue);
+ minValue, maxValue, null);
}
/**
@@ -338,7 +423,23 @@ public class Config {
* @return an integer value from the configuration, or defaultValue.
*/
public long getLong(String section, String name, long defaultValue) {
- return typedGetter.getLong(this, section, null, name, defaultValue);
+ return getLong(section, null, name, defaultValue);
+ }
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Long getLong(String section, String name) {
+ return getLong(section, null, name);
}
/**
@@ -355,9 +456,28 @@ public class Config {
* @return an integer value from the configuration, or defaultValue.
*/
public long getLong(final String section, String subsection,
- final String name, final long defaultValue) {
- return typedGetter.getLong(this, section, subsection, name,
- defaultValue);
+ String name, long defaultValue) {
+ Long v = typedGetter.getLong(this, section, subsection, name,
+ Long.valueOf(defaultValue));
+ return v == null ? defaultValue : v.longValue();
+ }
+
+ /**
+ * Obtain an integer value from the configuration.
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return an integer value from the configuration, or {@code null} if not
+ * set.
+ * @since 7.2
+ */
+ @Nullable
+ public Long getLong(String section, String subsection, String name) {
+ return typedGetter.getLong(this, section, subsection, name, null);
}
/**
@@ -372,9 +492,26 @@ public class Config {
* @return true if any value or defaultValue is true, false for missing or
* explicit false
*/
- public boolean getBoolean(final String section, final String name,
- final boolean defaultValue) {
- return typedGetter.getBoolean(this, section, null, name, defaultValue);
+ public boolean getBoolean(String section, String name,
+ boolean defaultValue) {
+ Boolean v = typedGetter.getBoolean(this, section, null, name,
+ Boolean.valueOf(defaultValue));
+ return v == null ? defaultValue : v.booleanValue();
+ }
+
+ /**
+ * Get a boolean value from the git config
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param name
+ * name of the key to get.
+ * @return configured boolean value, or {@code null} if not set.
+ * @since 7.2
+ */
+ @Nullable
+ public Boolean getBoolean(String section, String name) {
+ return getBoolean(section, null, name);
}
/**
@@ -391,10 +528,28 @@ public class Config {
* @return true if any value or defaultValue is true, false for missing or
* explicit false
*/
- public boolean getBoolean(final String section, String subsection,
- final String name, final boolean defaultValue) {
- return typedGetter.getBoolean(this, section, subsection, name,
- defaultValue);
+ public boolean getBoolean(String section, String subsection, String name,
+ boolean defaultValue) {
+ Boolean v = typedGetter.getBoolean(this, section, subsection, name,
+ Boolean.valueOf(defaultValue));
+ return v == null ? defaultValue : v.booleanValue();
+ }
+
+ /**
+ * Get a boolean value from the git config
+ *
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return configured boolean value, or {@code null} if not set.
+ * @since 7.2
+ */
+ @Nullable
+ public Boolean getBoolean(String section, String subsection, String name) {
+ return typedGetter.getBoolean(this, section, subsection, name, null);
}
/**
@@ -412,8 +567,8 @@ public class Config {
* default value to return if no value was present.
* @return the selected enumeration value, or {@code defaultValue}.
*/
- public <T extends Enum<?>> T getEnum(final String section,
- final String subsection, final String name, final T defaultValue) {
+ public <T extends Enum<?>> T getEnum(String section, String subsection,
+ String name, @NonNull T defaultValue) {
final T[] all = allValuesOf(defaultValue);
return typedGetter.getEnum(this, all, section, subsection, name,
defaultValue);
@@ -448,14 +603,41 @@ public class Config {
* @param defaultValue
* default value to return if no value was present.
* @return the selected enumeration value, or {@code defaultValue}.
+ * @deprecated use {@link #getEnum(String, String, String, Enum)} or
+ * {{@link #getEnum(Enum[], String, String, String)}} instead.
*/
- public <T extends Enum<?>> T getEnum(final T[] all, final String section,
- final String subsection, final String name, final T defaultValue) {
+ @Nullable
+ @Deprecated
+ public <T extends Enum<?>> T getEnum(T[] all, String section,
+ String subsection, String name, @Nullable T defaultValue) {
return typedGetter.getEnum(this, all, section, subsection, name,
defaultValue);
}
/**
+ * Parse an enumeration from the configuration.
+ *
+ * @param <T>
+ * type of the returned enum
+ * @param all
+ * all possible values in the enumeration which should be
+ * recognized. Typically {@code EnumType.values()}.
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @return the selected enumeration value, or {@code null} if not set.
+ * @since 7.2
+ */
+ @Nullable
+ public <T extends Enum<?>> T getEnum(T[] all, String section,
+ String subsection, String name) {
+ return typedGetter.getEnum(this, all, section, subsection, name, null);
+ }
+
+ /**
* Get string value or null if not found.
*
* @param section
@@ -466,8 +648,8 @@ public class Config {
* the key name
* @return a String value from the config, <code>null</code> if not found
*/
- public String getString(final String section, String subsection,
- final String name) {
+ @Nullable
+ public String getString(String section, String subsection, String name) {
return getRawString(section, subsection, name);
}
@@ -526,8 +708,34 @@ public class Config {
*/
public long getTimeUnit(String section, String subsection, String name,
long defaultValue, TimeUnit wantUnit) {
+ Long v = typedGetter.getTimeUnit(this, section, subsection, name,
+ Long.valueOf(defaultValue), wantUnit);
+ return v == null ? defaultValue : v.longValue();
+
+ }
+
+ /**
+ * Parse a numerical time unit, such as "1 minute", from the configuration.
+ *
+ * @param section
+ * section the key is in.
+ * @param subsection
+ * subsection the key is in, or null if not in a subsection.
+ * @param name
+ * the key name.
+ * @param wantUnit
+ * the units of {@code defaultValue} and the return value, as
+ * well as the units to assume if the value does not contain an
+ * indication of the units.
+ * @return the value, or {@code null} if not set, expressed in
+ * {@code units}.
+ * @since 7.2
+ */
+ @Nullable
+ public Long getTimeUnit(String section, String subsection, String name,
+ TimeUnit wantUnit) {
return typedGetter.getTimeUnit(this, section, subsection, name,
- defaultValue, wantUnit);
+ null, wantUnit);
}
/**
@@ -555,8 +763,9 @@ public class Config {
* @return the {@link Path}, or {@code defaultValue} if not set
* @since 5.10
*/
+ @Nullable
public Path getPath(String section, String subsection, String name,
- @NonNull FS fs, File resolveAgainst, Path defaultValue) {
+ @NonNull FS fs, File resolveAgainst, @Nullable Path defaultValue) {
return typedGetter.getPath(this, section, subsection, name, fs,
resolveAgainst, defaultValue);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
index a57f1b714a..c4550329d3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -446,6 +446,13 @@ public final class ConfigConstants {
/** The "rebase" key */
public static final String CONFIG_KEY_REBASE = "rebase";
+ /**
+ * The "checkout" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_CHECKOUT = "checkout";
+
/** The "url" key */
public static final String CONFIG_KEY_URL = "url";
@@ -593,11 +600,21 @@ public final class ConfigConstants {
/**
* The "trustfolderstat" key in the "core" section
+ *
* @since 3.6
+ * @deprecated use {CONFIG_KEY_TRUST_STAT} instead
*/
+ @Deprecated(since = "7.2", forRemoval = true)
public static final String CONFIG_KEY_TRUSTFOLDERSTAT = "trustfolderstat";
/**
+ * The "trustfilestat" key in the "core"section
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_STAT = "truststat";
+
+ /**
* The "supportsAtomicFileCreation" key in the "core" section
*
* @since 4.5
@@ -1016,6 +1033,27 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_TRUST_LOOSE_REF_STAT = "trustLooseRefStat";
/**
+ * The "trustLooseRefStat" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_PACK_STAT = "trustPackStat";
+
+ /**
+ * The "trustLooseObjectFileStat" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_LOOSE_OBJECT_STAT = "trustLooseObjectStat";
+
+ /**
+ * The "trustTablesListStat" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_TRUST_TABLESLIST_STAT = "trustTablesListStat";
+
+ /**
* The "pack.preserveOldPacks" key
*
* @since 5.13.2
@@ -1063,4 +1101,18 @@ public final class ConfigConstants {
* @since 7.1
*/
public static final String CONFIG_KEY_LOAD_REV_INDEX_IN_PARALLEL = "loadRevIndexInParallel";
+
+ /**
+ * The "reftable" section
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_REFTABLE_SECTION = "reftable";
+
+ /**
+ * The "autorefresh" key
+ *
+ * @since 7.2
+ */
+ public static final String CONFIG_KEY_AUTOREFRESH = "autorefresh";
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
index 997f4ed314..9de8392690 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -345,6 +345,15 @@ public final class Constants {
public static final String XDG_CONFIG_HOME = "XDG_CONFIG_HOME";
/**
+ * The key of the XDG_CACHE_HOME directory defined in the
+ * <a href="https://wiki.archlinux.org/index.php/XDG_Base_Directory">
+ * XDG Base Directory specification</a>.
+ *
+ * @since 7.3
+ */
+ public static final String XDG_CACHE_HOME = "XDG_CACHE_HOME";
+
+ /**
* The environment variable that limits how close to the root of the file
* systems JGit will traverse when looking for a repository root.
*/
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
index 49602a75eb..0e27b2743c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CoreConfig.java
@@ -17,12 +17,16 @@ package org.eclipse.jgit.lib;
import static java.util.zip.Deflater.DEFAULT_COMPRESSION;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config.SectionParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This class keeps git repository core parameters.
*/
public class CoreConfig {
+ private static final Logger LOG = LoggerFactory.getLogger(CoreConfig.class);
/** Key for {@link Config#get(SectionParser)}. */
public static final Config.SectionParser<CoreConfig> KEY = CoreConfig::new;
@@ -127,7 +131,9 @@ public class CoreConfig {
* Permissible values for {@code core.trustPackedRefsStat}.
*
* @since 6.1.1
+ * @deprecated use {@link TrustStat} instead
*/
+ @Deprecated(since = "7.2", forRemoval = true)
public enum TrustPackedRefsStat {
/** Do not trust file attributes of the packed-refs file. */
NEVER,
@@ -135,12 +141,15 @@ public class CoreConfig {
/** Trust file attributes of the packed-refs file. */
ALWAYS,
- /** Open and close the packed-refs file to refresh its file attributes
- * and then trust it. */
+ /**
+ * Open and close the packed-refs file to refresh its file attributes
+ * and then trust it.
+ */
AFTER_OPEN,
- /** {@code core.trustPackedRefsStat} defaults to this when it is
- * not set */
+ /**
+ * {@code core.trustPackedRefsStat} defaults to this when it is not set
+ */
UNSET
}
@@ -148,17 +157,44 @@ public class CoreConfig {
* Permissible values for {@code core.trustLooseRefStat}.
*
* @since 6.9
+ * @deprecated use {@link TrustStat} instead
*/
+ @Deprecated(since = "7.2", forRemoval = true)
public enum TrustLooseRefStat {
/** Trust file attributes of the loose ref. */
ALWAYS,
- /** Open and close parent directories of the loose ref file until the
- * repository root to refresh its file attributes and then trust it. */
+ /**
+ * Open and close parent directories of the loose ref file until the
+ * repository root to refresh its file attributes and then trust it.
+ */
AFTER_OPEN,
}
+ /**
+ * Values for {@code core.trustXXX} options.
+ *
+ * @since 7.2
+ */
+ public enum TrustStat {
+ /** Do not trust file attributes of a File. */
+ NEVER,
+
+ /** Always trust file attributes of a File. */
+ ALWAYS,
+
+ /** Open and close the File to refresh its file attributes
+ * and then trust it. */
+ AFTER_OPEN,
+
+ /**
+ * Used for specific options to inherit value from value set for
+ * core.trustStat.
+ */
+ INHERIT
+ }
+
private final int compression;
private final int packIndexVersion;
@@ -169,6 +205,18 @@ public class CoreConfig {
private final boolean commitGraph;
+ private final TrustStat trustStat;
+
+ private final TrustStat trustPackedRefsStat;
+
+ private final TrustStat trustLooseRefStat;
+
+ private final TrustStat trustPackStat;
+
+ private final TrustStat trustLooseObjectStat;
+
+ private final TrustStat trustTablesListStat;
+
/**
* Options for symlink handling
*
@@ -198,7 +246,13 @@ public class CoreConfig {
DOTGITONLY
}
- private CoreConfig(Config rc) {
+ /**
+ * Create a new core configuration from the passed configuration.
+ *
+ * @param rc
+ * git configuration
+ */
+ CoreConfig(Config rc) {
compression = rc.getInt(ConfigConstants.CONFIG_CORE_SECTION,
ConfigConstants.CONFIG_KEY_COMPRESSION, DEFAULT_COMPRESSION);
packIndexVersion = rc.getInt(ConfigConstants.CONFIG_PACK_SECTION,
@@ -210,6 +264,68 @@ public class CoreConfig {
commitGraph = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION,
ConfigConstants.CONFIG_COMMIT_GRAPH,
DEFAULT_COMMIT_GRAPH_ENABLE);
+
+ trustStat = parseTrustStat(rc);
+ trustPackedRefsStat = parseTrustPackedRefsStat(rc);
+ trustLooseRefStat = parseTrustLooseRefStat(rc);
+ trustPackStat = parseTrustPackFileStat(rc);
+ trustLooseObjectStat = parseTrustLooseObjectFileStat(rc);
+ trustTablesListStat = parseTablesListStat(rc);
+ }
+
+ private static TrustStat parseTrustStat(Config rc) {
+ Boolean tfs = rc.getBoolean(ConfigConstants.CONFIG_CORE_SECTION,
+ ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT);
+ TrustStat ts = rc.getEnum(TrustStat.values(),
+ ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_TRUST_STAT);
+ if (tfs != null) {
+ if (ts == null) {
+ LOG.warn(JGitText.get().deprecatedTrustFolderStat);
+ return tfs.booleanValue() ? TrustStat.ALWAYS : TrustStat.NEVER;
+ }
+ LOG.warn(JGitText.get().precedenceTrustConfig);
+ }
+ if (ts == null) {
+ ts = TrustStat.ALWAYS;
+ } else if (ts == TrustStat.INHERIT) {
+ LOG.warn(JGitText.get().invalidTrustStat);
+ ts = TrustStat.ALWAYS;
+ }
+ return ts;
+ }
+
+ private TrustStat parseTrustPackedRefsStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_PACKED_REFS_STAT);
+ }
+
+ private TrustStat parseTrustLooseRefStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_LOOSE_REF_STAT);
+ }
+
+ private TrustStat parseTrustPackFileStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_PACK_STAT);
+ }
+
+ private TrustStat parseTrustLooseObjectFileStat(Config rc) {
+ return inheritParseTrustStat(rc,
+ ConfigConstants.CONFIG_KEY_TRUST_LOOSE_OBJECT_STAT);
+ }
+
+ private TrustStat inheritParseTrustStat(Config rc, String key) {
+ TrustStat t = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null, key,
+ TrustStat.INHERIT);
+ return t == TrustStat.INHERIT ? trustStat : t;
+ }
+
+ private TrustStat parseTablesListStat(Config rc) {
+ TrustStat t = rc.getEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_TRUST_TABLESLIST_STAT,
+ TrustStat.INHERIT);
+ return t == TrustStat.INHERIT ? trustStat : t;
}
/**
@@ -260,4 +376,70 @@ public class CoreConfig {
public boolean enableCommitGraph() {
return commitGraph;
}
+
+ /**
+ * Get how far we can trust file attributes of packed-refs file which is
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of packed-refs file.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustPackedRefsStat() {
+ return trustPackedRefsStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of loose ref files which are
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of loose ref files.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustLooseRefStat() {
+ return trustLooseRefStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of packed-refs file which is
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of packed-refs file.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustPackStat() {
+ return trustPackStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of loose ref files which are
+ * used to store {@link org.eclipse.jgit.lib.Ref}s in
+ * {@link org.eclipse.jgit.internal.storage.file.RefDirectory}.
+ *
+ * @return how far we can trust file attributes of loose ref files.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustLooseObjectStat() {
+ return trustLooseObjectStat;
+ }
+
+ /**
+ * Get how far we can trust file attributes of the "tables.list" file which
+ * is used to store the list of filenames of the files storing
+ * {@link org.eclipse.jgit.internal.storage.reftable.Reftable}s in
+ * {@link org.eclipse.jgit.internal.storage.file.FileReftableDatabase}.
+ *
+ * @return how far we can trust file attributes of the "tables.list" file.
+ *
+ * @since 7.2
+ */
+ public TrustStat getTrustTablesListStat() {
+ return trustTablesListStat;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
index a71549c92e..3059f283fe 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
@@ -18,6 +18,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config.ConfigEnum;
import org.eclipse.jgit.transport.RefSpec;
@@ -31,27 +32,37 @@ import org.eclipse.jgit.util.StringUtils;
*/
public class DefaultTypedConfigGetter implements TypedConfigGetter {
+ @SuppressWarnings("boxed")
@Override
public boolean getBoolean(Config config, String section, String subsection,
String name, boolean defaultValue) {
+ return neverNull(getBoolean(config, section, subsection, name,
+ Boolean.valueOf(defaultValue)));
+ }
+
+ @Nullable
+ @Override
+ public Boolean getBoolean(Config config, String section, String subsection,
+ String name, @Nullable Boolean defaultValue) {
String n = config.getString(section, subsection, name);
if (n == null) {
return defaultValue;
}
if (Config.isMissing(n)) {
- return true;
+ return Boolean.TRUE;
}
try {
- return StringUtils.toBoolean(n);
+ return Boolean.valueOf(StringUtils.toBoolean(n));
} catch (IllegalArgumentException err) {
throw new IllegalArgumentException(MessageFormat.format(
JGitText.get().invalidBooleanValue, section, name, n), err);
}
}
+ @Nullable
@Override
public <T extends Enum<?>> T getEnum(Config config, T[] all, String section,
- String subsection, String name, T defaultValue) {
+ String subsection, String name, @Nullable T defaultValue) {
String value = config.getString(section, subsection, name);
if (value == null) {
return defaultValue;
@@ -107,9 +118,27 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
@Override
public int getInt(Config config, String section, String subsection,
String name, int defaultValue) {
- long val = config.getLong(section, subsection, name, defaultValue);
+ return neverNull(getInt(config, section, subsection, name,
+ Integer.valueOf(defaultValue)));
+ }
+
+ @Nullable
+ @Override
+ @SuppressWarnings("boxing")
+ public Integer getInt(Config config, String section, String subsection,
+ String name, @Nullable Integer defaultValue) {
+ Long longDefault = defaultValue != null
+ ? Long.valueOf(defaultValue.longValue())
+ : null;
+ Long val = config.getLong(section, subsection, name);
+ if (val == null) {
+ val = longDefault;
+ }
+ if (val == null) {
+ return null;
+ }
if (Integer.MIN_VALUE <= val && val <= Integer.MAX_VALUE) {
- return (int) val;
+ return Integer.valueOf(Math.toIntExact(val));
}
throw new IllegalArgumentException(MessageFormat
.format(JGitText.get().integerValueOutOfRange, section, name));
@@ -118,37 +147,56 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
@Override
public int getIntInRange(Config config, String section, String subsection,
String name, int minValue, int maxValue, int defaultValue) {
- int val = getInt(config, section, subsection, name, defaultValue);
+ return neverNull(getIntInRange(config, section, subsection, name,
+ minValue, maxValue, Integer.valueOf(defaultValue)));
+ }
+
+ @Override
+ @SuppressWarnings("boxing")
+ public Integer getIntInRange(Config config, String section,
+ String subsection, String name, int minValue, int maxValue,
+ Integer defaultValue) {
+ Integer val = getInt(config, section, subsection, name, defaultValue);
+ if (val == null) {
+ return null;
+ }
if ((val >= minValue && val <= maxValue) || val == UNSET_INT) {
return val;
}
if (subsection == null) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().integerValueNotInRange, section, name,
- Integer.valueOf(val), Integer.valueOf(minValue),
- Integer.valueOf(maxValue)));
+ throw new IllegalArgumentException(
+ MessageFormat.format(JGitText.get().integerValueNotInRange,
+ section, name, val, minValue, maxValue));
}
throw new IllegalArgumentException(MessageFormat.format(
JGitText.get().integerValueNotInRangeSubSection, section,
- subsection, name, Integer.valueOf(val),
- Integer.valueOf(minValue), Integer.valueOf(maxValue)));
+ subsection, name, val, minValue, maxValue));
}
@Override
public long getLong(Config config, String section, String subsection,
String name, long defaultValue) {
- final String str = config.getString(section, subsection, name);
+ return neverNull(getLong(config, section, subsection, name,
+ Long.valueOf(defaultValue)));
+ }
+
+ @Nullable
+ @Override
+ public Long getLong(Config config, String section, String subsection,
+ String name, @Nullable Long defaultValue) {
+ String str = config.getString(section, subsection, name);
if (str == null) {
return defaultValue;
}
try {
- return StringUtils.parseLongWithSuffix(str, false);
+ return Long.valueOf(StringUtils.parseLongWithSuffix(str, false));
} catch (StringIndexOutOfBoundsException e) {
// Empty
return defaultValue;
} catch (NumberFormatException nfe) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().invalidIntegerValue, section, name, str),
+ throw new IllegalArgumentException(
+ MessageFormat.format(JGitText.get().invalidIntegerValue,
+ section, name, str),
nfe);
}
}
@@ -156,6 +204,13 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
@Override
public long getTimeUnit(Config config, String section, String subsection,
String name, long defaultValue, TimeUnit wantUnit) {
+ return neverNull(getTimeUnit(config, section, subsection, name,
+ Long.valueOf(defaultValue), wantUnit));
+ }
+
+ @Override
+ public Long getTimeUnit(Config config, String section, String subsection,
+ String name, @Nullable Long defaultValue, TimeUnit wantUnit) {
String valueString = config.getString(section, subsection, name);
if (valueString == null) {
@@ -232,8 +287,8 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
}
try {
- return wantUnit.convert(Long.parseLong(digits) * inputMul,
- inputUnit);
+ return Long.valueOf(wantUnit
+ .convert(Long.parseLong(digits) * inputMul, inputUnit));
} catch (NumberFormatException nfe) {
IllegalArgumentException iae = notTimeUnit(section, subsection,
unitName, valueString);
@@ -274,4 +329,14 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
}
return result;
}
+
+ // Trick for the checkers. When we use this, one is never null, but
+ // they don't know.
+ @NonNull
+ private static <T> T neverNull(T one) {
+ if (one == null) {
+ throw new IllegalArgumentException();
+ }
+ return one;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
index 76ed36a6e5..23d16db39f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/GpgConfig.java
@@ -74,8 +74,7 @@ public class GpgConfig {
* the config to read from
*/
public GpgConfig(Config config) {
- keyFormat = config.getEnum(GpgFormat.values(),
- ConfigConstants.CONFIG_GPG_SECTION, null,
+ keyFormat = config.getEnum(ConfigConstants.CONFIG_GPG_SECTION, null,
ConfigConstants.CONFIG_KEY_FORMAT, GpgFormat.OPENPGP);
signingKey = config.getString(ConfigConstants.CONFIG_USER_SECTION, null,
ConfigConstants.CONFIG_KEY_SIGNINGKEY);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
index f22642c4ce..50f4a83b93 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java
@@ -45,7 +45,9 @@ public class PersonIdent implements Serializable {
* timezone offset as in {@link #getTimeZoneOffset()}.
* @return time zone object for the given offset.
* @since 4.1
+ * @deprecated use {@link #getZoneId(int)} instead
*/
+ @Deprecated(since = "7.2")
public static TimeZone getTimeZone(int tzOffset) {
StringBuilder tzId = new StringBuilder(8);
tzId.append("GMT"); //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
index 09cb5a83dd..49d5224325 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
@@ -356,6 +356,40 @@ public abstract class RefDatabase {
}
/**
+ * Get the reflog reader
+ *
+ * @param refName
+ * a {@link java.lang.String} object.
+ * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied
+ * refname, or {@code null} if the named ref does not exist.
+ * @throws java.io.IOException
+ * the ref could not be accessed.
+ * @since 7.2
+ */
+ @Nullable
+ public ReflogReader getReflogReader(String refName) throws IOException {
+ Ref ref = exactRef(refName);
+ if (ref == null) {
+ return null;
+ }
+ return getReflogReader(ref);
+ }
+
+ /**
+ * Get the reflog reader.
+ *
+ * @param ref
+ * a Ref
+ * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref.
+ * @throws IOException
+ * if an IO error occurred
+ * @since 7.2
+ */
+ @NonNull
+ public abstract ReflogReader getReflogReader(@NonNull Ref ref)
+ throws IOException;
+
+ /**
* Get a section of the reference namespace.
*
* @param prefix
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index 0562840915..c9dc6da4ba 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -26,6 +26,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -33,10 +35,12 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
import org.eclipse.jgit.annotations.NonNull;
@@ -132,6 +136,8 @@ public abstract class Repository implements AutoCloseable {
private final String initialBranch;
+ private final AtomicReference<Boolean> caseInsensitiveWorktree = new AtomicReference<>();
+
/**
* Initialize a new repository instance.
*
@@ -1577,6 +1583,40 @@ public abstract class Repository implements AutoCloseable {
}
/**
+ * Tells whether the work tree is on a case-insensitive file system.
+ *
+ * @return {@code true} if the work tree is case-insensitive; {@code false}
+ * otherwise
+ * @throws NoWorkTreeException
+ * if the repository is bare
+ * @since 7.2
+ */
+ public boolean isWorkTreeCaseInsensitive() throws NoWorkTreeException {
+ Boolean flag = caseInsensitiveWorktree.get();
+ if (flag == null) {
+ File directory = getWorkTree();
+ // See if we can find ".git" also as ".GIT".
+ File dotGit = new File(directory, Constants.DOT_GIT);
+ if (Files.exists(dotGit.toPath(), LinkOption.NOFOLLOW_LINKS)) {
+ dotGit = new File(directory,
+ Constants.DOT_GIT.toUpperCase(Locale.ROOT));
+ flag = Boolean.valueOf(Files.exists(dotGit.toPath(),
+ LinkOption.NOFOLLOW_LINKS));
+ } else {
+ // Fall back to a mostly sane default. On Mac, HFS+ and APFS
+ // partitions are case-insensitive by default but can be
+ // configured to be case-sensitive.
+ SystemReader system = SystemReader.getInstance();
+ flag = Boolean.valueOf(system.isWindows() || system.isMacOS());
+ }
+ if (!caseInsensitiveWorktree.compareAndSet(null, flag)) {
+ flag = caseInsensitiveWorktree.get();
+ }
+ }
+ return flag.booleanValue();
+ }
+
+ /**
* Force a scan for changed refs. Fires an IndexChangedEvent(false) if
* changes are detected.
*
@@ -1692,10 +1732,13 @@ public abstract class Repository implements AutoCloseable {
* @throws java.io.IOException
* the ref could not be accessed.
* @since 3.0
+ * @deprecated use {@code #getRefDatabase().getReflogReader(String)} instead
*/
+ @Deprecated(since = "7.2")
@Nullable
- public abstract ReflogReader getReflogReader(String refName)
- throws IOException;
+ public ReflogReader getReflogReader(String refName) throws IOException {
+ return getRefDatabase().getReflogReader(refName);
+ }
/**
* Get the reflog reader. Subclasses should override this method and provide
@@ -1703,15 +1746,17 @@ public abstract class Repository implements AutoCloseable {
*
* @param ref
* a Ref
- * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref,
- * or {@code null} if the ref does not exist.
+ * @return a {@link org.eclipse.jgit.lib.ReflogReader} for the supplied ref.
* @throws IOException
* if an IO error occurred
* @since 5.13.2
+ * @deprecated use {@code #getRefDatabase().getReflogReader(Ref)} instead
*/
- public @Nullable ReflogReader getReflogReader(@NonNull Ref ref)
+ @Deprecated(since = "7.2")
+ @NonNull
+ public ReflogReader getReflogReader(@NonNull Ref ref)
throws IOException {
- return getReflogReader(ref.getName());
+ return getRefDatabase().getReflogReader(ref);
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
index 0c03adcab8..3d4e0d1f3c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
@@ -17,6 +17,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.util.FS;
@@ -50,11 +51,36 @@ public interface TypedConfigGetter {
* default value to return if no value was present.
* @return true if any value or defaultValue is true, false for missing or
* explicit false
+ * @deprecated use
+ * {@link #getBoolean(Config, String, String, String, Boolean)}
+ * instead
*/
+ @Deprecated
boolean getBoolean(Config config, String section, String subsection,
String name, boolean defaultValue);
/**
+ * Get a boolean value from a git {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return true if any value or defaultValue is true, false for missing or
+ * explicit false
+ * @since 7.2
+ */
+ @Nullable
+ Boolean getBoolean(Config config, String section, String subsection,
+ String name, @Nullable Boolean defaultValue);
+
+ /**
* Parse an enumeration from a git {@link Config}.
*
* @param <T>
@@ -74,8 +100,9 @@ public interface TypedConfigGetter {
* default value to return if no value was present.
* @return the selected enumeration value, or {@code defaultValue}.
*/
+ @Nullable
<T extends Enum<?>> T getEnum(Config config, T[] all, String section,
- String subsection, String name, T defaultValue);
+ String subsection, String name, @Nullable T defaultValue);
/**
* Obtain an integer value from a git {@link Config}.
@@ -91,11 +118,34 @@ public interface TypedConfigGetter {
* @param defaultValue
* default value to return if no value was present.
* @return an integer value from the configuration, or defaultValue.
+ * @deprecated use {@link #getInt(Config, String, String, String, Integer)}
+ * instead
*/
+ @Deprecated
int getInt(Config config, String section, String subsection, String name,
int defaultValue);
/**
+ * Obtain an integer value from a git {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return an integer value from the configuration, or defaultValue.
+ * @since 7.2
+ */
+ @Nullable
+ Integer getInt(Config config, String section, String subsection,
+ String name, @Nullable Integer defaultValue);
+
+ /**
* Obtain an integer value from a git {@link Config} which must be in given
* range.
*
@@ -117,11 +167,43 @@ public interface TypedConfigGetter {
* @return an integer value from the configuration, or defaultValue.
* {@code #UNSET_INT} if unset.
* @since 6.1
+ * @deprecated use
+ * {@link #getIntInRange(Config, String, String, String, int, int, Integer)}
+ * instead
*/
+ @Deprecated
int getIntInRange(Config config, String section, String subsection,
String name, int minValue, int maxValue, int defaultValue);
/**
+ * Obtain an integer value from a git {@link Config} which must be in given
+ * range.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param minValue
+ * minimal value
+ * @param maxValue
+ * maximum value
+ * @param defaultValue
+ * default value to return if no value was present. Use
+ * {@code #UNSET_INT} to set the default to unset.
+ * @return an integer value from the configuration, or defaultValue.
+ * {@code #UNSET_INT} if unset.
+ * @since 7.2
+ */
+ @Nullable
+ Integer getIntInRange(Config config, String section, String subsection,
+ String name, int minValue, int maxValue,
+ @Nullable Integer defaultValue);
+
+ /**
* Obtain a long value from a git {@link Config}.
*
* @param config
@@ -135,11 +217,34 @@ public interface TypedConfigGetter {
* @param defaultValue
* default value to return if no value was present.
* @return a long value from the configuration, or defaultValue.
+ * @deprecated use {@link #getLong(Config, String, String, String, Long)}
+ * instead
*/
+ @Deprecated
long getLong(Config config, String section, String subsection, String name,
long defaultValue);
/**
+ * Obtain a long value from a git {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is grouped within.
+ * @param subsection
+ * subsection name, such a remote or branch name.
+ * @param name
+ * name of the key to get.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @return a long value from the configuration, or defaultValue.
+ * @since 7.2
+ */
+ @Nullable
+ Long getLong(Config config, String section, String subsection, String name,
+ @Nullable Long defaultValue);
+
+ /**
* Parse a numerical time unit, such as "1 minute", from a git
* {@link Config}.
*
@@ -159,11 +264,41 @@ public interface TypedConfigGetter {
* indication of the units.
* @return the value, or {@code defaultValue} if not set, expressed in
* {@code units}.
+ * @deprecated use
+ * {@link #getTimeUnit(Config, String, String, String, Long, TimeUnit)}
+ * instead
*/
+ @Deprecated
long getTimeUnit(Config config, String section, String subsection,
String name, long defaultValue, TimeUnit wantUnit);
/**
+ * Parse a numerical time unit, such as "1 minute", from a git
+ * {@link Config}.
+ *
+ * @param config
+ * to get the value from
+ * @param section
+ * section the key is in.
+ * @param subsection
+ * subsection the key is in, or null if not in a subsection.
+ * @param name
+ * the key name.
+ * @param defaultValue
+ * default value to return if no value was present.
+ * @param wantUnit
+ * the units of {@code defaultValue} and the return value, as
+ * well as the units to assume if the value does not contain an
+ * indication of the units.
+ * @return the value, or {@code defaultValue} if not set, expressed in
+ * {@code units}.
+ * @since 7.2
+ */
+ @Nullable
+ Long getTimeUnit(Config config, String section, String subsection,
+ String name, @Nullable Long defaultValue, TimeUnit wantUnit);
+
+ /**
* Parse a string value from a git {@link Config} and treat it as a file
* path, replacing a ~/ prefix by the user's home directory.
* <p>
@@ -189,9 +324,10 @@ public interface TypedConfigGetter {
* @return the {@link Path}, or {@code defaultValue} if not set
* @since 5.10
*/
+ @Nullable
default Path getPath(Config config, String section, String subsection,
String name, @NonNull FS fs, File resolveAgainst,
- Path defaultValue) {
+ @Nullable Path defaultValue) {
String value = config.getString(section, subsection, name);
if (value == null) {
return defaultValue;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
index 0f6bd2d6cc..c8c454a228 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/PlotWalk.java
@@ -169,8 +169,9 @@ public class PlotWalk extends RevWalk {
}
long timeof(RevObject o) {
- if (o instanceof RevCommit)
- return ((RevCommit) o).getCommitTime();
+ if (o instanceof RevCommit) {
+ return ((RevCommit) o).getCommitTime() * 1000L;
+ }
if (o instanceof RevTag) {
RevTag tag = (RevTag) o;
try {
@@ -179,7 +180,7 @@ public class PlotWalk extends RevWalk {
return 0;
}
PersonIdent who = tag.getTaggerIdent();
- return who != null ? who.getWhen().getTime() : 0;
+ return who != null ? who.getWhenAsInstant().toEpochMilli() : 0;
}
return 0;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FollowFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FollowFilter.java
index 35ef51f4fd..12e6c4ea98 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FollowFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FollowFilter.java
@@ -18,7 +18,7 @@ import org.eclipse.jgit.diff.DiffConfig;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.treewalk.TreeWalk;
-import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.ChangedPathTreeFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
/**
@@ -56,39 +56,44 @@ public class FollowFilter extends TreeFilter {
* @since 3.0
*/
public static FollowFilter create(String path, DiffConfig cfg) {
- return new FollowFilter(PathFilter.create(path), cfg);
+ return new FollowFilter(ChangedPathTreeFilter.create(path), cfg);
}
- private final PathFilter path;
+ private final ChangedPathTreeFilter path;
final DiffConfig cfg;
private RenameCallback renameCallback;
- FollowFilter(PathFilter path, DiffConfig cfg) {
+ FollowFilter(ChangedPathTreeFilter path, DiffConfig cfg) {
this.path = path;
this.cfg = cfg;
}
- /** @return the path this filter matches. */
/**
* Get the path this filter matches.
*
* @return the path this filter matches.
*/
public String getPath() {
- return path.getPath();
+ return path.getPaths().get(0);
}
@Override
public boolean include(TreeWalk walker)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
- return path.include(walker) && ANY_DIFF.include(walker);
+ return path.include(walker);
+ }
+
+ @Override
+ public boolean shouldTreeWalk(RevCommit c, RevWalk rw,
+ MutableBoolean cpfUsed) {
+ return path.shouldTreeWalk(c, rw, cpfUsed);
}
@Override
public boolean shouldBeRecursive() {
- return path.shouldBeRecursive() || ANY_DIFF.shouldBeRecursive();
+ return path.shouldBeRecursive();
}
@Override
@@ -105,9 +110,7 @@ public class FollowFilter extends TreeFilter {
@SuppressWarnings("nls")
@Override
public String toString() {
- return "(FOLLOW(" + path.toString() + ")" //
- + " AND " //
- + ANY_DIFF.toString() + ")";
+ return "(FOLLOW(" + path.toString() + "))";
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java
index 55ddebf288..871545fca2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java
@@ -401,13 +401,13 @@ public class RevCommit extends RevObject {
* @since 5.1
*/
public final byte[] getRawGpgSignature() {
- final byte[] raw = buffer;
- final byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' };
- final int start = RawParseUtils.headerStart(header, raw, 0);
+ byte[] raw = buffer;
+ byte[] header = { 'g', 'p', 'g', 's', 'i', 'g' };
+ int start = RawParseUtils.headerStart(header, raw, 0);
if (start < 0) {
return null;
}
- final int end = RawParseUtils.headerEnd(raw, start);
+ int end = RawParseUtils.nextLfSkippingSplitLines(raw, start);
return RawParseUtils.headerValue(raw, start, end);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
index 9f0e28d0ce..41f98bad84 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
@@ -19,9 +19,14 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Optional;
+import java.util.Map;
+import java.util.
+Optional;
+import java.util.Set;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
@@ -523,6 +528,27 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable {
}
/**
+ * Determine if a <code>commit</code> is merged into any of the given
+ * <code>revs</code>.
+ *
+ * @param commit
+ * commit the caller thinks is reachable from <code>revs</code>.
+ * @param revs
+ * commits to start iteration from, and which is most likely a
+ * descendant (child) of <code>commit</code>.
+ * @return true if commit is merged into any of the revs; false otherwise.
+ * @throws java.io.IOException
+ * a pack file or loose object could not be read.
+ * @since 6.10.1
+ */
+ public boolean isMergedIntoAnyCommit(RevCommit commit, Collection<RevCommit> revs)
+ throws IOException {
+ return getCommitsMergedInto(commit, revs,
+ GetMergedIntoStrategy.RETURN_ON_FIRST_FOUND,
+ NullProgressMonitor.INSTANCE).size() > 0;
+ }
+
+ /**
* Determine if a <code>commit</code> is merged into all of the given
* <code>refs</code>.
*
@@ -545,7 +571,26 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable {
private List<Ref> getMergedInto(RevCommit needle, Collection<Ref> haystacks,
Enum returnStrategy, ProgressMonitor monitor) throws IOException {
+ Map<RevCommit, List<Ref>> refsByCommit = new HashMap<>();
+ for (Ref r : haystacks) {
+ RevObject o = peel(parseAny(r.getObjectId()));
+ if (!(o instanceof RevCommit)) {
+ continue;
+ }
+ refsByCommit.computeIfAbsent((RevCommit) o, c -> new ArrayList<>()).add(r);
+ }
+ monitor.update(1);
List<Ref> result = new ArrayList<>();
+ for (RevCommit c : getCommitsMergedInto(needle, refsByCommit.keySet(),
+ returnStrategy, monitor)) {
+ result.addAll(refsByCommit.get(c));
+ }
+ return result;
+ }
+
+ private Set<RevCommit> getCommitsMergedInto(RevCommit needle, Collection<RevCommit> haystacks,
+ Enum returnStrategy, ProgressMonitor monitor) throws IOException {
+ Set<RevCommit> result = new HashSet<>();
List<RevCommit> uninteresting = new ArrayList<>();
List<RevCommit> marked = new ArrayList<>();
RevFilter oldRF = filter;
@@ -561,16 +606,11 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable {
needle.parseHeaders(this);
}
int cutoff = needle.getGeneration();
- for (Ref r : haystacks) {
+ for (RevCommit c : haystacks) {
if (monitor.isCancelled()) {
return result;
}
monitor.update(1);
- RevObject o = peel(parseAny(r.getObjectId()));
- if (!(o instanceof RevCommit)) {
- continue;
- }
- RevCommit c = (RevCommit) o;
reset(UNINTERESTING | TEMP_MARK);
markStart(c);
boolean commitFound = false;
@@ -582,7 +622,7 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable {
}
if (References.isSameObject(next, needle)
|| (next.flags & TEMP_MARK) != 0) {
- result.add(r);
+ result.add(c);
if (returnStrategy == GetMergedIntoStrategy.RETURN_ON_FIRST_FOUND) {
return result;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
index 99943b78e6..e9a3e72c7f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/TreeRevFilter.java
@@ -12,15 +12,11 @@ package org.eclipse.jgit.revwalk;
import java.io.IOException;
import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import org.eclipse.jgit.internal.storage.commitgraph.ChangedPathFilter;
import org.eclipse.jgit.diff.DiffConfig;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.RenameDetector;
-import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.StopWalkException;
@@ -28,6 +24,7 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.eclipse.jgit.treewalk.filter.TreeFilter.MutableBoolean;
/**
* Filter applying a {@link org.eclipse.jgit.treewalk.filter.TreeFilter} against
@@ -50,6 +47,8 @@ public class TreeRevFilter extends RevFilter {
private final TreeWalk pathFilter;
+ private final MutableBoolean changedPathFilterUsed = new MutableBoolean();
+
private long changedPathFilterTruePositive = 0;
private long changedPathFilterFalsePositive = 0;
@@ -126,24 +125,15 @@ public class TreeRevFilter extends RevFilter {
}
trees[nParents] = c.getTree();
tw.reset(trees);
+ changedPathFilterUsed.reset();
if (nParents == 1) {
// We have exactly one parent. This is a very common case.
//
int chgs = 0, adds = 0;
- boolean changedPathFilterUsed = false;
- boolean mustCalculateChgs = true;
- ChangedPathFilter cpf = c.getChangedPathFilter(walker);
- if (cpf != null) {
- Optional<Set<byte[]>> paths = pathFilter.getFilter()
- .getPathsBestEffort();
- if (paths.isPresent()) {
- changedPathFilterUsed = true;
- if (paths.get().stream().noneMatch(cpf::maybeContains)) {
- mustCalculateChgs = false;
- }
- }
- }
+ TreeFilter tf = pathFilter.getFilter();
+ boolean mustCalculateChgs = tf.shouldTreeWalk(c, walker,
+ changedPathFilterUsed);
if (mustCalculateChgs) {
while (tw.next()) {
chgs++;
@@ -153,7 +143,7 @@ public class TreeRevFilter extends RevFilter {
break; // no point in looking at this further.
}
}
- if (changedPathFilterUsed) {
+ if (changedPathFilterUsed.get()) {
if (chgs > 0) {
changedPathFilterTruePositive++;
} else {
@@ -161,7 +151,7 @@ public class TreeRevFilter extends RevFilter {
}
}
} else {
- if (changedPathFilterUsed) {
+ if (changedPathFilterUsed.get()) {
changedPathFilterNegative++;
}
}
@@ -315,9 +305,7 @@ public class TreeRevFilter extends RevFilter {
}
private void updateFollowFilter(ObjectId[] trees, DiffConfig cfg,
- RevCommit commit)
- throws MissingObjectException, IncorrectObjectTypeException,
- CorruptObjectException, IOException {
+ RevCommit commit) throws IOException {
TreeWalk tw = pathFilter;
FollowFilter oldFilter = (FollowFilter) tw.getFilter();
tw.setFilter(TreeFilter.ANY_DIFF);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
index becc8082ba..105cba7d28 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
@@ -787,14 +787,14 @@ public class SubmoduleWalk implements AutoCloseable {
IgnoreSubmoduleMode mode = repoConfig.getEnum(
IgnoreSubmoduleMode.values(),
ConfigConstants.CONFIG_SUBMODULE_SECTION, getModuleName(),
- ConfigConstants.CONFIG_KEY_IGNORE, null);
+ ConfigConstants.CONFIG_KEY_IGNORE);
if (mode != null) {
return mode;
}
lazyLoadModulesConfig();
- return modulesConfig.getEnum(IgnoreSubmoduleMode.values(),
- ConfigConstants.CONFIG_SUBMODULE_SECTION, getModuleName(),
- ConfigConstants.CONFIG_KEY_IGNORE, IgnoreSubmoduleMode.NONE);
+ return modulesConfig.getEnum(ConfigConstants.CONFIG_SUBMODULE_SECTION,
+ getModuleName(), ConfigConstants.CONFIG_KEY_IGNORE,
+ IgnoreSubmoduleMode.NONE);
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java
index aaf9f8a08a..9d9f5495fe 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java
@@ -760,6 +760,15 @@ public class AmazonS3 {
SAXParserFactory saxParserFactory = SAXParserFactory
.newInstance();
saxParserFactory.setNamespaceAware(true);
+ saxParserFactory.setFeature(
+ "http://xml.org/sax/features/external-general-entities", //$NON-NLS-1$
+ false);
+ saxParserFactory.setFeature(
+ "http://xml.org/sax/features/external-parameter-entities", //$NON-NLS-1$
+ false);
+ saxParserFactory.setFeature(
+ "http://apache.org/xml/features/disallow-doctype-decl", //$NON-NLS-1$
+ true);
xr = saxParserFactory.newSAXParser().getXMLReader();
} catch (SAXException | ParserConfigurationException e) {
throw new IOException(
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
index 73eddb8e21..f10b7bf452 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
@@ -302,8 +302,7 @@ public class HttpConfig {
int postBufferSize = config.getInt(HTTP, POST_BUFFER_KEY,
1 * 1024 * 1024);
boolean sslVerifyFlag = config.getBoolean(HTTP, SSL_VERIFY_KEY, true);
- HttpRedirectMode followRedirectsMode = config.getEnum(
- HttpRedirectMode.values(), HTTP, null,
+ HttpRedirectMode followRedirectsMode = config.getEnum(HTTP, null,
FOLLOW_REDIRECTS_KEY, HttpRedirectMode.INITIAL);
int redirectLimit = config.getInt(HTTP, MAX_REDIRECTS_KEY,
MAX_REDIRECTS);
@@ -335,8 +334,8 @@ public class HttpConfig {
postBufferSize);
sslVerifyFlag = config.getBoolean(HTTP, match, SSL_VERIFY_KEY,
sslVerifyFlag);
- followRedirectsMode = config.getEnum(HttpRedirectMode.values(),
- HTTP, match, FOLLOW_REDIRECTS_KEY, followRedirectsMode);
+ followRedirectsMode = config.getEnum(HTTP, match,
+ FOLLOW_REDIRECTS_KEY, followRedirectsMode);
int newMaxRedirects = config.getInt(HTTP, match, MAX_REDIRECTS_KEY,
redirectLimit);
if (newMaxRedirects >= 0) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
index 4de6ff825f..7b5842b712 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
@@ -82,7 +82,7 @@ public class URIish implements Serializable {
* Part of a pattern which matches a relative path. Relative paths don't
* start with slash or drive letters. Defines no capturing group.
*/
- private static final String RELATIVE_PATH_P = "(?:(?:[^\\\\/]+[\\\\/]+)*[^\\\\/]+[\\\\/]*)"; //$NON-NLS-1$
+ private static final String RELATIVE_PATH_P = "(?:(?:[^\\\\/]+[\\\\/]+)*+[^\\\\/]*)"; //$NON-NLS-1$
/**
* Part of a pattern which matches a relative or absolute path. Defines no
@@ -120,7 +120,7 @@ public class URIish implements Serializable {
* path (maybe even containing windows drive-letters) or a relative path.
*/
private static final Pattern LOCAL_FILE = Pattern.compile("^" // //$NON-NLS-1$
- + "([\\\\/]?" + PATH_P + ")" // //$NON-NLS-1$ //$NON-NLS-2$
+ + "([\\\\/]?+" + PATH_P + ")" // //$NON-NLS-1$ //$NON-NLS-2$
+ "$"); //$NON-NLS-1$
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/AndTreeFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/AndTreeFilter.java
index c6804da039..b35dbebd17 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/AndTreeFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/AndTreeFilter.java
@@ -12,11 +12,14 @@
package org.eclipse.jgit.treewalk.filter;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Collection;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
/**
@@ -100,6 +103,13 @@ public abstract class AndTreeFilter extends TreeFilter {
}
@Override
+ public boolean shouldTreeWalk(RevCommit c, RevWalk rw,
+ MutableBoolean cpfUsed) {
+ return a.shouldTreeWalk(c, rw, cpfUsed)
+ && b.shouldTreeWalk(c, rw, cpfUsed);
+ }
+
+ @Override
public int matchFilter(TreeWalk walker)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
@@ -174,6 +184,13 @@ public abstract class AndTreeFilter extends TreeFilter {
}
@Override
+ public boolean shouldTreeWalk(RevCommit c, RevWalk rw,
+ MutableBoolean cpfUsed) {
+ return Arrays.stream(subfilters)
+ .allMatch(t -> t.shouldTreeWalk(c, rw, cpfUsed));
+ }
+
+ @Override
public TreeFilter clone() {
final TreeFilter[] s = new TreeFilter[subfilters.length];
for (int i = 0; i < s.length; i++)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilter.java
new file mode 100644
index 0000000000..a74b9b617f
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/ChangedPathTreeFilter.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2025, Google LLC 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
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.treewalk.filter;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.internal.storage.commitgraph.ChangedPathFilter;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.util.StringUtils;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Filter tree entries that modified the contents of particular file paths.
+ * <p>
+ * Equivalent to AndTreeFilter(PathFilter, AnyDiffFilter). This filter uses
+ * {@link org.eclipse.jgit.internal.storage.commitgraph.ChangedPathFilter}
+ * (bloom filters) when available to discard commits without diffing their
+ * trees.
+ *
+ * @since 7.3
+ */
+public class ChangedPathTreeFilter extends TreeFilter {
+
+ private TreeFilter pathFilter;
+
+ private List<String> paths;
+
+ private List<byte[]> rawPaths;
+
+ /**
+ * Create a TreeFilter for trees modifying one or more user supplied paths.
+ * <p>
+ * Path strings are relative to the root of the repository. If the user's
+ * input should be assumed relative to a subdirectory of the repository the
+ * caller must prepend the subdirectory's path prior to creating the filter.
+ * <p>
+ * Path strings use '/' to delimit directories on all platforms.
+ * <p>
+ * Paths may appear in any order within the collection. Sorting may be done
+ * internally when the group is constructed if doing so will improve path
+ * matching performance.
+ *
+ * @param paths
+ * the paths to test against. Must have at least one entry.
+ * @return a new filter for the list of paths supplied.
+ */
+ public static ChangedPathTreeFilter create(String... paths) {
+ return new ChangedPathTreeFilter(paths);
+ }
+
+ private ChangedPathTreeFilter(String... paths) {
+ List<String> filtered = Arrays.stream(paths)
+ .map(s -> StringUtils.trim(s, '/'))
+ .collect(Collectors.toList());
+
+ if (filtered.size() == 0)
+ throw new IllegalArgumentException(
+ JGitText.get().atLeastOnePathIsRequired);
+
+ if (filtered.stream().anyMatch(s -> s.isEmpty() || s.isBlank())) {
+ throw new IllegalArgumentException(
+ JGitText.get().emptyPathNotPermitted);
+ }
+
+ this.paths = filtered;
+ this.rawPaths = this.paths.stream().map(Constants::encode)
+ .collect(Collectors.toList());
+ if (filtered.size() == 1) {
+ this.pathFilter = PathFilter.create(paths[0]);
+ } else {
+ this.pathFilter = OrTreeFilter.create(Arrays.stream(paths)
+ .map(PathFilter::create).collect(Collectors.toList()));
+ }
+ }
+
+ @Override
+ public boolean shouldTreeWalk(RevCommit c, RevWalk rw,
+ MutableBoolean cpfUsed) {
+ ChangedPathFilter cpf = c.getChangedPathFilter(rw);
+ if (cpf == null) {
+ return true;
+ }
+ if (cpfUsed != null) {
+ cpfUsed.orValue(true);
+ }
+ // return true if at least one path might exist in cpf
+ return rawPaths.stream().anyMatch(cpf::maybeContains);
+ }
+
+ @Override
+ public boolean include(TreeWalk walker) throws IOException {
+ return pathFilter.include(walker) && ANY_DIFF.include(walker);
+ }
+
+ @Override
+ public boolean shouldBeRecursive() {
+ return pathFilter.shouldBeRecursive() || ANY_DIFF.shouldBeRecursive();
+ }
+
+ @Override
+ public ChangedPathTreeFilter clone() {
+ return this;
+ }
+
+ /**
+ * Get the paths this filter matches.
+ *
+ * @return the paths this filter matches.
+ */
+ public List<String> getPaths() {
+ return paths;
+ }
+
+ @SuppressWarnings("nls")
+ @Override
+ public String toString() {
+ return "(CHANGED_PATH(" + pathFilter.toString() + ")" //
+ + " AND " //
+ + ANY_DIFF.toString() + ")";
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/OrTreeFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/OrTreeFilter.java
index 3c18a9f98d..ce2382552b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/OrTreeFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/OrTreeFilter.java
@@ -12,11 +12,14 @@
package org.eclipse.jgit.treewalk.filter;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Collection;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
/**
@@ -116,6 +119,13 @@ public abstract class OrTreeFilter extends TreeFilter {
}
@Override
+ public boolean shouldTreeWalk(RevCommit c, RevWalk rw,
+ MutableBoolean cpfUsed) {
+ return a.shouldTreeWalk(c, rw, cpfUsed)
+ || b.shouldTreeWalk(c, rw, cpfUsed);
+ }
+
+ @Override
public boolean shouldBeRecursive() {
return a.shouldBeRecursive() || b.shouldBeRecursive();
}
@@ -164,6 +174,13 @@ public abstract class OrTreeFilter extends TreeFilter {
}
@Override
+ public boolean shouldTreeWalk(RevCommit c, RevWalk rw,
+ MutableBoolean cpfUsed) {
+ return Arrays.stream(subfilters)
+ .anyMatch(t -> t.shouldTreeWalk(c, rw, cpfUsed));
+ }
+
+ @Override
public boolean shouldBeRecursive() {
for (TreeFilter f : subfilters)
if (f.shouldBeRecursive())
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java
index a9066dc8f8..8159843312 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilter.java
@@ -14,9 +14,12 @@ import java.io.IOException;
import java.util.Optional;
import java.util.Set;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
@@ -210,14 +213,38 @@ public abstract class TreeFilter {
public abstract boolean shouldBeRecursive();
/**
- * If this filter checks that at least one of the paths in a set has been
+ * Return true if the tree entries within this commit require
+ * {@link #include(TreeWalk)} to correctly determine whether they are
+ * interesting to report.
+ * <p>
+ * Otherwise, all tree entries within this commit are UNINTERESTING for this
+ * tree filter.
+ *
+ * @param c
+ * the commit being considered by the TreeFilter.
+ * @param rw
+ * the RevWalk used in retrieving relevant commit data.
+ * @param cpfUsed
+ * if not null, it reports if the changedPathFilter was used in
+ * this method
+ * @return True if the tree entries within c require
+ * {@link #include(TreeWalk)}.
+ * @since 7.3
+ */
+ public boolean shouldTreeWalk(RevCommit c, RevWalk rw,
+ @Nullable MutableBoolean cpfUsed) {
+ return true;
+ }
+
+ /**
+ * If this filter checks that a specific set of paths have all been
* modified, returns that set of paths to be checked against a changed path
* filter. Otherwise, returns empty.
*
* @return a set of paths, or empty
- *
- * @since 6.7
+ * @deprecated use {@code shouldTreeWalk} instead.
*/
+ @Deprecated(since = "7.3")
public Optional<Set<byte[]>> getPathsBestEffort() {
return Optional.empty();
}
@@ -242,4 +269,33 @@ public abstract class TreeFilter {
}
return n.replace('$', '.');
}
+
+ /**
+ * Mutable wrapper to return a boolean in a function parameter.
+ *
+ * @since 7.3
+ */
+ public static class MutableBoolean {
+ private boolean value;
+
+ /**
+ * Return the boolean value.
+ *
+ * @return The state of the internal boolean value.
+ */
+ public boolean get() {
+ return value;
+ }
+
+ void orValue(boolean v) {
+ value = value || v;
+ }
+
+ /**
+ * Reset the boolean value.
+ */
+ public void reset() {
+ value = false;
+ }
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
index 12af374b2e..c8421d6012 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/ChangeIdUtil.java
@@ -86,8 +86,8 @@ public class ChangeIdUtil {
}
}
- private static final Pattern issuePattern = Pattern
- .compile("^(Bug|Issue)[a-zA-Z0-9-]*:.*$"); //$NON-NLS-1$
+ private static final Pattern signedOffByPattern = Pattern
+ .compile("^Signed-off-by:.*$"); //$NON-NLS-1$
private static final Pattern footerPattern = Pattern
.compile("(^[a-zA-Z0-9-]+:(?!//).*$)"); //$NON-NLS-1$
@@ -159,7 +159,7 @@ public class ChangeIdUtil {
int footerFirstLine = indexOfFirstFooterLine(lines);
int insertAfter = footerFirstLine;
for (int i = footerFirstLine; i < lines.length; ++i) {
- if (issuePattern.matcher(lines[i]).matches()) {
+ if (!signedOffByPattern.matcher(lines[i]).matches()) {
insertAfter = i + 1;
continue;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
index 59bbacfa76..6a40fad1db 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -363,6 +363,7 @@ public abstract class FS {
private static FileStoreAttributes getFileStoreAttributes(Path dir) {
FileStore s;
+ CompletableFuture<Optional<FileStoreAttributes>> f = null;
try {
if (Files.exists(dir)) {
s = Files.getFileStore(dir);
@@ -385,7 +386,7 @@ public abstract class FS {
return FALLBACK_FILESTORE_ATTRIBUTES;
}
- CompletableFuture<Optional<FileStoreAttributes>> f = CompletableFuture
+ f = CompletableFuture
.supplyAsync(() -> {
Lock lock = locks.computeIfAbsent(s,
l -> new ReentrantLock());
@@ -455,10 +456,13 @@ public abstract class FS {
}
// fall through and return fallback
} catch (IOException | ExecutionException | CancellationException e) {
+ cancel(f);
LOG.error(e.getMessage(), e);
} catch (TimeoutException | SecurityException e) {
+ cancel(f);
// use fallback
} catch (InterruptedException e) {
+ cancel(f);
LOG.error(e.getMessage(), e);
Thread.currentThread().interrupt();
}
@@ -467,6 +471,13 @@ public abstract class FS {
return FALLBACK_FILESTORE_ATTRIBUTES;
}
+ private static void cancel(
+ CompletableFuture<Optional<FileStoreAttributes>> f) {
+ if (f != null) {
+ f.cancel(true);
+ }
+ }
+
@SuppressWarnings("boxing")
private static Duration measureMinimalRacyInterval(Path dir) {
LOG.debug("{}: start measure minimal racy interval in {}", //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java
index 524126b098..332e65985e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateFormatter.java
@@ -10,10 +10,10 @@
package org.eclipse.jgit.util;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
import java.util.Locale;
-import java.util.TimeZone;
import org.eclipse.jgit.lib.PersonIdent;
@@ -26,9 +26,9 @@ import org.eclipse.jgit.lib.PersonIdent;
*/
public class GitDateFormatter {
- private DateFormat dateTimeInstance;
+ private DateTimeFormatter dateTimeFormat;
- private DateFormat dateTimeInstance2;
+ private DateTimeFormatter dateTimeFormat2;
private final Format format;
@@ -96,30 +96,34 @@ public class GitDateFormatter {
default:
break;
case DEFAULT: // Not default:
- dateTimeInstance = new SimpleDateFormat(
+ dateTimeFormat = DateTimeFormatter.ofPattern(
"EEE MMM dd HH:mm:ss yyyy Z", Locale.US); //$NON-NLS-1$
break;
case ISO:
- dateTimeInstance = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", //$NON-NLS-1$
+ dateTimeFormat = DateTimeFormatter.ofPattern(
+ "yyyy-MM-dd HH:mm:ss Z", //$NON-NLS-1$
Locale.US);
break;
case LOCAL:
- dateTimeInstance = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", //$NON-NLS-1$
+ dateTimeFormat = DateTimeFormatter.ofPattern(
+ "EEE MMM dd HH:mm:ss yyyy", //$NON-NLS-1$
Locale.US);
break;
case RFC:
- dateTimeInstance = new SimpleDateFormat(
+ dateTimeFormat = DateTimeFormatter.ofPattern(
"EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); //$NON-NLS-1$
break;
case SHORT:
- dateTimeInstance = new SimpleDateFormat("yyyy-MM-dd", Locale.US); //$NON-NLS-1$
+ dateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd", //$NON-NLS-1$
+ Locale.US);
break;
case LOCALE:
case LOCALELOCAL:
- SystemReader systemReader = SystemReader.getInstance();
- dateTimeInstance = systemReader.getDateTimeInstance(
- DateFormat.DEFAULT, DateFormat.DEFAULT);
- dateTimeInstance2 = systemReader.getSimpleDateFormat("Z"); //$NON-NLS-1$
+ dateTimeFormat = DateTimeFormatter
+ .ofLocalizedDateTime(FormatStyle.MEDIUM)
+ .withLocale(Locale.US);
+ dateTimeFormat2 = DateTimeFormatter.ofPattern("Z", //$NON-NLS-1$
+ Locale.US);
break;
}
}
@@ -135,39 +139,45 @@ public class GitDateFormatter {
@SuppressWarnings("boxing")
public String formatDate(PersonIdent ident) {
switch (format) {
- case RAW:
- int offset = ident.getTimeZoneOffset();
+ case RAW: {
+ int offset = ident.getZoneOffset().getTotalSeconds();
String sign = offset < 0 ? "-" : "+"; //$NON-NLS-1$ //$NON-NLS-2$
int offset2;
- if (offset < 0)
+ if (offset < 0) {
offset2 = -offset;
- else
+ } else {
offset2 = offset;
- int hours = offset2 / 60;
- int minutes = offset2 % 60;
+ }
+ int minutes = (offset2 / 60) % 60;
+ int hours = offset2 / 60 / 60;
return String.format("%d %s%02d%02d", //$NON-NLS-1$
- ident.getWhen().getTime() / 1000, sign, hours, minutes);
+ ident.getWhenAsInstant().getEpochSecond(), sign, hours,
+ minutes);
+ }
case RELATIVE:
return RelativeDateFormatter.format(ident.getWhenAsInstant());
case LOCALELOCAL:
case LOCAL:
- dateTimeInstance.setTimeZone(SystemReader.getInstance()
- .getTimeZone());
- return dateTimeInstance.format(ident.getWhen());
- case LOCALE:
- TimeZone tz = ident.getTimeZone();
- if (tz == null)
- tz = SystemReader.getInstance().getTimeZone();
- dateTimeInstance.setTimeZone(tz);
- dateTimeInstance2.setTimeZone(tz);
- return dateTimeInstance.format(ident.getWhen()) + " " //$NON-NLS-1$
- + dateTimeInstance2.format(ident.getWhen());
- default:
- tz = ident.getTimeZone();
- if (tz == null)
- tz = SystemReader.getInstance().getTimeZone();
- dateTimeInstance.setTimeZone(ident.getTimeZone());
- return dateTimeInstance.format(ident.getWhen());
+ return dateTimeFormat
+ .withZone(SystemReader.getInstance().getTimeZoneId())
+ .format(ident.getWhenAsInstant());
+ case LOCALE: {
+ ZoneId tz = ident.getZoneId();
+ if (tz == null) {
+ tz = SystemReader.getInstance().getTimeZoneId();
+ }
+ return dateTimeFormat.withZone(tz).format(ident.getWhenAsInstant())
+ + " " //$NON-NLS-1$
+ + dateTimeFormat2.withZone(tz)
+ .format(ident.getWhenAsInstant());
+ }
+ default: {
+ ZoneId tz = ident.getZoneId();
+ if (tz == null) {
+ tz = SystemReader.getInstance().getTimeZoneId();
+ }
+ return dateTimeFormat.withZone(tz).format(ident.getWhenAsInstant());
+ }
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java
index 7d00fcd5ed..acaa1ce563 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitTimeParser.java
@@ -11,6 +11,7 @@ package org.eclipse.jgit.util;
import java.text.MessageFormat;
import java.text.ParseException;
+import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@@ -97,6 +98,40 @@ public class GitTimeParser {
return parse(dateStr, SystemReader.getInstance().civilNow());
}
+ /**
+ * Parses a string into a {@link java.time.Instant} using the default
+ * locale. Since this parser also supports relative formats (e.g.
+ * "yesterday") the caller can specify the reference date. These types of
+ * strings can be parsed:
+ * <ul>
+ * <li>"never"</li>
+ * <li>"now"</li>
+ * <li>"yesterday"</li>
+ * <li>"(x) years|months|weeks|days|hours|minutes|seconds ago"<br>
+ * Multiple specs can be combined like in "2 weeks 3 days ago". Instead of '
+ * ' one can use '.' to separate the words</li>
+ * <li>"yyyy-MM-dd HH:mm:ss Z" (ISO)</li>
+ * <li>"EEE, dd MMM yyyy HH:mm:ss Z" (RFC)</li>
+ * <li>"yyyy-MM-dd"</li>
+ * <li>"yyyy.MM.dd"</li>
+ * <li>"MM/dd/yyyy",</li>
+ * <li>"dd.MM.yyyy"</li>
+ * <li>"EEE MMM dd HH:mm:ss yyyy Z" (DEFAULT)</li>
+ * <li>"EEE MMM dd HH:mm:ss yyyy" (LOCAL)</li>
+ * </ul>
+ *
+ * @param dateStr
+ * the string to be parsed
+ * @return the parsed {@link java.time.Instant}
+ * @throws java.text.ParseException
+ * if the given dateStr was not recognized
+ * @since 7.2
+ */
+ public static Instant parseInstant(String dateStr) throws ParseException {
+ return parse(dateStr).atZone(SystemReader.getInstance().getTimeZoneId())
+ .toInstant();
+ }
+
// Only tests seem to use this method
static LocalDateTime parse(String dateStr, LocalDateTime now)
throws ParseException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java
index 820ac2db91..e3e3e04fd9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SignatureUtils.java
@@ -48,7 +48,7 @@ public final class SignatureUtils {
if (verification.creationDate() != null) {
// Use the creator's timezone for the signature date
PersonIdent dateId = new PersonIdent(creator,
- verification.creationDate());
+ verification.creationDate().toInstant());
result.append(
MessageFormat.format(JGitText.get().verifySignatureMade,
formatter.formatDate(dateId)));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
index 2fbd12dcc5..e381a3bcc9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
@@ -278,6 +278,44 @@ public final class StringUtils {
}
/**
+ * Remove the specified character from beginning and end of a string
+ * <p>
+ * If the character repeats, all copies
+ *
+ * @param str input string
+ * @param c character to remove
+ * @return the input string with c
+ * @since 7.2
+ */
+ public static String trim(String str, char c) {
+ if (str == null || str.length() == 0) {
+ return str;
+ }
+
+ int endPos = str.length()-1;
+ while (endPos >= 0 && str.charAt(endPos) == c) {
+ endPos--;
+ }
+
+ // Whole string is c
+ if (endPos == -1) {
+ return EMPTY;
+ }
+
+ int startPos = 0;
+ while (startPos < endPos && str.charAt(startPos) == c) {
+ startPos++;
+ }
+
+ if (startPos == 0 && endPos == str.length()-1) {
+ // No need to copy
+ return str;
+ }
+
+ return str.substring(startPos, endPos+1);
+ }
+
+ /**
* Appends {@link Constants#DOT_GIT_EXT} unless the given name already ends
* with that suffix.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
index 55cc878e02..0b7c6204f2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
@@ -492,6 +492,36 @@ public abstract class SystemReader {
}
/**
+ * Gets the directory denoted by environment variable XDG_CACHE_HOME. If
+ * the variable is not set or empty, return a path for
+ * {@code $HOME/.cache}.
+ *
+ * @param fileSystem
+ * {@link FS} to get the user's home directory
+ * @return a {@link Path} denoting the directory, which may exist or not, or
+ * {@code null} if the environment variable is not set and there is
+ * no home directory, or the path is invalid.
+ * @since 7.3
+ */
+ public Path getXdgCacheDirectory(FS fileSystem) {
+ String cacheHomePath = getenv(Constants.XDG_CACHE_HOME);
+ if (StringUtils.isEmptyOrNull(cacheHomePath)) {
+ File home = fileSystem.userHome();
+ if (home == null) {
+ return null;
+ }
+ cacheHomePath = new File(home, ".cache").getAbsolutePath(); //$NON-NLS-1$
+ }
+ try {
+ return Paths.get(cacheHomePath);
+ } catch (InvalidPathException e) {
+ LOG.error(JGitText.get().logXDGCacheHomeInvalid, cacheHomePath,
+ e);
+ }
+ return null;
+ }
+
+ /**
* Update config and its parents if they seem modified
*
* @param config
@@ -523,7 +553,7 @@ public abstract class SystemReader {
*
* @deprecated Use {@link #now()}
*/
- @Deprecated
+ @Deprecated(since = "7.1")
public abstract long getCurrentTime();
/**
@@ -569,7 +599,7 @@ public abstract class SystemReader {
*
* @deprecated Use {@link #getTimeZoneAt(Instant)} instead.
*/
- @Deprecated
+ @Deprecated(since = "7.1")
public abstract int getTimezone(long when);
/**
@@ -592,7 +622,7 @@ public abstract class SystemReader {
*
* @deprecated Use {@link #getTimeZoneId()}
*/
- @Deprecated
+ @Deprecated(since = "7.1")
public TimeZone getTimeZone() {
return TimeZone.getDefault();
}
diff --git a/pom.xml b/pom.xml
index 4fb22188d8..eb01960aff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
<packaging>pom</packaging>
- <version>7.2.0-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
<name>JGit - Parent</name>
<url>${jgit-url}</url>
@@ -33,7 +33,7 @@
</description>
<scm>
- <url>https://eclipse.gerrithub.io/plugins/gitiles/eclipse-jgit/jgit</url>
+ <url>https://eclipse.gerrithub.io/admin/repos/eclipse-jgit/jgit</url>
<connection>scm:git:https://eclipse.gerrithub.io/eclipse-jgit/jgit</connection>
</scm>
@@ -118,9 +118,9 @@
<project.build.outputTimestamp>${commit.time.iso}</project.build.outputTimestamp>
- <jgit-last-release-version>7.1.0.202411261347-r</jgit-last-release-version>
+ <jgit-last-release-version>7.3.0.202506031305-r</jgit-last-release-version>
<ant-version>1.10.15</ant-version>
- <apache-sshd-version>2.14.0</apache-sshd-version>
+ <apache-sshd-version>2.15.0</apache-sshd-version>
<jsch-version>0.1.55</jsch-version>
<jzlib-version>1.1.3</jzlib-version>
<javaewah-version>1.2.3</javaewah-version>
@@ -130,25 +130,25 @@
<commons-compress-version>1.27.1</commons-compress-version>
<osgi-core-version>6.0.0</osgi-core-version>
<servlet-api-version>6.1.0</servlet-api-version>
- <jetty-version>12.0.16</jetty-version>
- <japicmp-version>0.23.0</japicmp-version>
+ <jetty-version>12.0.22</jetty-version>
+ <japicmp-version>0.23.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>
- <gson-version>2.11.0</gson-version>
- <bouncycastle-version>1.79</bouncycastle-version>
- <spotbugs-maven-plugin-version>4.8.6.6</spotbugs-maven-plugin-version>
- <maven-project-info-reports-plugin-version>3.8.0</maven-project-info-reports-plugin-version>
+ <gson-version>2.13.1</gson-version>
+ <bouncycastle-version>1.81</bouncycastle-version>
+ <spotbugs-maven-plugin-version>4.9.3.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.2</maven-surefire-plugin-version>
+ <maven-surefire-plugin-version>3.5.3</maven-surefire-plugin-version>
<maven-surefire-report-plugin-version>${maven-surefire-plugin-version}</maven-surefire-report-plugin-version>
- <maven-compiler-plugin-version>3.13.0</maven-compiler-plugin-version>
+ <maven-compiler-plugin-version>3.14.0</maven-compiler-plugin-version>
<plexus-compiler-version>2.13.0</plexus-compiler-version>
<hamcrest-version>2.2</hamcrest-version>
- <assertj-version>3.27.0</assertj-version>
- <jna-version>5.15.0</jna-version>
- <byte-buddy-version>1.15.11</byte-buddy-version>
+ <assertj-version>3.27.3</assertj-version>
+ <jna-version>5.17.0</jna-version>
+ <byte-buddy-version>1.17.5</byte-buddy-version>
<!-- Properties to enable jacoco code coverage analysis -->
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
@@ -208,7 +208,7 @@
<plugin>
<artifactId>maven-clean-plugin</artifactId>
- <version>3.4.0</version>
+ <version>3.4.1</version>
</plugin>
<plugin>
@@ -305,7 +305,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
- <version>0.8.12</version>
+ <version>0.8.13</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -337,12 +337,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
- <version>3.1.3</version>
+ <version>3.1.4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
- <version>3.1.3</version>
+ <version>3.1.4</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -357,7 +357,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
- <version>3.4.1</version>
+ <version>3.5.0</version>
</plugin>
<plugin>
<groupId>org.eclipse.dash</groupId>
@@ -372,7 +372,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-artifact-plugin</artifactId>
- <version>3.5.3</version>
+ <version>3.6.0</version>
<configuration>
<ignore>**/*cyclonedx.json</ignore>
<reproducible>true</reproducible>
@@ -623,7 +623,7 @@
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
- <version>9.0.1</version>
+ <version>9.0.2</version>
<executions>
<execution>
<id>get-the-git-infos</id>
@@ -642,7 +642,7 @@
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
- <version>4.0.1</version>
+ <version>4.2.0</version>
<dependencies>
<dependency>
<groupId>org.apache.groovy</groupId>
@@ -886,7 +886,7 @@
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.17.1</version>
+ <version>1.18.0</version>
</dependency>
<dependency>
@@ -898,13 +898,13 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
- <version>2.18.0</version>
+ <version>2.19.0</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
- <version>1.3.4</version>
+ <version>1.3.5</version>
</dependency>
<dependency>
@@ -1007,7 +1007,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
- <version>5.14.2</version>
+ <version>5.18.0</version>
</dependency>
<dependency>
@@ -1116,7 +1116,7 @@
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>ecj</artifactId>
- <version>3.38.0</version>
+ <version>3.40.0</version>
</dependency>
</dependencies>
</plugin>
diff --git a/tools/BUILD b/tools/BUILD
index 844f0049e6..379a9bd34c 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -54,7 +54,7 @@ errorprone_checks = [
"-Xep:ArrayHashCode:ERROR",
"-Xep:ArraysAsListPrimitiveArray:ERROR",
"-Xep:ArrayToString:ERROR",
- "-Xep:AssertEqualsArgumentOrderChecker:ERROR",
+ "-Xep:AssertEqualsArgumentOrderChecker:WARN",
"-Xep:AssertionFailureIgnored:WARN",
"-Xep:AsyncCallableReturnsNull:ERROR",
"-Xep:AsyncFunctionReturnsNull:ERROR",
diff --git a/tools/bazlets.bzl b/tools/bazlets.bzl
deleted file mode 100644
index f089af473a..0000000000
--- a/tools/bazlets.bzl
+++ /dev/null
@@ -1,18 +0,0 @@
-load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
-
-NAME = "com_googlesource_gerrit_bazlets"
-
-def load_bazlets(
- commit,
- local_path = None):
- if not local_path:
- git_repository(
- name = NAME,
- remote = "https://gerrit.googlesource.com/bazlets",
- commit = commit,
- )
- else:
- native.local_repository(
- name = NAME,
- path = local_path,
- )