Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/.settings/.api_filters88
-rw-r--r--org.eclipse.jgit/META-INF/MANIFEST.MF122
-rw-r--r--org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit/pom.xml4
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java60
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java45
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java17
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java30
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java35
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/errors/IncorrectObjectTypeException.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/WildMatcher.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchLeader.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchReplica.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LagCheck.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java25
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java23
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/StageBuilder.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackCompactor.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReader.java25
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java19
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReftableDatabase.java24
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRepository.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java20
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java32
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java97
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObjectCache.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/WindowCache.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BinaryDelta.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaTask.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaWindow.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java168
-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/transport/http/NetscapeCookieFile.java488
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileCache.java106
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java29
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java43
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java16
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java28
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java43
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java55
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/nls/GlobalBundleCache.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/nls/TranslationBundle.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMapMerger.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java20
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapCalculator.java136
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmappedReachabilityChecker.java120
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java147
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PedestrianReachabilityChecker.java96
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java90
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java26
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java44
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/RevFlagFilter.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java28
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleWriter.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java46
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java20
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java23
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java192
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java20
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java84
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java14
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java119
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PostReceiveHook.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHook.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PreReceiveHook.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV0Parser.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java113
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java135
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/RefFilter.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java43
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java264
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java16
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java186
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/FileResolver.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/ReceivePackFactory.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/RepositoryResolver.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/UploadPackFactory.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java6
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java37
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilterMarker.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java12
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java43
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java19
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java42
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/GSSManagerFactory.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java25
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/LRUMap.java83
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java64
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java22
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/References.java67
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SimpleLruCache.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java9
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java38
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/io/ThrowingPrintWriter.java10
165 files changed, 3506 insertions, 1263 deletions
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
index bb37dd8c8a..5ca7c0f664 100644
--- a/org.eclipse.jgit/.settings/.api_filters
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -3,8 +3,8 @@
<resource path="META-INF/MANIFEST.MF">
<filter id="924844039">
<message_arguments>
- <message_argument value="5.3.3"/>
- <message_argument value="5.3.0"/>
+ <message_argument value="5.4.1"/>
+ <message_argument value="5.4.0"/>
</message_arguments>
</filter>
</resource>
@@ -28,20 +28,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/jgit/errors/PackInvalidException.java" type="org.eclipse.jgit.errors.PackInvalidException">
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="4.5.7"/>
- <message_argument value="PackInvalidException(File, Throwable)"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="4.5.7"/>
- <message_argument value="PackInvalidException(String, Throwable)"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
<filter id="1142947843">
<message_arguments>
@@ -62,62 +48,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/jgit/storage/pack/PackConfig.java" type="org.eclipse.jgit.storage.pack.PackConfig">
- <filter id="336658481">
- <message_arguments>
- <message_argument value="org.eclipse.jgit.storage.pack.PackConfig"/>
- <message_argument value="DEFAULT_MINSIZE_PREVENT_RACY_PACK"/>
- </message_arguments>
- </filter>
- <filter id="336658481">
- <message_arguments>
- <message_argument value="org.eclipse.jgit.storage.pack.PackConfig"/>
- <message_argument value="DEFAULT_WAIT_PREVENT_RACY_PACK"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="DEFAULT_MINSIZE_PREVENT_RACY_PACK"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="DEFAULT_WAIT_PREVENT_RACY_PACK"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="doWaitPreventRacyPack(long)"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="getMinSizePreventRacyPack()"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="isWaitPreventRacyPack()"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="setMinSizePreventRacyPack(long)"/>
- </message_arguments>
- </filter>
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="setWaitPreventRacyPack(boolean)"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java" type="org.eclipse.jgit.treewalk.WorkingTreeIterator">
<filter id="1142947843">
<message_arguments>
@@ -141,6 +71,12 @@
</filter>
</resource>
<resource path="src/org/eclipse/jgit/util/FS.java" type="org.eclipse.jgit.util.FS">
+ <filter id="338792546">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.util.FS"/>
+ <message_argument value="getFsTimerResolution(Path)"/>
+ </message_arguments>
+ </filter>
<filter id="1142947843">
<message_arguments>
<message_argument value="5.1.9"/>
@@ -188,14 +124,6 @@
</message_arguments>
</filter>
</resource>
- <resource path="src/org/eclipse/jgit/util/FileUtils.java" type="org.eclipse.jgit.util.FileUtils">
- <filter id="1142947843">
- <message_arguments>
- <message_argument value="5.1.8"/>
- <message_argument value="touch(Path)"/>
- </message_arguments>
- </filter>
- </resource>
<resource path="src/org/eclipse/jgit/util/SimpleLruCache.java" type="org.eclipse.jgit.util.SimpleLruCache">
<filter id="1109393411">
<message_arguments>
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index d4226925bd..493cab4d2e 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -3,12 +3,12 @@ Bundle-ManifestVersion: 2
Bundle-Name: %plugin_name
Automatic-Module-Name: org.eclipse.jgit
Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 5.3.3.qualifier
+Bundle-Version: 5.4.1.qualifier
Bundle-Localization: plugin
Bundle-Vendor: %provider_name
Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.jgit.annotations;version="5.3.3",
- org.eclipse.jgit.api;version="5.3.3";
+Export-Package: org.eclipse.jgit.annotations;version="5.4.1",
+ org.eclipse.jgit.api;version="5.4.1";
uses:="org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.diff,
@@ -22,53 +22,53 @@ Export-Package: org.eclipse.jgit.annotations;version="5.3.3",
org.eclipse.jgit.submodule,
org.eclipse.jgit.transport,
org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="5.3.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="5.3.3",
- org.eclipse.jgit.blame;version="5.3.3";
+ org.eclipse.jgit.api.errors;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.errors",
+ org.eclipse.jgit.attributes;version="5.4.1",
+ org.eclipse.jgit.blame;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.diff",
- org.eclipse.jgit.diff;version="5.3.3";
+ org.eclipse.jgit.diff;version="5.4.1";
uses:="org.eclipse.jgit.patch,
org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util",
- org.eclipse.jgit.dircache;version="5.3.3";
+ org.eclipse.jgit.dircache;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util,
org.eclipse.jgit.events,
org.eclipse.jgit.attributes",
- org.eclipse.jgit.errors;version="5.3.3";
+ org.eclipse.jgit.errors;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.internal.storage.pack,
org.eclipse.jgit.transport,
org.eclipse.jgit.dircache",
- org.eclipse.jgit.events;version="5.3.3";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="5.3.3",
- org.eclipse.jgit.gitrepo;version="5.3.3";
+ org.eclipse.jgit.events;version="5.4.1";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.fnmatch;version="5.4.1",
+ org.eclipse.jgit.gitrepo;version="5.4.1";
uses:="org.eclipse.jgit.api,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.xml.sax.helpers,
org.xml.sax",
- org.eclipse.jgit.gitrepo.internal;version="5.3.3";x-internal:=true,
- org.eclipse.jgit.hooks;version="5.3.3";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="5.3.3",
- org.eclipse.jgit.ignore.internal;version="5.3.3";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="5.3.3";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.fsck;version="5.3.3";x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.ketch;version="5.3.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.revwalk;version="5.3.3";x-internal:=true,
- org.eclipse.jgit.internal.storage.dfs;version="5.3.3";
+ org.eclipse.jgit.gitrepo.internal;version="5.4.1";x-internal:=true,
+ org.eclipse.jgit.hooks;version="5.4.1";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.ignore;version="5.4.1",
+ org.eclipse.jgit.ignore.internal;version="5.4.1";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal;version="5.4.1";x-friends:="org.eclipse.jgit.test,org.eclipse.jgit.http.test",
+ org.eclipse.jgit.internal.fsck;version="5.4.1";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.ketch;version="5.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.revwalk;version="5.4.1";x-internal:=true,
+ org.eclipse.jgit.internal.storage.dfs;version="5.4.1";
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="5.3.3";
+ org.eclipse.jgit.internal.storage.file;version="5.4.1";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.junit,
org.eclipse.jgit.junit.http,
@@ -77,18 +77,19 @@ Export-Package: org.eclipse.jgit.annotations;version="5.3.3",
org.eclipse.jgit.pgm,
org.eclipse.jgit.pgm.test,
org.eclipse.jgit.ssh.apache",
- org.eclipse.jgit.internal.storage.io;version="5.3.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.pack;version="5.3.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftable;version="5.3.3";
+ org.eclipse.jgit.internal.storage.io;version="5.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.pack;version="5.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.storage.reftable;version="5.4.1";
x-friends:="org.eclipse.jgit.http.test,
org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftree;version="5.3.3";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.submodule;version="5.3.3";x-internal:=true,
- org.eclipse.jgit.internal.transport.parser;version="5.3.3";x-friends:="org.eclipse.jgit.http.server,org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.ssh;version="5.3.3";x-friends:="org.eclipse.jgit.ssh.apache",
- org.eclipse.jgit.lib;version="5.3.3";
+ org.eclipse.jgit.internal.storage.reftree;version="5.4.1";x-friends:="org.eclipse.jgit.junit,org.eclipse.jgit.test,org.eclipse.jgit.pgm",
+ org.eclipse.jgit.internal.submodule;version="5.4.1";x-internal:=true,
+ org.eclipse.jgit.internal.transport.http;version="5.4.1";x-friends:="org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.transport.parser;version="5.4.1";x-friends:="org.eclipse.jgit.http.server,org.eclipse.jgit.test",
+ org.eclipse.jgit.internal.transport.ssh;version="5.4.1";x-friends:="org.eclipse.jgit.ssh.apache",
+ org.eclipse.jgit.lib;version="5.4.1";
uses:="org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util,
@@ -98,33 +99,33 @@ Export-Package: org.eclipse.jgit.annotations;version="5.3.3",
org.eclipse.jgit.treewalk,
org.eclipse.jgit.transport,
org.eclipse.jgit.submodule",
- org.eclipse.jgit.lib.internal;version="5.3.3";x-internal:=true,
- org.eclipse.jgit.merge;version="5.3.3";
+ org.eclipse.jgit.lib.internal;version="5.4.1";x-internal:=true,
+ org.eclipse.jgit.merge;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.diff,
org.eclipse.jgit.dircache,
org.eclipse.jgit.api",
- org.eclipse.jgit.nls;version="5.3.3",
- org.eclipse.jgit.notes;version="5.3.3";
+ org.eclipse.jgit.nls;version="5.4.1",
+ org.eclipse.jgit.notes;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="5.3.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="5.3.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="5.3.3";
+ org.eclipse.jgit.patch;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.diff",
+ org.eclipse.jgit.revplot;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.revwalk",
+ org.eclipse.jgit.revwalk;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.diff,
org.eclipse.jgit.revwalk.filter",
- org.eclipse.jgit.revwalk.filter;version="5.3.3";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="5.3.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="5.3.3";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="5.3.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
- org.eclipse.jgit.transport;version="5.3.3";
+ org.eclipse.jgit.revwalk.filter;version="5.4.1";uses:="org.eclipse.jgit.revwalk,org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.file;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.util",
+ org.eclipse.jgit.storage.pack;version="5.4.1";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.submodule;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.treewalk.filter,org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.transport;version="5.4.1";
uses:="org.eclipse.jgit.transport.resolver,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.internal.storage.pack,
@@ -137,39 +138,40 @@ Export-Package: org.eclipse.jgit.annotations;version="5.3.3",
org.eclipse.jgit.transport.http,
org.eclipse.jgit.errors,
org.eclipse.jgit.storage.pack",
- org.eclipse.jgit.transport.http;version="5.3.3";uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="5.3.3";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
- org.eclipse.jgit.treewalk;version="5.3.3";
+ org.eclipse.jgit.transport.http;version="5.4.1";uses:="javax.net.ssl",
+ org.eclipse.jgit.transport.resolver;version="5.4.1";uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
+ org.eclipse.jgit.treewalk;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.attributes,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util,
org.eclipse.jgit.dircache",
- org.eclipse.jgit.treewalk.filter;version="5.3.3";uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="5.3.3";
+ org.eclipse.jgit.treewalk.filter;version="5.4.1";uses:="org.eclipse.jgit.treewalk",
+ org.eclipse.jgit.util;version="5.4.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.transport.http,
org.eclipse.jgit.storage.file,
org.ietf.jgss",
- org.eclipse.jgit.util.io;version="5.3.3",
- org.eclipse.jgit.util.sha1;version="5.3.3",
- org.eclipse.jgit.util.time;version="5.3.3"
+ org.eclipse.jgit.util.io;version="5.4.1",
+ org.eclipse.jgit.util.sha1;version="5.4.1",
+ org.eclipse.jgit.util.time;version="5.4.1"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
com.jcraft.jsch;version="[0.1.37,0.2.0)",
javax.crypto,
javax.net.ssl,
- org.bouncycastle;version="[1.60.0,2.0.0)",
- org.bouncycastle.bcpg;version="[1.60.0,2.0.0)",
- org.bouncycastle.gpg;version="[1.60.0,2.0.0)",
- org.bouncycastle.gpg.keybox;version="[1.60.0,2.0.0)",
- org.bouncycastle.jce.provider;version="[1.60.0,2.0.0)",
- org.bouncycastle.openpgp;version="[1.60.0,2.0.0)",
- org.bouncycastle.openpgp.jcajce;version="[1.60.0,2.0.0)",
- org.bouncycastle.openpgp.operator;version="[1.60.0,2.0.0)",
- org.bouncycastle.openpgp.operator.jcajce;version="[1.60.0,2.0.0)",
- org.bouncycastle.util.encoders;version="[1.60.0,2.0.0)",
+ org.bouncycastle;version="[1.61.0,2.0.0)",
+ org.bouncycastle.bcpg;version="[1.61.0,2.0.0)",
+ org.bouncycastle.gpg;version="[1.61.0,2.0.0)",
+ org.bouncycastle.gpg.keybox;version="[1.61.0,2.0.0)",
+ org.bouncycastle.gpg.keybox.jcajce;version="[1.61.0,2.0.0)",
+ org.bouncycastle.jce.provider;version="[1.61.0,2.0.0)",
+ org.bouncycastle.openpgp;version="[1.61.0,2.0.0)",
+ org.bouncycastle.openpgp.jcajce;version="[1.61.0,2.0.0)",
+ org.bouncycastle.openpgp.operator;version="[1.61.0,2.0.0)",
+ org.bouncycastle.openpgp.operator.jcajce;version="[1.61.0,2.0.0)",
+ org.bouncycastle.util.encoders;version="[1.61.0,2.0.0)",
org.slf4j;version="[1.7.0,2.0.0)",
org.xml.sax,
org.xml.sax.helpers
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index e3fd47d5c7..e21d20789b 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: 5.3.3.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="5.3.3.qualifier";roots="."
+Bundle-Version: 5.4.1.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="5.4.1.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index 6097858185..1856716494 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -53,7 +53,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>5.3.3-SNAPSHOT</version>
+ <version>5.4.1-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit</artifactId>
@@ -115,7 +115,7 @@
<includes>
<include>plugin.properties</include>
<include>about.html</include>
- <include>META-INF/eclipse.inf</include>
+ <include>META-INF/eclipse.inf</include>
</includes>
</resource>
<resource>
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 91136620c4..a10d1d7ed9 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -55,7 +55,7 @@ cannotBeCombined=Cannot be combined.
cannotBeRecursiveWhenTreesAreIncluded=TreeWalk shouldn't be recursive when tree objects are included.
cannotChangeActionOnComment=Cannot change action on comment line in git-rebase-todo file, old action: {0}, new action: {1}.
cannotChangeToComment=Cannot change a non-comment line to a comment line.
-cannotCheckoutFromUnbornBranch=Cannot checkout from unborn branch
+cannotCheckoutFromUnbornBranch=Cannot check out from unborn branch
cannotCheckoutOursSwitchBranch=Checking out ours/theirs is only possible when checking out index, not when switching branches.
cannotCombineSquashWithNoff=Cannot combine --squash with --no-ff.
cannotCombineTreeFilterWithRevFilter=Cannot combine TreeFilter {0} with RevFilter {1}.
@@ -141,6 +141,7 @@ configSubsectionContainsNewline=config subsection name contains newline
configSubsectionContainsNullByte=config subsection name contains byte 0x00
configValueContainsNullByte=config value contains byte 0x00
configHandleIsStale=config file handle is stale, {0}. retry
+configHandleMayBeLocked=config file handle may be locked by other process, {0}. retry
connectionFailed=connection failed
connectionTimeOut=Connection time out: {0}
contextMustBeNonNegative=context must be >= 0
@@ -177,8 +178,8 @@ corruptObjectInvalidType=invalid type
corruptObjectInvalidType2=invalid type {0}
corruptObjectMalformedHeader=malformed header: {0}
corruptObjectMissingEmail=missing email
-corruptObjectNameContainsByte=name contains byte 0x%x
-corruptObjectNameContainsChar=name contains '%c'
+corruptObjectNameContainsByte=byte 0x%x not allowed in Windows filename
+corruptObjectNameContainsChar=char '%c' not allowed in Windows filename
corruptObjectNameContainsNullByte=name contains byte 0x00
corruptObjectNameContainsSlash=name contains '/'
corruptObjectNameDot=invalid name '.'
@@ -210,6 +211,10 @@ couldNotDeleteTemporaryIndexFileShouldNotHappen=Could not delete temporary index
couldNotGetAdvertisedRef=Remote {0} did not advertise Ref for branch {1}. This Ref may not exist in the remote or may be hidden by permission settings.
couldNotGetRepoStatistics=Could not get repository statistics
couldNotLockHEAD=Could not lock HEAD
+couldNotFindTabInLine=Could not find tab in line {0}. Tab is the mandatory separator for the Netscape Cookie File Format.
+couldNotFindSixTabsInLine=Could not find 6 tabs but only {0} in line '{1}'. 7 tab separated columns per line are mandatory for the Netscape Cookie File Format.
+couldNotPersistCookies=Could not persist received cookies in file ''{0}''
+couldNotReadCookieFile=Could not read cookie file ''{0}''
couldNotReadIndexInOneGo=Could not read index in one go, only {0} out of {1} read
couldNotReadObjectWhileParsingCommit=Could not read an object while parsing commit {0}
couldNotRenameDeleteOldIndex=Could not rename delete old index
@@ -333,6 +338,7 @@ gpgNoKeyring=neither pubring.kbx nor secring.gpg files found
gpgNoKeyInLegacySecring=no matching secret key found in legacy secring.gpg for key or user id: {0}
gpgNoPublicKeyFound=Unable to find a public-key with key or user id: {0}
gpgNoSecretKeyForPublicKey=unable to find associated secret key for public key: {0}
+gpgNotASigningKey=Secret key ({0}) is not suitable for signing
gpgKeyInfo=GPG Key (fingerprint {0})
gpgSigningCancelled=Signing was cancelled
headRequiredToStash=HEAD required to stash local changes
@@ -459,6 +465,7 @@ mismatchOffset=mismatch offset for object {0}
mismatchCRC=mismatch CRC for object {0}
missingAccesskey=Missing accesskey.
missingConfigurationForKey=No value for key {0} found in configuration
+missingCookieFile=Configured http.cookieFile ''{0}'' is missing
missingCRC=missing CRC for object {0}
missingDeltaBase=delta base
missingForwardImageInGITBinaryPatch=Missing forward-image in GIT binary patch
@@ -632,6 +639,7 @@ rewinding=Rewinding to commit {0}
s3ActionDeletion=Deletion
s3ActionReading=Reading
s3ActionWriting=Writing
+searchForReachableBranches=Finding reachable branches
saveFileStoreAttributesFailed=Saving measured FileStore attributes to user config failed
searchForReuse=Finding sources
searchForSizes=Getting sizes
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
index 65b72f7d95..c9dd547b49 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CherryPickCommand.java
@@ -157,8 +157,8 @@ public class CherryPickCommand extends GitCommand<CherryPickResult> {
merger.setCommitNames(new String[] { "BASE", ourName, //$NON-NLS-1$
cherryPickName });
if (merger.merge(newHead, srcCommit)) {
- if (AnyObjectId.equals(newHead.getTree().getId(), merger
- .getResultTreeId()))
+ if (AnyObjectId.isEqual(newHead.getTree().getId(),
+ merger.getResultTreeId()))
continue;
DirCacheCheckout dco = new DirCacheCheckout(repo,
newHead.getTree(), repo.lockDirCache(),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
index 61d51cc913..b55987ead4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
@@ -282,7 +282,7 @@ public class CommitCommand extends GitCommand<RevCommit> {
ru.setRefLogMessage(reflogComment, false);
} else {
String prefix = amend ? "commit (amend): " //$NON-NLS-1$
- : parents.size() == 0 ? "commit (initial): " //$NON-NLS-1$
+ : parents.isEmpty() ? "commit (initial): " //$NON-NLS-1$
: "commit: "; //$NON-NLS-1$
ru.setRefLogMessage(prefix + revCommit.getShortMessage(),
false);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
index 31e7281d64..c3feaeffca 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteBranchCommand.java
@@ -46,6 +46,7 @@ package org.eclipse.jgit.api;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -188,8 +189,7 @@ public class DeleteBranchCommand extends GitCommand<List<String>> {
public DeleteBranchCommand setBranchNames(String... branchnames) {
checkCallable();
this.branchNames.clear();
- for (String branch : branchnames)
- this.branchNames.add(branch);
+ this.branchNames.addAll(Arrays.asList(branchnames));
return this;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java
index 63a090cafc..1970240621 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DeleteTagCommand.java
@@ -45,6 +45,7 @@ package org.eclipse.jgit.api;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -135,8 +136,7 @@ public class DeleteTagCommand extends GitCommand<List<String>> {
public DeleteTagCommand setTags(String... tags) {
checkCallable();
this.tags.clear();
- for (String tagName : tags)
- this.tags.add(tagName);
+ this.tags.addAll(Arrays.asList(tags));
return this;
}
}
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 a484742e08..9ad77e65fd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
@@ -63,8 +63,7 @@ import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.InvalidPatternException;
import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.ignore.internal.IMatcher;
-import org.eclipse.jgit.ignore.internal.PathMatcher;
+import org.eclipse.jgit.fnmatch.FileNameMatcher;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
@@ -102,14 +101,19 @@ public class DescribeCommand extends GitCommand<String> {
private boolean longDesc;
/**
- * Pattern matchers to be applied to tags under consideration
+ * Pattern matchers to be applied to tags under consideration.
*/
- private List<IMatcher> matchers = new ArrayList<>();
+ private List<FileNameMatcher> matchers = new ArrayList<>();
/**
- * Whether to use all tags (incl. lightweight) or not
+ * Whether to use all tags (incl. lightweight) or not.
*/
- private boolean useTags = false;
+ private boolean useTags;
+
+ /**
+ * Whether to show a uniquely abbreviated commit hash as a fallback or not.
+ */
+ private boolean always;
/**
* Constructor for DescribeCommand.
@@ -197,6 +201,21 @@ public class DescribeCommand extends GitCommand<String> {
return this;
}
+ /**
+ * Always describe the commit by eventually falling back to a uniquely
+ * abbreviated commit hash if no other name matches.
+ *
+ * @param always
+ * <code>true</code> enables falling back to a uniquely
+ * abbreviated commit hash
+ * @return {@code this}
+ * @since 5.4
+ */
+ public DescribeCommand setAlways(boolean always) {
+ this.always = always;
+ return this;
+ }
+
private String longDescription(Ref tag, int depth, ObjectId tip)
throws IOException {
return String.format(
@@ -222,7 +241,7 @@ public class DescribeCommand extends GitCommand<String> {
*/
public DescribeCommand setMatch(String... patterns) throws InvalidPatternException {
for (String p : patterns) {
- matchers.add(PathMatcher.createPathMatcher(p, null, false));
+ matchers.add(new FileNameMatcher(p, null));
}
return this;
}
@@ -246,18 +265,24 @@ public class DescribeCommand extends GitCommand<String> {
};
private Optional<Ref> getBestMatch(List<Ref> tags) {
- if (tags == null || tags.size() == 0) {
+ if (tags == null || tags.isEmpty()) {
return Optional.empty();
- } else if (matchers.size() == 0) {
+ } else if (matchers.isEmpty()) {
Collections.sort(tags, TAG_TIE_BREAKER);
return Optional.of(tags.get(0));
} else {
// 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();
- for (IMatcher matcher : matchers) {
+ for (FileNameMatcher matcher : matchers) {
Stream<Ref> m = tags.stream().filter(
- tag -> matcher.matches(tag.getName(), false, false));
+ tag -> {
+ matcher.append(
+ tag.getName().substring(R_TAGS.length()));
+ boolean result = matcher.isMatch();
+ matcher.reset();
+ return result;
+ });
matchingTags = Stream.of(matchingTags, m).flatMap(i -> i);
}
return matchingTags.sorted(TAG_TIE_BREAKER).findFirst();
@@ -399,15 +424,12 @@ public class DescribeCommand extends GitCommand<String> {
}
// if all the nodes are dominated by all the tags, the walk stops
- if (candidates.isEmpty())
- return null;
+ if (candidates.isEmpty()) {
+ return always ? w.getObjectReader().abbreviate(target).name() : null;
+ }
- Candidate best = Collections.min(candidates, new Comparator<Candidate>() {
- @Override
- public int compare(Candidate o1, Candidate o2) {
- return o1.depth - o2.depth;
- }
- });
+ Candidate best = Collections.min(candidates,
+ (Candidate o1, Candidate o2) -> o1.depth - o2.depth);
return best.describe(target);
} catch (IOException e) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
index 400a7dfe48..835e7b5fd2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/Git.java
@@ -43,6 +43,8 @@
*/
package org.eclipse.jgit.api;
+import static java.util.Objects.requireNonNull;
+
import java.io.File;
import java.io.IOException;
@@ -220,9 +222,7 @@ public class Git implements AutoCloseable {
}
Git(Repository repo, boolean closeRepo) {
- if (repo == null)
- throw new NullPointerException();
- this.repo = repo;
+ this.repo = requireNonNull(repo);
this.closeRepo = closeRepo;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
index 29a51a0f02..e0eafc7533 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListBranchCommand.java
@@ -53,7 +53,6 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -134,12 +133,8 @@ public class ListBranchCommand extends GitCommand<List<Ref>> {
throw new JGitInternalException(e.getMessage(), e);
}
- Collections.sort(resultRefs, new Comparator<Ref>() {
- @Override
- public int compare(Ref o1, Ref o2) {
- return o1.getName().compareTo(o2.getName());
- }
- });
+ Collections.sort(resultRefs,
+ (Ref o1, Ref o2) -> o1.getName().compareTo(o2.getName()));
setCallable(false);
return resultRefs;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java
index 01c1991846..c894d056a0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ListTagCommand.java
@@ -45,7 +45,6 @@ package org.eclipse.jgit.api;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import org.eclipse.jgit.api.errors.GitAPIException;
@@ -87,12 +86,8 @@ public class ListTagCommand extends GitCommand<List<Ref>> {
} catch (IOException e) {
throw new JGitInternalException(e.getMessage(), e);
}
- Collections.sort(tags, new Comparator<Ref>() {
- @Override
- public int compare(Ref o1, Ref o2) {
- return o1.getName().compareTo(o2.getName());
- }
- });
+ Collections.sort(tags,
+ (Ref o1, Ref o2) -> o1.getName().compareTo(o2.getName()));
setCallable(false);
return tags;
}
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 cf3d35fe89..66de8ae131 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java
@@ -133,7 +133,7 @@ public class LogCommand extends GitCommand<Iterable<RevCommit>> {
@Override
public Iterable<RevCommit> call() throws GitAPIException, NoHeadException {
checkCallable();
- if (pathFilters.size() > 0)
+ if (!pathFilters.isEmpty())
walk.setTreeFilter(AndTreeFilter.create(
PathFilterGroup.create(pathFilters), TreeFilter.ANY_DIFF));
if (skip > -1 && maxCount > -1)
@@ -282,13 +282,11 @@ public class LogCommand extends GitCommand<Iterable<RevCommit>> {
RevCommit commit = null;
try {
commit = walk.parseCommit(objectId);
- } catch (MissingObjectException e) {
- // ignore: the ref points to an object that does not exist;
- // it should be ignored as traversal starting point.
- } catch (IncorrectObjectTypeException e) {
- // ignore: the ref points to an object that is not a commit
- // (e.g. a tree or a blob);
- // it should be ignored as traversal starting point.
+ } catch (MissingObjectException | IncorrectObjectTypeException e) {
+ // ignore as traversal starting point:
+ // - the ref points to an object that does not exist
+ // - the ref points to an object that is not a commit (e.g. a
+ // tree or a blob)
}
if (commit != null)
add(commit);
@@ -348,9 +346,7 @@ public class LogCommand extends GitCommand<Iterable<RevCommit>> {
} else
walk.markUninteresting(walk.lookupCommit(start));
return this;
- } catch (MissingObjectException e) {
- throw e;
- } catch (IncorrectObjectTypeException e) {
+ } catch (MissingObjectException | IncorrectObjectTypeException e) {
throw e;
} catch (IOException e) {
throw new JGitInternalException(MessageFormat.format(
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 f0ad29db49..bdb2d1bbc5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PullCommand.java
@@ -60,6 +60,7 @@ import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.RefNotAdvertisedException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
+import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode;
@@ -67,12 +68,17 @@ import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.lib.SubmoduleConfig.FetchRecurseSubmodulesMode;
import org.eclipse.jgit.merge.MergeStrategy;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.TagOpt;
@@ -339,6 +345,45 @@ public class PullCommand extends TransportCommand<PullCommand, PullResult> {
PullResult result;
if (pullRebaseMode != BranchRebaseMode.NONE) {
+ try {
+ Ref head = repo.exactRef(Constants.HEAD);
+ if (head == null) {
+ throw new NoHeadException(JGitText
+ .get().commitOnRepoWithoutHEADCurrentlyNotSupported);
+ }
+ ObjectId headId = head.getObjectId();
+ if (headId == null) {
+ // Pull on an unborn branch: checkout
+ try (RevWalk revWalk = new RevWalk(repo)) {
+ RevCommit srcCommit = revWalk
+ .parseCommit(commitToMerge);
+ DirCacheCheckout dco = new DirCacheCheckout(repo,
+ repo.lockDirCache(), srcCommit.getTree());
+ dco.setFailOnConflict(true);
+ dco.setProgressMonitor(monitor);
+ dco.checkout();
+ RefUpdate refUpdate = repo
+ .updateRef(head.getTarget().getName());
+ refUpdate.setNewObjectId(commitToMerge);
+ refUpdate.setExpectedOldObjectId(null);
+ refUpdate.setRefLogMessage("initial pull", false); //$NON-NLS-1$
+ if (refUpdate.update() != Result.NEW) {
+ throw new NoHeadException(JGitText
+ .get().commitOnRepoWithoutHEADCurrentlyNotSupported);
+ }
+ monitor.endTask();
+ return new PullResult(fetchRes, remote,
+ RebaseResult.result(
+ RebaseResult.Status.FAST_FORWARD,
+ srcCommit));
+ }
+ }
+ } catch (NoHeadException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new JGitInternalException(JGitText
+ .get().exceptionCaughtDuringExecutionOfPullCommand, e);
+ }
RebaseCommand rebase = new RebaseCommand(repo);
RebaseResult rebaseRes = rebase.setUpstream(commitToMerge)
.setUpstreamName(upstreamName).setProgressMonitor(monitor)
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 0e3d000d3a..0dacd4dfbf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RebaseCommand.java
@@ -362,7 +362,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
List<RebaseTodoLine> steps = repo.readRebaseTodo(
rebaseState.getPath(GIT_REBASE_TODO), false);
- if (steps.size() == 0) {
+ if (steps.isEmpty()) {
return finishRebase(walk.parseCommit(repo.resolve(Constants.HEAD)), false);
}
if (isInteractive()) {
@@ -490,7 +490,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
resetSoftToParent();
List<RebaseTodoLine> steps = repo.readRebaseTodo(
rebaseState.getPath(GIT_REBASE_TODO), false);
- RebaseTodoLine nextStep = steps.size() > 0 ? steps.get(0) : null;
+ RebaseTodoLine nextStep = steps.isEmpty() ? null : steps.get(0);
File messageFixupFile = rebaseState.getFile(MESSAGE_FIXUP);
File messageSquashFile = rebaseState.getFile(MESSAGE_SQUASH);
if (isSquash && messageFixupFile.exists())
@@ -575,7 +575,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
ObjectId headId = getHead().getObjectId();
// getHead() checks for null
assert headId != null;
- if (!AnyObjectId.equals(headId, newParents.get(0)))
+ if (!AnyObjectId.isEqual(headId, newParents.get(0)))
checkoutCommit(headId.getName(), newParents.get(0));
// Use the cherry-pick strategy if all non-first parents did not
@@ -1083,7 +1083,7 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
repo.writeRebaseTodoFile(rebaseState.getPath(GIT_REBASE_TODO),
todoLines, false);
- if (poppedLines.size() > 0) {
+ if (!poppedLines.isEmpty()) {
repo.writeRebaseTodoFile(rebaseState.getPath(DONE), poppedLines,
true);
}
@@ -1295,13 +1295,8 @@ public class RebaseCommand extends GitCommand<RebaseResult> {
}
}
return newCommit;
- } catch (RefAlreadyExistsException e) {
- throw new JGitInternalException(e.getMessage(), e);
- } catch (RefNotFoundException e) {
- throw new JGitInternalException(e.getMessage(), e);
- } catch (InvalidRefNameException e) {
- throw new JGitInternalException(e.getMessage(), e);
- } catch (CheckoutConflictException e) {
+ } catch (RefAlreadyExistsException | RefNotFoundException
+ | InvalidRefNameException | CheckoutConflictException e) {
throw new JGitInternalException(e.getMessage(), e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
index 46e0df7263..ddd60b6fa2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/RevertCommand.java
@@ -175,8 +175,8 @@ public class RevertCommand extends GitCommand<RevCommit> {
+ "This reverts commit " + srcCommit.getId().getName() //$NON-NLS-1$
+ ".\n"; //$NON-NLS-1$
if (merger.merge(headCommit, srcParent)) {
- if (AnyObjectId.equals(headCommit.getTree().getId(), merger
- .getResultTreeId()))
+ if (AnyObjectId.isEqual(headCommit.getTree().getId(),
+ merger.getResultTreeId()))
continue;
DirCacheCheckout dco = new DirCacheCheckout(repo,
headCommit.getTree(), repo.lockDirCache(),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
index f92455a96a..8908277725 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleAddCommand.java
@@ -238,9 +238,7 @@ public class SubmoduleAddCommand extends
modulesConfig.setString(ConfigConstants.CONFIG_SUBMODULE_SECTION,
name, ConfigConstants.CONFIG_KEY_URL, uri);
modulesConfig.save();
- } catch (IOException e) {
- throw new JGitInternalException(e.getMessage(), e);
- } catch (ConfigInvalidException e) {
+ } catch (IOException | ConfigInvalidException e) {
throw new JGitInternalException(e.getMessage(), e);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
index 5a0528b0f5..ebcea4b1dd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
@@ -173,8 +173,8 @@ public class SubmoduleDeinitCommand
}
final File[] ls = dir.listFiles();
if (ls != null) {
- for (int i = 0; i < ls.length; i++) {
- FileUtils.delete(ls[i], RECURSIVE);
+ for (File f : ls) {
+ FileUtils.delete(f, RECURSIVE);
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
index 2db12b8e25..6fd94052a4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleInitCommand.java
@@ -128,9 +128,7 @@ public class SubmoduleInitCommand extends GitCommand<Collection<String>> {
if (!initialized.isEmpty())
config.save();
return initialized;
- } catch (IOException e) {
- throw new JGitInternalException(e.getMessage(), e);
- } catch (ConfigInvalidException e) {
+ } catch (IOException | ConfigInvalidException e) {
throw new JGitInternalException(e.getMessage(), e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
index 0606c5b8d4..58e59598ed 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleStatusCommand.java
@@ -108,9 +108,7 @@ public class SubmoduleStatusCommand extends
statuses.put(status.getPath(), status);
}
return statuses;
- } catch (IOException e) {
- throw new JGitInternalException(e.getMessage(), e);
- } catch (ConfigInvalidException e) {
+ } catch (IOException | ConfigInvalidException e) {
throw new JGitInternalException(e.getMessage(), e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
index 7cf4b73af0..52393695d9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleSyncCommand.java
@@ -162,9 +162,7 @@ public class SubmoduleSyncCommand extends GitCommand<Map<String, String>> {
if (!synced.isEmpty())
config.save();
return synced;
- } catch (IOException e) {
- throw new JGitInternalException(e.getMessage(), e);
- } catch (ConfigInvalidException e) {
+ } catch (IOException | ConfigInvalidException e) {
throw new JGitInternalException(e.getMessage(), e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
index e7ad0bc40d..1cecff6fb0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java
@@ -1063,7 +1063,7 @@ public class DiffFormatter implements AutoCloseable {
entry.newId = id;
break;
}
- } else if (ids.size() == 0)
+ } else if (ids.isEmpty())
throw new MissingObjectException(id, Constants.OBJ_BLOB);
else
throw new AmbiguousObjectException(id, ids);
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 0cfd16b58a..95e1d21434 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCache.java
@@ -112,14 +112,12 @@ public class DirCache {
private static final byte[] NO_CHECKSUM = {};
- static final Comparator<DirCacheEntry> ENT_CMP = new Comparator<DirCacheEntry>() {
- @Override
- public int compare(DirCacheEntry o1, DirCacheEntry o2) {
- final int cr = cmp(o1, o2);
- if (cr != 0)
- return cr;
- return o1.getStage() - o2.getStage();
- }
+ static final Comparator<DirCacheEntry> ENT_CMP = (DirCacheEntry o1,
+ DirCacheEntry o2) -> {
+ final int cr = cmp(o1, o2);
+ if (cr != 0)
+ return cr;
+ return o1.getStage() - o2.getStage();
};
static int cmp(DirCacheEntry a, DirCacheEntry b) {
@@ -254,13 +252,7 @@ public class DirCache {
try {
c.read();
- } catch (IOException e) {
- c.unlock();
- throw e;
- } catch (RuntimeException e) {
- c.unlock();
- throw e;
- } catch (Error e) {
+ } catch (IOException | RuntimeException | Error e) {
c.unlock();
throw e;
}
@@ -637,13 +629,7 @@ public class DirCache {
try (OutputStream o = tmp.getOutputStream();
OutputStream bo = new BufferedOutputStream(o)) {
writeTo(liveFile.getParentFile(), bo);
- } catch (IOException err) {
- tmp.unlock();
- throw err;
- } catch (RuntimeException err) {
- tmp.unlock();
- throw err;
- } catch (Error err) {
+ } catch (IOException | RuntimeException | Error err) {
tmp.unlock();
throw err;
}
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 2d6228657a..22090f5b60 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
@@ -635,7 +635,7 @@ public class DirCacheCheckout {
if (!builder.commit())
throw new IndexWriteException();
}
- return toBeDeleted.size() == 0;
+ return toBeDeleted.isEmpty();
}
private void checkoutGitlink(String path, DirCacheEntry entry)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
index 74ba97fb8d..5b8e11f330 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
@@ -75,13 +75,11 @@ import org.eclipse.jgit.util.Paths;
* @see DirCacheBuilder
*/
public class DirCacheEditor extends BaseDirCacheEditor {
- private static final Comparator<PathEdit> EDIT_CMP = new Comparator<PathEdit>() {
- @Override
- public int compare(PathEdit o1, PathEdit o2) {
- final byte[] a = o1.path;
- final byte[] b = o2.path;
- return cmp(a, a.length, b, b.length);
- }
+ private static final Comparator<PathEdit> EDIT_CMP = (PathEdit o1,
+ PathEdit o2) -> {
+ final byte[] a = o1.path;
+ final byte[] b = o2.path;
+ return cmp(a, a.length, b, b.length);
};
private final List<PathEdit> edits;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
index d2a59c1310..d4db15ce9b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
@@ -448,9 +448,9 @@ public class DirCacheEntry {
*/
public void setAssumeValid(boolean assume) {
if (assume)
- info[infoOffset + P_FLAGS] |= ASSUME_VALID;
+ info[infoOffset + P_FLAGS] |= (byte) ASSUME_VALID;
else
- info[infoOffset + P_FLAGS] &= ~ASSUME_VALID;
+ info[infoOffset + P_FLAGS] &= (byte) ~ASSUME_VALID;
}
/**
@@ -470,9 +470,9 @@ public class DirCacheEntry {
*/
public void setUpdateNeeded(boolean updateNeeded) {
if (updateNeeded)
- inCoreFlags |= UPDATE_NEEDED;
+ inCoreFlags |= (byte) UPDATE_NEEDED;
else
- inCoreFlags &= ~UPDATE_NEEDED;
+ inCoreFlags &= (byte) ~UPDATE_NEEDED;
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
index 11a3474a35..80e1084fe0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
@@ -81,25 +81,26 @@ public class DirCacheTree {
private static final DirCacheTree[] NO_CHILDREN = {};
- private static final Comparator<DirCacheTree> TREE_CMP = new Comparator<DirCacheTree>() {
- @Override
- public int compare(DirCacheTree o1, DirCacheTree o2) {
- final byte[] a = o1.encodedName;
- final byte[] b = o2.encodedName;
- final int aLen = a.length;
- final int bLen = b.length;
- int cPos;
- for (cPos = 0; cPos < aLen && cPos < bLen; cPos++) {
- final int cmp = (a[cPos] & 0xff) - (b[cPos] & 0xff);
- if (cmp != 0)
- return cmp;
+ private static final Comparator<DirCacheTree> TREE_CMP = (DirCacheTree o1,
+ DirCacheTree o2) -> {
+ final byte[] a = o1.encodedName;
+ final byte[] b = o2.encodedName;
+ final int aLen = a.length;
+ final int bLen = b.length;
+ int cPos;
+ for (cPos = 0; cPos < aLen && cPos < bLen; cPos++) {
+ final int cmp = (a[cPos] & 0xff) - (b[cPos] & 0xff);
+ if (cmp != 0) {
+ return cmp;
}
- if (aLen == bLen)
- return 0;
- if (aLen < bLen)
- return '/' - (b[cPos] & 0xff);
- return (a[cPos] & 0xff) - '/';
}
+ if (aLen == bLen) {
+ return 0;
+ }
+ if (aLen < bLen) {
+ return '/' - (b[cPos] & 0xff);
+ }
+ return (a[cPos] & 0xff) - '/';
};
/** Tree this tree resides in; null if we are the root. */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/errors/IncorrectObjectTypeException.java b/org.eclipse.jgit/src/org/eclipse/jgit/errors/IncorrectObjectTypeException.java
index 5abd0c347b..15fd803d00 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/errors/IncorrectObjectTypeException.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/errors/IncorrectObjectTypeException.java
@@ -63,7 +63,7 @@ public class IncorrectObjectTypeException extends IOException {
private static final long serialVersionUID = 1L;
/**
- * Construct and IncorrectObjectTypeException for the specified object id.
+ * Construct an IncorrectObjectTypeException for the specified object id.
*
* Provide the type to make it easier to track down the problem.
*
@@ -75,7 +75,7 @@ public class IncorrectObjectTypeException extends IOException {
}
/**
- * Construct and IncorrectObjectTypeException for the specified object id.
+ * Construct an IncorrectObjectTypeException for the specified object id.
*
* Provide the type to make it easier to track down the problem.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/WildMatcher.java b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/WildMatcher.java
index 2ad87dade6..239e2c81d3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/WildMatcher.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/ignore/internal/WildMatcher.java
@@ -64,7 +64,7 @@ public final class WildMatcher extends AbstractMatcher {
public final boolean matches(String path, boolean assumeDirectory,
boolean pathMatch) {
return !dirOnly || assumeDirectory
- || !pathMatch && isSubdirectory(path);
+ || (!pathMatch && isSubdirectory(path));
}
/** {@inheritDoc} */
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 039a6b2b43..cd50e347ab 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -202,6 +202,7 @@ public class JGitText extends TranslationBundle {
/***/ public String configSubsectionContainsNullByte;
/***/ public String configValueContainsNullByte;
/***/ public String configHandleIsStale;
+ /***/ public String configHandleMayBeLocked;
/***/ public String connectionFailed;
/***/ public String connectionTimeOut;
/***/ public String contextMustBeNonNegative;
@@ -269,9 +270,13 @@ public class JGitText extends TranslationBundle {
/***/ public String couldNotCheckOutBecauseOfConflicts;
/***/ public String couldNotDeleteLockFileShouldNotHappen;
/***/ public String couldNotDeleteTemporaryIndexFileShouldNotHappen;
+ /***/ public String couldNotFindTabInLine;
+ /***/ public String couldNotFindSixTabsInLine;
/***/ public String couldNotGetAdvertisedRef;
/***/ public String couldNotGetRepoStatistics;
/***/ public String couldNotLockHEAD;
+ /***/ public String couldNotPersistCookies;
+ /***/ public String couldNotReadCookieFile;
/***/ public String couldNotReadIndexInOneGo;
/***/ public String couldNotReadObjectWhileParsingCommit;
/***/ public String couldNotRenameDeleteOldIndex;
@@ -394,6 +399,7 @@ public class JGitText extends TranslationBundle {
/***/ public String gpgNoKeyInLegacySecring;
/***/ public String gpgNoPublicKeyFound;
/***/ public String gpgNoSecretKeyForPublicKey;
+ /***/ public String gpgNotASigningKey;
/***/ public String gpgKeyInfo;
/***/ public String gpgSigningCancelled;
/***/ public String headRequiredToStash;
@@ -520,6 +526,7 @@ public class JGitText extends TranslationBundle {
/***/ public String mismatchCRC;
/***/ public String missingAccesskey;
/***/ public String missingConfigurationForKey;
+ /***/ public String missingCookieFile;
/***/ public String missingCRC;
/***/ public String missingDeltaBase;
/***/ public String missingForwardImageInGITBinaryPatch;
@@ -694,6 +701,7 @@ public class JGitText extends TranslationBundle {
/***/ public String s3ActionReading;
/***/ public String s3ActionWriting;
/***/ public String saveFileStoreAttributesFailed;
+ /***/ public String searchForReachableBranches;
/***/ public String searchForReuse;
/***/ public String searchForSizes;
/***/ public String secondsAgo;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchLeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchLeader.java
index fa32b267df..c0364acdd1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchLeader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchLeader.java
@@ -385,12 +385,7 @@ public abstract class KetchLeader {
private void scheduleLeader() {
idle = false;
- system.getExecutor().execute(new Runnable() {
- @Override
- public void run() {
- runLeader();
- }
- });
+ system.getExecutor().execute(this::runLeader);
}
private void runLeader() {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchReplica.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchReplica.java
index a0176d7d2e..0e8377dd02 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchReplica.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchReplica.java
@@ -345,7 +345,7 @@ public abstract class KetchReplica {
}
private static boolean equals(@Nullable ObjectId a, LogIndex b) {
- return a != null && b != null && AnyObjectId.equals(a, b);
+ return a != null && b != null && AnyObjectId.isEqual(a, b);
}
/**
@@ -749,7 +749,7 @@ public abstract class KetchReplica {
Ref oldRef = remote.remove(name);
ObjectId oldId = getId(oldRef);
ObjectId newId = tw.getObjectId(0);
- if (!AnyObjectId.equals(oldId, newId)) {
+ if (!AnyObjectId.isEqual(oldId, newId)) {
delta.add(new ReceiveCommand(oldId, newId, name));
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LagCheck.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LagCheck.java
index c09d872f0a..53fd198006 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LagCheck.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LagCheck.java
@@ -106,7 +106,7 @@ class LagCheck implements AutoCloseable {
return UNKNOWN;
}
- if (AnyObjectId.equals(remoteId, ObjectId.zeroId())) {
+ if (AnyObjectId.isEqual(remoteId, ObjectId.zeroId())) {
// Replica does not have the txnAccepted reference.
return LAGGING;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java
index 6f1f5c5c2c..cd0ded5e38 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/LocalReplica.java
@@ -123,21 +123,18 @@ public class LocalReplica extends KetchReplica {
/** {@inheritDoc} */
@Override
protected void startPush(ReplicaPushRequest req) {
- getSystem().getExecutor().execute(new Runnable() {
- @Override
- public void run() {
- MonotonicClock clk = getSystem().getClock();
- try (Repository git = getLeader().openRepository();
- ProposedTimestamp ts = clk.propose()) {
- try {
- update(git, req, ts);
- req.done(git);
- } catch (Throwable err) {
- req.setException(git, err);
- }
- } catch (IOException err) {
- req.setException(null, err);
+ getSystem().getExecutor().execute(() -> {
+ MonotonicClock clk = getSystem().getClock();
+ try (Repository git = getLeader().openRepository();
+ ProposedTimestamp ts = clk.propose()) {
+ try {
+ update(git, req, ts);
+ req.done(git);
+ } catch (Throwable err) {
+ req.setException(git, err);
}
+ } catch (IOException err) {
+ req.setException(null, err);
}
});
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java
index b61274ef4a..4bed575f26 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/RemoteGitReplica.java
@@ -139,19 +139,16 @@ public class RemoteGitReplica extends KetchReplica {
/** {@inheritDoc} */
@Override
protected void startPush(ReplicaPushRequest req) {
- getSystem().getExecutor().execute(new Runnable() {
- @Override
- public void run() {
- try (Repository git = getLeader().openRepository()) {
- try {
- push(git, req);
- req.done(git);
- } catch (Throwable err) {
- req.setException(git, err);
- }
- } catch (IOException err) {
- req.setException(null, err);
+ getSystem().getExecutor().execute(() -> {
+ try (Repository git = getLeader().openRepository()) {
+ try {
+ push(git, req);
+ req.done(git);
+ } catch (Throwable err) {
+ req.setException(git, err);
}
+ } catch (IOException err) {
+ req.setException(null, err);
}
});
}
@@ -203,7 +200,7 @@ public class RemoteGitReplica extends KetchReplica {
private static boolean isExpectedValue(Map<String, Ref> adv,
RemoteRefUpdate u) {
Ref r = adv.get(u.getRemoteName());
- if (!AnyObjectId.equals(getId(r), u.getExpectedOldObjectId())) {
+ if (!AnyObjectId.isEqual(getId(r), u.getExpectedOldObjectId())) {
((RemoteCommand) u).cmd.setResult(LOCK_FAILURE);
return false;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/StageBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/StageBuilder.java
index ae82dced21..815984deb2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/StageBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/StageBuilder.java
@@ -138,7 +138,7 @@ public class StageBuilder {
try (RevWalk rw = new RevWalk(git);
TreeWalk tw = new TreeWalk(rw.getObjectReader());
ObjectInserter ins = git.newObjectInserter()) {
- if (AnyObjectId.equals(oldTree, ObjectId.zeroId())) {
+ if (AnyObjectId.isEqual(oldTree, ObjectId.zeroId())) {
tw.addTree(new EmptyTreeIterator());
} else {
tw.addTree(rw.parseTree(oldTree));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java
index bd4b4d23f4..3b92deeaeb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DeltaBaseCache.java
@@ -180,8 +180,8 @@ final class DeltaBaseCache {
int getMemoryUsedByTableForTest() {
int r = 0;
- for (int i = 0; i < table.length; i++) {
- for (Entry e = table[i]; e != null; e = e.tableNext) {
+ for (Entry t : table) {
+ for (Entry e = t; e != null; e = e.tableNext) {
r += e.data.length;
}
}
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 ca11fb9265..f10a1d8127 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
@@ -661,7 +661,7 @@ public class DfsGarbageCollector {
private int objectsBefore() {
int cnt = 0;
for (DfsPackFile p : packsBefore)
- cnt += p.getPackDescription().getObjectCount();
+ cnt += (int) p.getPackDescription().getObjectCount();
return cnt;
}
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 127ee6bf11..6f3f2bd8e7 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
@@ -469,12 +469,8 @@ public class DfsPackCompactor {
continue SCAN;
want.add(new ObjectIdWithOffset(id, ent.getOffset()));
}
- Collections.sort(want, new Comparator<ObjectIdWithOffset>() {
- @Override
- public int compare(ObjectIdWithOffset a, ObjectIdWithOffset b) {
- return Long.signum(a.offset - b.offset);
- }
- });
+ Collections.sort(want, (ObjectIdWithOffset a,
+ ObjectIdWithOffset b) -> Long.signum(a.offset - b.offset));
return want;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java
index 3a30d7daf5..e4c37cb4c2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackParser.java
@@ -429,10 +429,10 @@ public class DfsPackParser extends PackParser {
final byte[] buf = buffer();
int sz = data.length;
int len = 0;
- buf[len++] = (byte) ((typeCode << 4) | sz & 15);
+ buf[len++] = (byte) ((typeCode << 4) | (sz & 15));
sz >>>= 4;
while (sz > 0) {
- buf[len - 1] |= 0x80;
+ buf[len - 1] |= (byte) 0x80;
buf[len++] = (byte) (sz & 0x7f);
sz >>>= 7;
}
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 d04709f6c2..c75b88f3bd 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
@@ -287,14 +287,12 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
return Collections.emptySet();
}
- private static final Comparator<FoundObject<?>> FOUND_OBJECT_SORT = new Comparator<FoundObject<?>>() {
- @Override
- public int compare(FoundObject<?> a, FoundObject<?> b) {
- int cmp = a.packIndex - b.packIndex;
- if (cmp == 0)
- cmp = Long.signum(a.offset - b.offset);
- return cmp;
- }
+ private static final Comparator<FoundObject<?>> FOUND_OBJECT_SORT = (
+ FoundObject<?> a, FoundObject<?> b) -> {
+ int cmp = a.packIndex - b.packIndex;
+ if (cmp == 0)
+ cmp = Long.signum(a.offset - b.offset);
+ return cmp;
};
private static class FoundObject<T extends ObjectId> {
@@ -565,12 +563,9 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
return new DfsObjectToPack(objectId, type);
}
- private static final Comparator<DfsObjectToPack> OFFSET_SORT = new Comparator<DfsObjectToPack>() {
- @Override
- public int compare(DfsObjectToPack a, DfsObjectToPack b) {
- return Long.signum(a.getOffset() - b.getOffset());
- }
- };
+ private static final Comparator<DfsObjectToPack> OFFSET_SORT = (
+ DfsObjectToPack a,
+ DfsObjectToPack b) -> Long.signum(a.getOffset() - b.getOffset());
@Override
public void selectObjectRepresentation(PackWriter packer,
@@ -757,6 +752,7 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
*/
int inflate(DfsPackFile pack, long position, byte[] dstbuf,
boolean headerOnly) throws IOException, DataFormatException {
+ long start = System.nanoTime();
prepareInflater();
pin(pack, position);
position += block.setInput(position, inf);
@@ -765,6 +761,7 @@ public class DfsReader extends ObjectReader implements ObjectReuseAsIs {
dstoff += n;
if (inf.finished() || (headerOnly && dstoff == dstbuf.length)) {
stats.inflatedBytes += dstoff;
+ stats.inflationMicros += BlockBasedFile.elapsedMicros(start);
return dstoff;
} else if (inf.needsInput()) {
pin(pack, position);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java
index c35801f3b0..d6401a1640 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsReaderIoStats.java
@@ -85,6 +85,9 @@ public class DfsReaderIoStats {
/** Total number of bytes decompressed. */
long inflatedBytes;
+ /** Total microseconds spent inflating compressed bytes. */
+ long inflationMicros;
+
Accumulator() {
}
}
@@ -186,4 +189,13 @@ public class DfsReaderIoStats {
public long getInflatedBytes() {
return stats.inflatedBytes;
}
+
+ /**
+ * Get total microseconds spent inflating compressed bytes.
+ *
+ * @return total microseconds inflating compressed bytes.
+ */
+ public long getInflationMicros() {
+ return stats.inflationMicros;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java
index 8b2a03d4c5..732cd4d1c6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRefDatabase.java
@@ -43,6 +43,7 @@
package org.eclipse.jgit.internal.storage.dfs;
+import static org.eclipse.jgit.lib.Ref.UNDEFINED_UPDATE_INDEX;
import static org.eclipse.jgit.lib.Ref.Storage.NEW;
import java.io.IOException;
@@ -175,7 +176,7 @@ public abstract class DfsRefDatabase extends RefDatabase {
cachePeeledState(oldLeaf, newLeaf);
}
- return recreate(ref, newLeaf);
+ return recreate(ref, newLeaf, hasVersioning());
}
Ref doPeel(Ref leaf) throws MissingObjectException,
@@ -187,20 +188,26 @@ public abstract class DfsRefDatabase extends RefDatabase {
leaf.getStorage(),
leaf.getName(),
leaf.getObjectId(),
- rw.peel(obj).copy());
+ rw.peel(obj).copy(),
+ hasVersioning() ? leaf.getUpdateIndex()
+ : UNDEFINED_UPDATE_INDEX);
} else {
return new ObjectIdRef.PeeledNonTag(
leaf.getStorage(),
leaf.getName(),
- leaf.getObjectId());
+ leaf.getObjectId(),
+ hasVersioning() ? leaf.getUpdateIndex()
+ : UNDEFINED_UPDATE_INDEX);
}
}
}
- static Ref recreate(Ref old, Ref leaf) {
+ static Ref recreate(Ref old, Ref leaf, boolean hasVersioning) {
if (old.isSymbolic()) {
- Ref dst = recreate(old.getTarget(), leaf);
- return new SymbolicRef(old.getName(), dst);
+ Ref dst = recreate(old.getTarget(), leaf, hasVersioning);
+ return new SymbolicRef(old.getName(), dst,
+ hasVersioning ? old.getUpdateIndex()
+ : UNDEFINED_UPDATE_INDEX);
}
return leaf;
}
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 83394bb92c..6050c15992 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
@@ -47,8 +47,10 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.jgit.annotations.Nullable;
@@ -277,12 +279,31 @@ public class DfsReftableDatabase extends DfsRefDatabase {
/** {@inheritDoc} */
@Override
+ public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
+ if (!getReftableConfig().isIndexObjects()) {
+ return super.getTipsWithSha1(id);
+ }
+ lock.lock();
+ try {
+ RefCursor cursor = reader().byObjectId(id);
+ Set<Ref> refs = new HashSet<>();
+ while (cursor.next()) {
+ refs.add(cursor.getRef());
+ }
+ return refs;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
public Ref peel(Ref ref) throws IOException {
Ref oldLeaf = ref.getLeaf();
if (oldLeaf.isPeeled() || oldLeaf.getObjectId() == null) {
return ref;
}
- return recreate(ref, doPeel(oldLeaf));
+ return recreate(ref, doPeel(oldLeaf), hasVersioning());
}
@Override
@@ -315,6 +336,7 @@ public class DfsReftableDatabase extends DfsRefDatabase {
throws IOException {
ReceiveCommand cmd = toCommand(oldRef, newRef);
try (RevWalk rw = new RevWalk(getRepository())) {
+ rw.setRetainBody(false);
newBatchUpdate().setAllowNonFastForwards(true).addCommand(cmd)
.execute(rw, NullProgressMonitor.INSTANCE);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRepository.java
index 5169e929e4..8e5c5a7f75 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRepository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsRepository.java
@@ -126,6 +126,12 @@ public abstract class DfsRepository extends Repository {
/** {@inheritDoc} */
@Override
+ public String getIdentifier() {
+ return getDescription().getRepositoryName();
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void scanForRepoChanges() throws IOException {
getRefDatabase().refresh();
getObjectDatabase().clearCache();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java
index 47ac4ec72e..07fd00f149 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/ReftableBatchRefUpdate.java
@@ -252,7 +252,7 @@ public class ReftableBatchRefUpdate extends BatchRefUpdate {
private static boolean matchOld(ReceiveCommand cmd, @Nullable Ref ref) {
if (ref == null) {
- return AnyObjectId.equals(ObjectId.zeroId(), cmd.getOldId())
+ return AnyObjectId.isEqual(ObjectId.zeroId(), cmd.getOldId())
&& cmd.getOldSymref() == null;
} else if (ref.isSymbolic()) {
return ref.getTarget().getName().equals(cmd.getOldSymref());
@@ -368,7 +368,7 @@ public class ReftableBatchRefUpdate extends BatchRefUpdate {
String name = cmd.getRefName();
ObjectId newId = cmd.getNewId();
String newSymref = cmd.getNewSymref();
- if (AnyObjectId.equals(ObjectId.zeroId(), newId)
+ if (AnyObjectId.isEqual(ObjectId.zeroId(), newId)
&& newSymref == null) {
refs.add(new ObjectIdRef.Unpeeled(NEW, name, null));
continue;
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 356d64b563..4f5f8a613e 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
@@ -62,8 +62,6 @@ import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.attributes.AttributesNode;
import org.eclipse.jgit.attributes.AttributesNodeProvider;
import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.events.ConfigChangedEvent;
-import org.eclipse.jgit.events.ConfigChangedListener;
import org.eclipse.jgit.events.IndexChangedEvent;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.ObjectDirectory.AlternateHandle;
@@ -192,12 +190,7 @@ public class FileRepository extends Repository {
getFS());
loadRepoConfig();
- repoConfig.addChangeListener(new ConfigChangedListener() {
- @Override
- public void onConfigChanged(ConfigChangedEvent event) {
- fireEvent(event);
- }
- });
+ repoConfig.addChangeListener(this::fireEvent);
final long repositoryFormatVersion = getConfig().getLong(
ConfigConstants.CONFIG_CORE_SECTION, null,
@@ -361,6 +354,17 @@ public class FileRepository extends Repository {
/** {@inheritDoc} */
@Override
+ public String getIdentifier() {
+ File directory = getDirectory();
+ if (directory != null) {
+ return directory.getPath();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
public FileBasedConfig getConfig() {
try {
SystemReader.getInstance().getUserConfig();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
index 976f946e5d..8650ebfe29 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileSnapshot.java
@@ -413,6 +413,7 @@ public class FileSnapshot {
* the other snapshot.
* @return true if the two snapshots share the same information.
*/
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(FileSnapshot other) {
boolean sizeEq = size == UNKNOWN_SIZE || other.size == UNKNOWN_SIZE || size == other.size;
return lastModified.equals(other.lastModified) && sizeEq
@@ -490,7 +491,7 @@ public class FileSnapshot {
}
/** {@inheritDoc} */
- @SuppressWarnings("nls")
+ @SuppressWarnings({ "nls", "ReferenceEquality" })
@Override
public String toString() {
if (this == DIRTY) {
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 7400308c86..08bb6cb7fa 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
@@ -244,7 +244,7 @@ public class GC {
* If the configuration parameter "gc.pruneexpire" couldn't be
* parsed
*/
- // TODO(ms): in 5.0 change signature and return Future<Collection<PackFile>>
+ // TODO(ms): change signature and return Future<Collection<PackFile>>
@SuppressWarnings("FutureReturnValueIgnored")
public Collection<PackFile> gc() throws IOException, ParseException {
if (!background) {
@@ -281,7 +281,7 @@ public class GC {
}
return Collections.emptyList();
};
- // TODO(ms): in 5.0 change signature and return the Future
+ // TODO(ms): change signature and return the Future
executor().submit(gcTask);
return Collections.emptyList();
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
index f7e78b94f7..6af41256d6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/LockFile.java
@@ -120,12 +120,8 @@ public class LockFile {
}
/** Filter to skip over active lock files when listing a directory. */
- static final FilenameFilter FILTER = new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return !name.endsWith(LOCK_SUFFIX);
- }
- };
+ static final FilenameFilter FILTER = (File dir,
+ String name) -> !name.endsWith(LOCK_SUFFIX);
private final File ref;
@@ -248,13 +244,7 @@ public class LockFile {
// Don't worry about a file that doesn't exist yet, it
// conceptually has no current content to copy.
//
- } catch (IOException ioe) {
- unlock();
- throw ioe;
- } catch (RuntimeException ioe) {
- unlock();
- throw ioe;
- } catch (Error ioe) {
+ } catch (IOException | RuntimeException | Error ioe) {
unlock();
throw ioe;
}
@@ -308,13 +298,7 @@ public class LockFile {
}
os.close();
os = null;
- } catch (IOException ioe) {
- unlock();
- throw ioe;
- } catch (RuntimeException ioe) {
- unlock();
- throw ioe;
- } catch (Error ioe) {
+ } catch (IOException | RuntimeException | Error ioe) {
unlock();
throw ioe;
}
@@ -362,13 +346,7 @@ public class LockFile {
os.getChannel().force(true);
out.close();
os = null;
- } catch (IOException ioe) {
- unlock();
- throw ioe;
- } catch (RuntimeException ioe) {
- unlock();
- throw ioe;
- } catch (Error ioe) {
+ } catch (IOException | RuntimeException | Error ioe) {
unlock();
throw ioe;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java
index 6e8a15e86d..7d31673566 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java
@@ -353,10 +353,10 @@ public class ObjectDirectoryPackParser extends PackParser {
final byte[] buf = buffer();
int sz = data.length;
int len = 0;
- buf[len++] = (byte) ((typeCode << 4) | sz & 15);
+ buf[len++] = (byte) ((typeCode << 4) | (sz & 15));
sz >>>= 4;
while (sz > 0) {
- buf[len - 1] |= 0x80;
+ buf[len - 1] |= (byte) 0x80;
buf[len++] = (byte) (sz & 0x7f);
sz >>>= 7;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
index eff7958748..9941ff3740 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackBitmapIndexBuilder.java
@@ -45,7 +45,6 @@ package org.eclipse.jgit.internal.storage.file;
import java.text.MessageFormat;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
@@ -133,12 +132,8 @@ public class PackBitmapIndexBuilder extends BasePackBitmapIndex {
for (int i = 0; i < entries.size(); i++) {
positionEntries.add(new PositionEntry(entries.get(i), i));
}
- Collections.sort(entries, new Comparator<ObjectToPack>() {
- @Override
- public int compare(ObjectToPack a, ObjectToPack b) {
- return Long.signum(a.getOffset() - b.getOffset());
- }
- });
+ Collections.sort(entries, (ObjectToPack a, ObjectToPack b) -> Long
+ .signum(a.getOffset() - b.getOffset()));
for (int i = 0; i < entries.size(); i++) {
PositionEntry e = positionEntries.get(entries.get(i));
e.offsetPosition = i;
@@ -310,57 +305,55 @@ public class PackBitmapIndexBuilder extends BasePackBitmapIndex {
public Iterable<StoredEntry> getCompressedBitmaps() {
// Add order is from oldest to newest. The reverse add order is the
// output order.
- return new Iterable<StoredEntry>() {
+ return () -> new Iterator<StoredEntry>() {
+
+ private int index = byAddOrder.size() - 1;
+
@Override
- public Iterator<StoredEntry> iterator() {
- return new Iterator<StoredEntry>() {
- private int index = byAddOrder.size() - 1;
+ public boolean hasNext() {
+ return index >= 0;
+ }
- @Override
- public boolean hasNext() {
- return index >= 0;
+ @Override
+ public StoredEntry next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ StoredBitmap item = byAddOrder.get(index);
+ int bestXorOffset = 0;
+ EWAHCompressedBitmap bestBitmap = item.getBitmap();
+
+ // Attempt to compress the bitmap with an XOR of the
+ // previously written entries.
+ for (int i = 1; i <= MAX_XOR_OFFSET_SEARCH; i++) {
+ int curr = i + index;
+ if (curr >= byAddOrder.size()) {
+ break;
}
- @Override
- public StoredEntry next() {
- if (!hasNext())
- throw new NoSuchElementException();
- StoredBitmap item = byAddOrder.get(index);
- int bestXorOffset = 0;
- EWAHCompressedBitmap bestBitmap = item.getBitmap();
-
- // Attempt to compress the bitmap with an XOR of the
- // previously written entries.
- for (int i = 1; i <= MAX_XOR_OFFSET_SEARCH; i++) {
- int curr = i + index;
- if (curr >= byAddOrder.size())
- break;
-
- StoredBitmap other = byAddOrder.get(curr);
- EWAHCompressedBitmap bitmap = other.getBitmap()
- .xor(item.getBitmap());
-
- if (bitmap.sizeInBytes()
- < bestBitmap.sizeInBytes()) {
- bestBitmap = bitmap;
- bestXorOffset = i;
- }
- }
- index--;
-
- PositionEntry entry = positionEntries.get(item);
- if (entry == null)
- throw new IllegalStateException();
- bestBitmap.trim();
- return new StoredEntry(entry.namePosition, bestBitmap,
- bestXorOffset, item.getFlags());
- }
+ StoredBitmap other = byAddOrder.get(curr);
+ EWAHCompressedBitmap bitmap = other.getBitmap()
+ .xor(item.getBitmap());
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
+ if (bitmap.sizeInBytes() < bestBitmap.sizeInBytes()) {
+ bestBitmap = bitmap;
+ bestXorOffset = i;
}
- };
+ }
+ index--;
+
+ PositionEntry entry = positionEntries.get(item);
+ if (entry == null) {
+ throw new IllegalStateException();
+ }
+ bestBitmap.trim();
+ return new StoredEntry(entry.namePosition, bestBitmap,
+ bestXorOffset, item.getFlags());
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
}
};
}
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 a4729bba48..e5cea6c010 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
@@ -745,7 +745,7 @@ public class RefDirectory extends RefDatabase {
for (LockFile ol : heldLocks.values()) {
ol.requireLock();
}
- if (refs.size() == 0) {
+ if (refs.isEmpty()) {
return null;
}
FS fs = parent.getFS();
@@ -1128,9 +1128,11 @@ public class RefDirectory extends RefDatabase {
// check whether the found new ref is the an additional ref. These refs
// should not go into looseRefs
- for (int i = 0; i < additionalRefsNames.length; i++)
- if (name.equals(additionalRefsNames[i]))
+ for (String additionalRefsName : additionalRefsNames) {
+ if (name.equals(additionalRefsName)) {
return n;
+ }
+ }
if (looseRefs.compareAndSet(curList, curList.add(idx, n)))
modCnt.incrementAndGet();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java
index cf474afbbe..79f1307578 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObject.java
@@ -295,7 +295,7 @@ public class UnpackedObject {
* can always correctly determine the buffer format.
*/
final int fb = hdr[0] & 0xff;
- return (fb & 0x8f) == 0x08 && (((fb << 8) | hdr[1] & 0xff) % 31) == 0;
+ return (fb & 0x8f) == 0x08 && (((fb << 8) | (hdr[1] & 0xff)) % 31) == 0;
}
static InputStream inflate(final InputStream in, final long size,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObjectCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObjectCache.java
index 967754a627..ea0d269053 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObjectCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/UnpackedObjectCache.java
@@ -112,7 +112,7 @@ class UnpackedObjectCache {
if (obj == null)
break;
- if (AnyObjectId.equals(obj, toFind))
+ if (AnyObjectId.isEqual(obj, toFind))
return true;
if (++i == ids.length())
@@ -132,7 +132,7 @@ class UnpackedObjectCache {
continue;
}
- if (AnyObjectId.equals(obj, toAdd))
+ if (AnyObjectId.isEqual(obj, toAdd))
return true;
if (++i == ids.length())
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 e8fac514be..da7250d141 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
@@ -298,13 +298,7 @@ public class WindowCache {
if (mmap)
return pack.mmap(offset, windowSize);
return pack.read(offset, windowSize);
- } catch (IOException e) {
- close(pack);
- throw e;
- } catch (RuntimeException e) {
- close(pack);
- throw e;
- } catch (Error e) {
+ } catch (IOException | RuntimeException | Error e) {
close(pack);
throw e;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BinaryDelta.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BinaryDelta.java
index c7e5ad6232..5f69d0a884 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BinaryDelta.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/BinaryDelta.java
@@ -142,7 +142,7 @@ public class BinaryDelta {
int c, shift = 0;
do {
c = delta[deltaPtr++] & 0xff;
- baseLen |= ((long) (c & 0x7f)) << shift;
+ baseLen |= (c & 0x7f) << shift;
shift += 7;
} while ((c & 0x80) != 0);
if (base.length != baseLen)
@@ -155,7 +155,7 @@ public class BinaryDelta {
shift = 0;
do {
c = delta[deltaPtr++] & 0xff;
- resLen |= ((long) (c & 0x7f)) << shift;
+ resLen |= (c & 0x7f) << shift;
shift += 7;
} while ((c & 0x80) != 0);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaTask.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaTask.java
index 0347644324..a211d164c4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaTask.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaTask.java
@@ -46,7 +46,6 @@ package org.eclipse.jgit.internal.storage.pack;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -212,12 +211,8 @@ final class DeltaTask implements Callable<Object> {
}
// Sort by starting index to identify gaps later.
- Collections.sort(topPaths, new Comparator<WeightedPath>() {
- @Override
- public int compare(WeightedPath a, WeightedPath b) {
- return a.slice.beginIndex - b.slice.beginIndex;
- }
- });
+ Collections.sort(topPaths, (WeightedPath a,
+ WeightedPath b) -> a.slice.beginIndex - b.slice.beginIndex);
bytesPerUnit = 1;
while (MAX_METER <= (totalWeight / bytesPerUnit)) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaWindow.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaWindow.java
index a047534fbf..d152a392f0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaWindow.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaWindow.java
@@ -365,9 +365,7 @@ final class DeltaWindow {
resObj.setCachedDelta(deltaCache.cache(zbuf, len, deltaLen));
resObj.setCachedSize(deltaLen);
- } catch (IOException err) {
- deltaCache.credit(deltaLen);
- } catch (OutOfMemoryError err) {
+ } catch (IOException | OutOfMemoryError err) {
deltaCache.credit(deltaLen);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
index 1e3d74ab57..6506789218 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java
@@ -44,6 +44,7 @@
package org.eclipse.jgit.internal.storage.pack;
+import static java.util.Objects.requireNonNull;
import static org.eclipse.jgit.internal.storage.pack.StoredObjectRepresentation.PACK_DELTA;
import static org.eclipse.jgit.internal.storage.pack.StoredObjectRepresentation.PACK_WHOLE;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
@@ -61,7 +62,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -119,6 +120,7 @@ import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.storage.pack.PackConfig;
import org.eclipse.jgit.storage.pack.PackStatistics;
+import org.eclipse.jgit.transport.FilterSpec;
import org.eclipse.jgit.transport.ObjectCountCallback;
import org.eclipse.jgit.transport.WriteAbortedException;
import org.eclipse.jgit.util.BlockList;
@@ -303,7 +305,7 @@ public class PackWriter implements AutoCloseable {
private ObjectCountCallback callback;
- private long filterBlobLimit = -1;
+ private FilterSpec filterSpec = FilterSpec.NO_FILTER;
/**
* Create writer for specified repository.
@@ -641,10 +643,11 @@ public class PackWriter implements AutoCloseable {
}
/**
- * @param bytes exclude blobs of size greater than this
+ * @param filter the filter which indicates what and what not this writer
+ * should include
*/
- public void setFilterBlobLimit(long bytes) {
- filterBlobLimit = bytes;
+ public void setFilterSpec(@NonNull FilterSpec filter) {
+ filterSpec = requireNonNull(filter);
}
/**
@@ -870,6 +873,37 @@ public class PackWriter implements AutoCloseable {
}
/**
+ * A visitation policy which uses the depth at which the object is seen to
+ * decide if re-traversal is necessary. In particular, if the object has
+ * already been visited at this depth or shallower, it is not necessary to
+ * re-visit at this depth.
+ */
+ private static class DepthAwareVisitationPolicy
+ implements ObjectWalk.VisitationPolicy {
+ private final Map<ObjectId, Integer> lowestDepthVisited = new HashMap<>();
+
+ private final ObjectWalk walk;
+
+ DepthAwareVisitationPolicy(ObjectWalk walk) {
+ this.walk = requireNonNull(walk);
+ }
+
+ @Override
+ public boolean shouldVisit(RevObject o) {
+ Integer lastDepth = lowestDepthVisited.get(o);
+ if (lastDepth == null) {
+ return true;
+ }
+ return walk.getTreeDepth() < lastDepth.intValue();
+ }
+
+ @Override
+ public void visited(RevObject o) {
+ lowestDepthVisited.put(o, Integer.valueOf(walk.getTreeDepth()));
+ }
+ }
+
+ /**
* Prepare the list of objects to be written to the pack stream.
* <p>
* Basing on these 2 sets, another set of objects to put in a pack file is
@@ -910,6 +944,9 @@ public class PackWriter implements AutoCloseable {
if (shallowPack && !(walk instanceof DepthWalk.ObjectWalk))
throw new IllegalArgumentException(
JGitText.get().shallowPacksRequireDepthWalk);
+ if (filterSpec.getTreeDepthLimit() >= 0) {
+ walk.setVisitationPolicy(new DepthAwareVisitationPolicy(walk));
+ }
findObjectsToPack(countingMonitor, walk, interestingObjects,
uninterestingObjects, noBitmaps);
}
@@ -1380,32 +1417,33 @@ public class PackWriter implements AutoCloseable {
// applies "Linus' Law" which states that newer files tend to be the
// bigger ones, because source files grow and hardly ever shrink.
//
- Arrays.sort(list, 0, cnt, new Comparator<ObjectToPack>() {
- @Override
- public int compare(ObjectToPack a, ObjectToPack b) {
- int cmp = (a.isDoNotDelta() ? 1 : 0)
- - (b.isDoNotDelta() ? 1 : 0);
- if (cmp != 0)
- return cmp;
-
- cmp = a.getType() - b.getType();
- if (cmp != 0)
- return cmp;
-
- cmp = (a.getPathHash() >>> 1) - (b.getPathHash() >>> 1);
- if (cmp != 0)
- return cmp;
-
- cmp = (a.getPathHash() & 1) - (b.getPathHash() & 1);
- if (cmp != 0)
- return cmp;
-
- cmp = (a.isEdge() ? 0 : 1) - (b.isEdge() ? 0 : 1);
- if (cmp != 0)
- return cmp;
-
- return b.getWeight() - a.getWeight();
+ Arrays.sort(list, 0, cnt, (ObjectToPack a, ObjectToPack b) -> {
+ int cmp = (a.isDoNotDelta() ? 1 : 0) - (b.isDoNotDelta() ? 1 : 0);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ cmp = a.getType() - b.getType();
+ if (cmp != 0) {
+ return cmp;
}
+
+ cmp = (a.getPathHash() >>> 1) - (b.getPathHash() >>> 1);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ cmp = (a.getPathHash() & 1) - (b.getPathHash() & 1);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ cmp = (a.isEdge() ? 0 : 1) - (b.isEdge() ? 0 : 1);
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ return b.getWeight() - a.getWeight();
});
// Above we stored the objects we cannot delta onto the end.
@@ -1499,7 +1537,7 @@ public class PackWriter implements AutoCloseable {
Executor executor = config.getExecutor();
final List<Throwable> errors =
- Collections.synchronizedList(new ArrayList<Throwable>(threads));
+ Collections.synchronizedList(new ArrayList<>(threads));
if (executor instanceof ExecutorService) {
// Caller supplied us a service, use it directly.
runTasks((ExecutorService) executor, pm, taskBlock, errors);
@@ -1526,14 +1564,11 @@ public class PackWriter implements AutoCloseable {
// asynchronous execution. Wrap everything and hope it
// can schedule these for us.
for (DeltaTask task : taskBlock.tasks) {
- executor.execute(new Runnable() {
- @Override
- public void run() {
- try {
- task.call();
- } catch (Throwable failure) {
- errors.add(failure);
- }
+ executor.execute(() -> {
+ try {
+ task.call();
+ } catch (Throwable failure) {
+ errors.add(failure);
}
});
}
@@ -1969,7 +2004,9 @@ public class PackWriter implements AutoCloseable {
byte[] pathBuf = walker.getPathBuffer();
int pathLen = walker.getPathLength();
bases.addBase(o.getType(), pathBuf, pathLen, pathHash);
- filterAndAddObject(o, o.getType(), pathHash, want);
+ if (!depthSkip(o, walker)) {
+ filterAndAddObject(o, o.getType(), pathHash, want);
+ }
countingMonitor.update(1);
}
} else {
@@ -1979,7 +2016,10 @@ public class PackWriter implements AutoCloseable {
continue;
if (exclude(o))
continue;
- filterAndAddObject(o, o.getType(), walker.getPathHashCode(), want);
+ if (!depthSkip(o, walker)) {
+ filterAndAddObject(o, o.getType(), walker.getPathHashCode(),
+ want);
+ }
countingMonitor.update(1);
}
}
@@ -2071,6 +2111,44 @@ public class PackWriter implements AutoCloseable {
objectsMap.add(otp);
}
+ /**
+ * Determines if the object should be omitted from the pack as a result of
+ * its depth (probably because of the tree:<depth> filter).
+ * <p>
+ * Causes {@code walker} to skip traversing the current tree, which ought to
+ * have just started traversal, assuming this method is called as soon as a
+ * new depth is reached.
+ * <p>
+ * This method increments the {@code treesTraversed} statistic.
+ *
+ * @param obj
+ * the object to check whether it should be omitted.
+ * @param walker
+ * the walker being used for traveresal.
+ * @return whether the given object should be skipped.
+ */
+ private boolean depthSkip(@NonNull RevObject obj, ObjectWalk walker) {
+ long treeDepth = walker.getTreeDepth();
+
+ // Check if this object needs to be rejected because it is a tree or
+ // blob that is too deep from the root tree.
+
+ // A blob is considered one level deeper than the tree that contains it.
+ if (obj.getType() == OBJ_BLOB) {
+ treeDepth++;
+ } else {
+ stats.treesTraversed++;
+ }
+
+ if (filterSpec.getTreeDepthLimit() < 0 ||
+ treeDepth <= filterSpec.getTreeDepthLimit()) {
+ return false;
+ }
+
+ walker.skipTree();
+ return true;
+ }
+
// Adds the given object as an object to be packed, first performing
// filtering on blobs at or exceeding a given size.
private void filterAndAddObject(@NonNull AnyObjectId src, int type,
@@ -2079,10 +2157,10 @@ public class PackWriter implements AutoCloseable {
// Check if this object needs to be rejected, doing the cheaper
// checks first.
- boolean reject = filterBlobLimit >= 0 &&
+ boolean reject = filterSpec.getBlobLimit() >= 0 &&
type == OBJ_BLOB &&
!want.contains(src) &&
- reader.getObjectSize(src, OBJ_BLOB) > filterBlobLimit;
+ reader.getObjectSize(src, OBJ_BLOB) > filterSpec.getBlobLimit();
if (!reject) {
addObject(src, type, pathHashCode);
}
@@ -2120,7 +2198,7 @@ public class PackWriter implements AutoCloseable {
if (!cachedPacks.isEmpty()) {
if (otp.isEdge())
return;
- if ((nFmt == PACK_WHOLE) | (nFmt == PACK_DELTA)) {
+ if (nFmt == PACK_WHOLE || nFmt == PACK_DELTA) {
for (CachedPack pack : cachedPacks) {
if (pack.hasObject(otp, next)) {
otp.setEdge();
@@ -2163,7 +2241,7 @@ public class PackWriter implements AutoCloseable {
otp.clearReuseAsIs();
}
- otp.setDeltaAttempted(reuseDeltas & next.wasDeltaAttempted());
+ otp.setDeltaAttempted(reuseDeltas && next.wasDeltaAttempted());
otp.select(next);
}
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 99db74956c..d3b5e128d1 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
@@ -91,12 +91,9 @@ class PackWriterBitmapPreparer {
private static final int DAY_IN_SECONDS = 24 * 60 * 60;
- private static final Comparator<RevCommit> ORDER_BY_REVERSE_TIMESTAMP = new Comparator<RevCommit>() {
- @Override
- public int compare(RevCommit a, RevCommit b) {
- return Integer.signum(b.getCommitTime() - a.getCommitTime());
- }
- };
+ private static final Comparator<RevCommit> ORDER_BY_REVERSE_TIMESTAMP = (
+ RevCommit a, RevCommit b) -> Integer
+ .signum(b.getCommitTime() - a.getCommitTime());
private final ObjectReader reader;
private final ProgressMonitor pm;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java
new file mode 100644
index 0000000000..e16adb9bfb
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFile.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2018, Konrad Windszus <konrad_w@gmx.de>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.internal.transport.http;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.io.Writer;
+import java.net.HttpCookie;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.LinkedHashSet;
+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.file.FileSnapshot;
+import org.eclipse.jgit.internal.storage.file.LockFile;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.RawParseUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Wraps all cookies persisted in a <strong>Netscape Cookie File Format</strong>
+ * being referenced via the git config <a href=
+ * "https://git-scm.com/docs/git-config#git-config-httpcookieFile">http.cookieFile</a>.
+ * <p>
+ * It will only load the cookies lazily, i.e. before calling
+ * {@link #getCookies(boolean)} the file is not evaluated. This class also
+ * allows persisting cookies in that file format.
+ * <p>
+ * In general this class is not thread-safe. So any consumer needs to take care
+ * of synchronization!
+ *
+ * @see <a href="http://www.cookiecentral.com/faq/#3.5">Netscape Cookie File
+ * Format</a>
+ * @see <a href=
+ * "https://unix.stackexchange.com/questions/36531/format-of-cookies-when-using-wget">Cookie
+ * format for wget</a>
+ * @see <a href=
+ * "https://github.com/curl/curl/blob/07ebaf837843124ee670e5b8c218b80b92e06e47/lib/cookie.c#L745">libcurl
+ * Cookie file parsing</a>
+ * @see <a href=
+ * "https://github.com/curl/curl/blob/07ebaf837843124ee670e5b8c218b80b92e06e47/lib/cookie.c#L1417">libcurl
+ * Cookie file writing</a>
+ * @see NetscapeCookieFileCache
+ */
+public final class NetscapeCookieFile {
+
+ private static final String HTTP_ONLY_PREAMBLE = "#HttpOnly_"; //$NON-NLS-1$
+
+ private static final String COLUMN_SEPARATOR = "\t"; //$NON-NLS-1$
+
+ private static final String LINE_SEPARATOR = "\n"; //$NON-NLS-1$
+
+ /**
+ * Maximum number of retries to acquire the lock for writing to the
+ * underlying file.
+ */
+ private static final int LOCK_ACQUIRE_MAX_RETRY_COUNT = 4;
+
+ /**
+ * Sleep time in milliseconds between retries to acquire the lock for
+ * writing to the underlying file.
+ */
+ private static final int LOCK_ACQUIRE_RETRY_SLEEP = 500;
+
+ private final Path path;
+
+ private FileSnapshot snapshot;
+
+ private byte[] hash;
+
+ final Date creationDate;
+
+ private Set<HttpCookie> cookies = null;
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(NetscapeCookieFile.class);
+
+ /**
+ * @param path
+ * where to find the cookie file
+ */
+ public NetscapeCookieFile(Path path) {
+ this(path, new Date());
+ }
+
+ NetscapeCookieFile(Path path, Date creationDate) {
+ this.path = path;
+ this.snapshot = FileSnapshot.DIRTY;
+ this.creationDate = creationDate;
+ }
+
+ /**
+ * Path to the underlying cookie file.
+ *
+ * @return the path
+ */
+ public Path getPath() {
+ return path;
+ }
+
+ /**
+ * Return all cookies from the underlying cookie file.
+ *
+ * @param refresh
+ * if {@code true} updates the list from the underlying cookie
+ * file if it has been modified since the last read otherwise
+ * returns the current transient state. In case the cookie file
+ * has never been read before will always read from the
+ * underlying file disregarding the value of this parameter.
+ * @return all cookies (may contain session cookies as well). This does not
+ * return a copy of the list but rather the original one. Every
+ * addition to the returned list can afterwards be persisted via
+ * {@link #write(URL)}. Errors in the underlying file will not lead
+ * to exceptions but rather to an empty set being returned and the
+ * underlying error being logged.
+ */
+ public Set<HttpCookie> getCookies(boolean refresh) {
+ if (cookies == null || refresh) {
+ try {
+ byte[] in = getFileContentIfModified();
+ Set<HttpCookie> newCookies = parseCookieFile(in, creationDate);
+ if (cookies != null) {
+ cookies = mergeCookies(newCookies, cookies);
+ } else {
+ cookies = newCookies;
+ }
+ return cookies;
+ } catch (IOException | IllegalArgumentException e) {
+ LOG.warn(
+ MessageFormat.format(
+ JGitText.get().couldNotReadCookieFile, path),
+ e);
+ if (cookies == null) {
+ cookies = new LinkedHashSet<>();
+ }
+ }
+ }
+ return cookies;
+
+ }
+
+ /**
+ * Parses the given file and extracts all cookie information from it.
+ *
+ * @param input
+ * the file content to parse
+ * @param creationDate
+ * the date for the creation of the cookies (used to calculate
+ * the maxAge based on the expiration date given within the file)
+ * @return the set of parsed cookies from the given file (even expired
+ * ones). If there is more than one cookie with the same name in
+ * this file the last one overwrites the first one!
+ * @throws IOException
+ * if the given file could not be read for some reason
+ * @throws IllegalArgumentException
+ * if the given file does not have a proper format
+ */
+ private static Set<HttpCookie> parseCookieFile(@NonNull byte[] input,
+ @NonNull Date creationDate)
+ throws IOException, IllegalArgumentException {
+
+ String decoded = RawParseUtils.decode(StandardCharsets.US_ASCII, input);
+
+ Set<HttpCookie> cookies = new LinkedHashSet<>();
+ try (BufferedReader reader = new BufferedReader(
+ new StringReader(decoded))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ HttpCookie cookie = parseLine(line, creationDate);
+ if (cookie != null) {
+ cookies.add(cookie);
+ }
+ }
+ }
+ return cookies;
+ }
+
+ private static HttpCookie parseLine(@NonNull String line,
+ @NonNull Date creationDate) {
+ if (line.isEmpty() || (line.startsWith("#") //$NON-NLS-1$
+ && !line.startsWith(HTTP_ONLY_PREAMBLE))) {
+ return null;
+ }
+ String[] cookieLineParts = line.split(COLUMN_SEPARATOR, 7);
+ if (cookieLineParts == null) {
+ throw new IllegalArgumentException(MessageFormat
+ .format(JGitText.get().couldNotFindTabInLine, line));
+ }
+ if (cookieLineParts.length < 7) {
+ throw new IllegalArgumentException(MessageFormat.format(
+ JGitText.get().couldNotFindSixTabsInLine,
+ Integer.valueOf(cookieLineParts.length), line));
+ }
+ String name = cookieLineParts[5];
+ String value = cookieLineParts[6];
+ HttpCookie cookie = new HttpCookie(name, value);
+
+ String domain = cookieLineParts[0];
+ if (domain.startsWith(HTTP_ONLY_PREAMBLE)) {
+ cookie.setHttpOnly(true);
+ domain = domain.substring(HTTP_ONLY_PREAMBLE.length());
+ }
+ // strip off leading "."
+ // (https://tools.ietf.org/html/rfc6265#section-5.2.3)
+ if (domain.startsWith(".")) { //$NON-NLS-1$
+ domain = domain.substring(1);
+ }
+ cookie.setDomain(domain);
+ // domain evaluation as boolean flag not considered (i.e. always assumed
+ // to be true)
+ cookie.setPath(cookieLineParts[2]);
+ cookie.setSecure(Boolean.parseBoolean(cookieLineParts[3]));
+
+ long expires = Long.parseLong(cookieLineParts[4]);
+ long maxAge = (expires - creationDate.getTime()) / 1000;
+ if (maxAge <= 0) {
+ return null; // skip expired cookies
+ }
+ cookie.setMaxAge(maxAge);
+ return cookie;
+ }
+
+ /**
+ * Read the underying file and return its content but only in case it has
+ * been modified since the last access.
+ * <p>
+ * Internally calculates the hash and maintains {@link FileSnapshot}s to
+ * prevent issues described as <a href=
+ * "https://github.com/git/git/blob/master/Documentation/technical/racy-git.txt">"Racy
+ * Git problem"</a>. Inspired by {@link FileBasedConfig#load()}.
+ *
+ * @return the file contents in case the file has been modified since the
+ * last access, otherwise {@code null}
+ * @throws IOException
+ * if the file is not found or cannot be read
+ */
+ private byte[] getFileContentIfModified() throws IOException {
+ final int maxStaleRetries = 5;
+ int retries = 0;
+ File file = getPath().toFile();
+ if (!file.exists()) {
+ LOG.warn(MessageFormat.format(JGitText.get().missingCookieFile,
+ file.getAbsolutePath()));
+ return new byte[0];
+ }
+ while (true) {
+ final FileSnapshot oldSnapshot = snapshot;
+ final FileSnapshot newSnapshot = FileSnapshot.save(file);
+ try {
+ final byte[] in = IO.readFully(file);
+ byte[] newHash = hash(in);
+ if (Arrays.equals(hash, newHash)) {
+ if (oldSnapshot.equals(newSnapshot)) {
+ oldSnapshot.setClean(newSnapshot);
+ } else {
+ snapshot = newSnapshot;
+ }
+ } else {
+ snapshot = newSnapshot;
+ hash = newHash;
+ }
+ return in;
+ } catch (FileNotFoundException e) {
+ throw e;
+ } catch (IOException e) {
+ if (FileUtils.isStaleFileHandle(e)
+ && retries < maxStaleRetries) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(MessageFormat.format(
+ JGitText.get().configHandleIsStale,
+ Integer.valueOf(retries)), e);
+ }
+ retries++;
+ continue;
+ }
+ throw new IOException(MessageFormat
+ .format(JGitText.get().cannotReadFile, getPath()), e);
+ }
+ }
+
+ }
+
+ private static byte[] hash(final byte[] in) {
+ return Constants.newMessageDigest().digest(in);
+ }
+
+ /**
+ * Writes all the cookies being maintained in the set being returned by
+ * {@link #getCookies(boolean)} to the underlying file.
+ * <p>
+ * Session-cookies will not be persisted.
+ *
+ * @param url
+ * url for which to write the cookies (important to derive
+ * default values for non-explicitly set attributes)
+ * @throws IOException
+ * if the underlying cookie file could not be read or written or
+ * a problem with the lock file
+ * @throws InterruptedException
+ * if the thread is interrupted while waiting for the lock
+ */
+ public void write(URL url) throws IOException, InterruptedException {
+ try {
+ byte[] cookieFileContent = getFileContentIfModified();
+ if (cookieFileContent != null) {
+ LOG.debug("Reading the underlying cookie file '{}' " //$NON-NLS-1$
+ + "as it has been modified since " //$NON-NLS-1$
+ + "the last access", //$NON-NLS-1$
+ path);
+ // reread new changes if necessary
+ Set<HttpCookie> cookiesFromFile = NetscapeCookieFile
+ .parseCookieFile(cookieFileContent, creationDate);
+ this.cookies = mergeCookies(cookiesFromFile, cookies);
+ }
+ } catch (FileNotFoundException e) {
+ // ignore if file previously did not exist yet!
+ }
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try (Writer writer = new OutputStreamWriter(output,
+ StandardCharsets.US_ASCII)) {
+ write(writer, cookies, url, creationDate);
+ }
+ LockFile lockFile = new LockFile(path.toFile());
+ for (int retryCount = 0; retryCount < LOCK_ACQUIRE_MAX_RETRY_COUNT; retryCount++) {
+ if (lockFile.lock()) {
+ try {
+ lockFile.setNeedSnapshot(true);
+ lockFile.write(output.toByteArray());
+ if (!lockFile.commit()) {
+ throw new IOException(MessageFormat.format(
+ JGitText.get().cannotCommitWriteTo, path));
+ }
+ } finally {
+ lockFile.unlock();
+ }
+ return;
+ }
+ Thread.sleep(LOCK_ACQUIRE_RETRY_SLEEP);
+ }
+ throw new IOException(
+ MessageFormat.format(JGitText.get().cannotLock, lockFile));
+ }
+
+ /**
+ * Writes the given cookies to the file in the Netscape Cookie File Format
+ * (also used by curl).
+ *
+ * @param writer
+ * the writer to use to persist the cookies
+ * @param cookies
+ * the cookies to write into the file
+ * @param url
+ * the url for which to write the cookie (to derive the default
+ * values for certain cookie attributes)
+ * @param creationDate
+ * the date when the cookie has been created. Important for
+ * calculation the cookie expiration time (calculated from
+ * cookie's maxAge and this creation time)
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ static void write(@NonNull Writer writer,
+ @NonNull Collection<HttpCookie> cookies, @NonNull URL url,
+ @NonNull Date creationDate) throws IOException {
+ for (HttpCookie cookie : cookies) {
+ writeCookie(writer, cookie, url, creationDate);
+ }
+ }
+
+ private static void writeCookie(@NonNull Writer writer,
+ @NonNull HttpCookie cookie, @NonNull URL url,
+ @NonNull Date creationDate) throws IOException {
+ if (cookie.getMaxAge() <= 0) {
+ return; // skip expired cookies
+ }
+ String domain = ""; //$NON-NLS-1$
+ if (cookie.isHttpOnly()) {
+ domain = HTTP_ONLY_PREAMBLE;
+ }
+ if (cookie.getDomain() != null) {
+ domain += cookie.getDomain();
+ } else {
+ domain += url.getHost();
+ }
+ writer.write(domain);
+ writer.write(COLUMN_SEPARATOR);
+ writer.write("TRUE"); //$NON-NLS-1$
+ writer.write(COLUMN_SEPARATOR);
+ String path = cookie.getPath();
+ if (path == null) {
+ path = url.getPath();
+ }
+ writer.write(path);
+ writer.write(COLUMN_SEPARATOR);
+ writer.write(Boolean.toString(cookie.getSecure()).toUpperCase());
+ writer.write(COLUMN_SEPARATOR);
+ final String expirationDate;
+ // whenCreated field is not accessible in HttpCookie
+ expirationDate = String
+ .valueOf(creationDate.getTime() + (cookie.getMaxAge() * 1000));
+ writer.write(expirationDate);
+ writer.write(COLUMN_SEPARATOR);
+ writer.write(cookie.getName());
+ writer.write(COLUMN_SEPARATOR);
+ writer.write(cookie.getValue());
+ writer.write(LINE_SEPARATOR);
+ }
+
+ /**
+ * Merge the given sets in the following way. All cookies from
+ * {@code cookies1} and {@code cookies2} are contained in the resulting set
+ * which have unique names. If there is a duplicate entry for one name only
+ * the entry from set {@code cookies1} ends up in the resulting set.
+ *
+ * @param cookies1
+ * first set of cookies
+ * @param cookies2
+ * second set of cookies
+ *
+ * @return the merged cookies
+ */
+ static Set<HttpCookie> mergeCookies(Set<HttpCookie> cookies1,
+ @Nullable Set<HttpCookie> cookies2) {
+ Set<HttpCookie> mergedCookies = new LinkedHashSet<>(cookies1);
+ if (cookies2 != null) {
+ mergedCookies.addAll(cookies2);
+ }
+ return mergedCookies;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileCache.java
new file mode 100644
index 0000000000..882b2d055b
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/transport/http/NetscapeCookieFileCache.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018, Konrad Windszus <konrad_w@gmx.de>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.internal.transport.http;
+
+import java.nio.file.Path;
+
+import org.eclipse.jgit.transport.HttpConfig;
+import org.eclipse.jgit.util.LRUMap;
+
+/**
+ * A cache of all known cookie files ({@link NetscapeCookieFile}). May contain
+ * at most {@code n} entries, where the least-recently used one is evicted as
+ * soon as more entries are added. The maximum number of entries (={@code n})
+ * can be set via the git config key {@code http.cookieFileCacheLimit}. By
+ * default it is set to 10.
+ * <p>
+ * The cache is global, i.e. it is shared among all consumers within the same
+ * Java process.
+ *
+ * @see NetscapeCookieFile
+ *
+ */
+public class NetscapeCookieFileCache {
+
+ private final LRUMap<Path, NetscapeCookieFile> cookieFileMap;
+
+ private static NetscapeCookieFileCache instance;
+
+ private NetscapeCookieFileCache(HttpConfig config) {
+ cookieFileMap = new LRUMap<>(config.getCookieFileCacheLimit(),
+ config.getCookieFileCacheLimit());
+ }
+
+ /**
+ * @param config
+ * the config which defines the limit for this cache
+ * @return the singleton instance of the cookie file cache. If the cache has
+ * already been created the given config is ignored (even if it
+ * differs from the config, with which the cache has originally been
+ * created)
+ */
+ public static NetscapeCookieFileCache getInstance(HttpConfig config) {
+ if (instance == null) {
+ return new NetscapeCookieFileCache(config);
+ } else {
+ return instance;
+ }
+ }
+
+ /**
+ * @param path
+ * the path of the cookie file to retrieve
+ * @return the cache entry belonging to the requested file
+ */
+ public NetscapeCookieFile getEntry(Path path) {
+ if (!cookieFileMap.containsKey(path)) {
+ synchronized (NetscapeCookieFileCache.class) {
+ if (!cookieFileMap.containsKey(path)) {
+ cookieFileMap.put(path, new NetscapeCookieFile(path));
+ }
+ }
+ }
+ return cookieFileMap.get(path);
+ }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java
index d105d0d200..b0339c677f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AbbreviatedObjectId.java
@@ -162,7 +162,7 @@ public final class AbbreviatedObjectId implements Serializable {
r |= RawParseUtils.parseHexInt4(bs[p++]);
n++;
}
- return r << (8 - n) * 4;
+ return r << ((8 - n) * 4);
}
static int mask(int nibbles, int word, int v) {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
index 978dd3a729..4f90e69008 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/AnyObjectId.java
@@ -49,6 +49,7 @@ import java.io.Writer;
import java.nio.ByteBuffer;
import org.eclipse.jgit.util.NB;
+import org.eclipse.jgit.util.References;
/**
* A (possibly mutable) SHA-1 abstraction.
@@ -60,19 +61,37 @@ import org.eclipse.jgit.util.NB;
public abstract class AnyObjectId implements Comparable<AnyObjectId> {
/**
- * Compare to object identifier byte sequences for equality.
+ * Compare two object identifier byte sequences for equality.
*
* @param firstObjectId
* the first identifier to compare. Must not be null.
* @param secondObjectId
* the second identifier to compare. Must not be null.
* @return true if the two identifiers are the same.
+ * @deprecated use {@link #isEqual(AnyObjectId, AnyObjectId)} instead
*/
+ @Deprecated
+ @SuppressWarnings("AmbiguousMethodReference")
public static boolean equals(final AnyObjectId firstObjectId,
final AnyObjectId secondObjectId) {
- if (firstObjectId == secondObjectId)
- return true;
+ return isEqual(firstObjectId, secondObjectId);
+ }
+ /**
+ * Compare two object identifier byte sequences for equality.
+ *
+ * @param firstObjectId
+ * the first identifier to compare. Must not be null.
+ * @param secondObjectId
+ * the second identifier to compare. Must not be null.
+ * @return true if the two identifiers are the same.
+ * @since 5.4
+ */
+ public static boolean isEqual(final AnyObjectId firstObjectId,
+ final AnyObjectId secondObjectId) {
+ if (References.isSameObject(firstObjectId, secondObjectId)) {
+ return true;
+ }
// We test word 3 first since the git file-based ODB
// uses the first byte of w1, and we use w2 as the
// hash code, one of those probably came up with these
@@ -80,7 +99,6 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> {
// Therefore the first two words are very likely to be
// identical. We want to break away from collisions as
// quickly as possible.
- //
return firstObjectId.w3 == secondObjectId.w3
&& firstObjectId.w4 == secondObjectId.w4
&& firstObjectId.w5 == secondObjectId.w5
@@ -276,8 +294,9 @@ public abstract class AnyObjectId implements Comparable<AnyObjectId> {
* the other id to compare to. May be null.
* @return true only if both ObjectIds have identical bits.
*/
+ @SuppressWarnings({ "NonOverridingEquals", "AmbiguousMethodReference" })
public final boolean equals(AnyObjectId other) {
- return other != null ? equals(this, other) : false;
+ return other != null ? isEqual(this, other) : false;
}
/** {@inheritDoc} */
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
index 6cbddec543..13f71a7ff6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CommitBuilder.java
@@ -57,6 +57,7 @@ import java.text.MessageFormat;
import java.util.List;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.util.References;
/**
* Mutable builder to construct a commit recording the state of a project.
@@ -365,7 +366,7 @@ public class CommitBuilder {
os.write('\n');
}
- if (getEncoding() != UTF_8) {
+ if (!References.isSameObject(getEncoding(), UTF_8)) {
os.write(hencoding);
os.write(' ');
os.write(Constants.encodeASCII(getEncoding().name()));
@@ -474,7 +475,7 @@ public class CommitBuilder {
r.append(gpgSignature != null ? gpgSignature.toString() : "NOT_SET");
r.append("\n");
- if (encoding != null && encoding != UTF_8) {
+ if (encoding != null && !References.isSameObject(encoding, UTF_8)) {
r.append("encoding ");
r.append(encoding.name());
r.append("\n");
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 4726975d07..71f863589d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
@@ -107,7 +107,7 @@ public class Config {
* must ensure it is a special copy of the empty string. It also must
* be treated like the empty string.
*/
- static final String MAGIC_EMPTY_VALUE = new String();
+ private static final String MISSING_ENTRY = new String();
/**
* Create a configuration with no default fallback.
@@ -129,6 +129,18 @@ public class Config {
}
/**
+ * Check if a given string is the "missing" value.
+ *
+ * @param value string to be checked.
+ * @return true if the given string is the "missing" value.
+ * @since 5.4
+ */
+ @SuppressWarnings({ "ReferenceEquality", "StringEquality" })
+ public static boolean isMissing(String value) {
+ return value == MISSING_ENTRY;
+ }
+
+ /**
* Globally sets a {@link org.eclipse.jgit.lib.TypedConfigGetter} that is
* subsequently used to read typed values from all git configs.
*
@@ -1041,7 +1053,7 @@ public class Config {
if (e.prefix == null || "".equals(e.prefix)) //$NON-NLS-1$
out.append('\t');
out.append(e.name);
- if (MAGIC_EMPTY_VALUE != e.value) {
+ if (!isMissing(e.value)) {
out.append(" ="); //$NON-NLS-1$
if (e.value != null) {
out.append(' ');
@@ -1132,7 +1144,7 @@ public class Config {
e.name = readKeyName(in);
if (e.name.endsWith("\n")) { //$NON-NLS-1$
e.name = e.name.substring(0, e.name.length() - 1);
- e.value = MAGIC_EMPTY_VALUE;
+ e.value = MISSING_ENTRY;
} else
e.value = readValue(in);
@@ -1165,7 +1177,7 @@ public class Config {
private void addIncludedConfig(final List<ConfigLine> newEntries,
ConfigLine line, int depth) throws ConfigInvalidException {
if (!line.name.equalsIgnoreCase("path") || //$NON-NLS-1$
- line.value == null || line.value.equals(MAGIC_EMPTY_VALUE)) {
+ line.value == null || line.value.equals(MISSING_ENTRY)) {
throw new ConfigInvalidException(MessageFormat.format(
JGitText.get().invalidLineInConfigFileWithParam, line));
}
@@ -1413,11 +1425,23 @@ public class Config {
case '"':
value.append('"');
continue;
+ case '\r': {
+ int next = in.read();
+ if (next == '\n') {
+ continue; // CR-LF
+ } else if (next >= 0) {
+ in.reset();
+ }
+ break;
+ }
default:
- throw new ConfigInvalidException(MessageFormat.format(
- JGitText.get().badEscape,
- Character.valueOf(((char) c))));
+ break;
}
+ throw new ConfigInvalidException(
+ MessageFormat.format(JGitText.get().badEscape,
+ Character.isAlphabetic(c)
+ ? Character.valueOf(((char) c))
+ : toUnicodeLiteral(c)));
}
if ('"' == c) {
@@ -1430,6 +1454,11 @@ public class Config {
return value.length() > 0 ? value.toString() : null;
}
+ private static String toUnicodeLiteral(int c) {
+ return String.format("\\u%04x", //$NON-NLS-1$
+ Integer.valueOf(c));
+ }
+
/**
* Parses a section of the configuration into an application model object.
* <p>
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 5ae9d41db2..8f40db626a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java
@@ -365,50 +365,50 @@ public final class ConfigConstants {
public static final String CONFIG_KEY_CHECKSTAT = "checkstat";
/**
- * The "renamelimit" key in the "diff section"
+ * The "renamelimit" key in the "diff" section
* @since 3.0
*/
public static final String CONFIG_KEY_RENAMELIMIT = "renamelimit";
/**
- * The "trustfolderstat" key in the "core section"
+ * The "trustfolderstat" key in the "core" section
* @since 3.6
*/
public static final String CONFIG_KEY_TRUSTFOLDERSTAT = "trustfolderstat";
/**
- * The "supportsAtomicFileCreation" key in the "core section"
+ * The "supportsAtomicFileCreation" key in the "core" section
*
* @since 4.5
*/
public static final String CONFIG_KEY_SUPPORTSATOMICFILECREATION = "supportsatomicfilecreation";
/**
- * The "noprefix" key in the "diff section"
+ * The "noprefix" key in the "diff" section
* @since 3.0
*/
public static final String CONFIG_KEY_NOPREFIX = "noprefix";
/**
- * A "renamelimit" value in the "diff section"
+ * A "renamelimit" value in the "diff" section
* @since 3.0
*/
public static final String CONFIG_RENAMELIMIT_COPY = "copy";
/**
- * A "renamelimit" value in the "diff section"
+ * A "renamelimit" value in the "diff" section
* @since 3.0
*/
public static final String CONFIG_RENAMELIMIT_COPIES = "copies";
/**
- * The "renames" key in the "diff section"
+ * The "renames" key in the "diff" section
* @since 3.0
*/
public static final String CONFIG_KEY_RENAMES = "renames";
/**
- * The "inCoreLimit" key in the "merge section". It's a size limit (bytes) used to
+ * The "inCoreLimit" key in the "merge" section. It's a size limit (bytes) used to
* control a file to be stored in {@code Heap} or {@code LocalFile} during the merge.
* @since 4.9
*/
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 4c55196961..8f4468eef2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java
@@ -58,7 +58,7 @@ import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.util.MutableInteger;
/**
- * Misc. constants used throughout JGit.
+ * Misc. constants and helpers used throughout JGit.
*/
@SuppressWarnings("nls")
public final class Constants {
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 fb239399ed..e865da83b1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/DefaultTypedConfigGetter.java
@@ -72,7 +72,7 @@ public class DefaultTypedConfigGetter implements TypedConfigGetter {
if (n == null) {
return defaultValue;
}
- if (Config.MAGIC_EMPTY_VALUE == n) {
+ if (Config.isMissing(n)) {
return true;
}
try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java
index d4c4d5b40d..8fa8d5f7d5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileMode.java
@@ -88,6 +88,7 @@ public abstract class FileMode {
public static final FileMode TREE = new FileMode(TYPE_TREE,
Constants.OBJ_TREE) {
@Override
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(int modeBits) {
return (modeBits & TYPE_MASK) == TYPE_TREE;
}
@@ -97,6 +98,7 @@ public abstract class FileMode {
public static final FileMode SYMLINK = new FileMode(TYPE_SYMLINK,
Constants.OBJ_BLOB) {
@Override
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(int modeBits) {
return (modeBits & TYPE_MASK) == TYPE_SYMLINK;
}
@@ -106,6 +108,7 @@ public abstract class FileMode {
public static final FileMode REGULAR_FILE = new FileMode(0100644,
Constants.OBJ_BLOB) {
@Override
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(int modeBits) {
return (modeBits & TYPE_MASK) == TYPE_FILE && (modeBits & 0111) == 0;
}
@@ -115,6 +118,7 @@ public abstract class FileMode {
public static final FileMode EXECUTABLE_FILE = new FileMode(0100755,
Constants.OBJ_BLOB) {
@Override
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(int modeBits) {
return (modeBits & TYPE_MASK) == TYPE_FILE && (modeBits & 0111) != 0;
}
@@ -124,6 +128,7 @@ public abstract class FileMode {
public static final FileMode GITLINK = new FileMode(TYPE_GITLINK,
Constants.OBJ_COMMIT) {
@Override
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(int modeBits) {
return (modeBits & TYPE_MASK) == TYPE_GITLINK;
}
@@ -133,6 +138,7 @@ public abstract class FileMode {
public static final FileMode MISSING = new FileMode(TYPE_MISSING,
Constants.OBJ_BAD) {
@Override
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(int modeBits) {
return modeBits == 0;
}
@@ -165,6 +171,7 @@ public abstract class FileMode {
return new FileMode(bits, Constants.OBJ_BAD) {
@Override
+ @SuppressWarnings("NonOverridingEquals")
public boolean equals(int a) {
return bits == a;
}
@@ -206,6 +213,7 @@ public abstract class FileMode {
* a int.
* @return true if the mode bits represent the same mode as this object
*/
+ @SuppressWarnings("NonOverridingEquals")
public abstract boolean equals(int modebits);
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
index f37c310752..ce1eb597fc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
@@ -352,12 +352,7 @@ public class IndexDiff {
public WorkingTreeIterator getWorkingTreeIterator(Repository repo);
}
- private WorkingTreeIteratorFactory wTreeIt = new WorkingTreeIteratorFactory() {
- @Override
- public WorkingTreeIterator getWorkingTreeIterator(Repository repo) {
- return new FileTreeIterator(repo);
- }
- };
+ private WorkingTreeIteratorFactory wTreeIt = FileTreeIterator::new;
/**
* Allows higher layers to set the factory for WorkingTreeIterators.
@@ -647,11 +642,12 @@ public class IndexDiff {
private void addConflict(String path, int stage) {
StageState existingStageStates = conflicts.get(path);
byte stageMask = 0;
- if (existingStageStates != null)
- stageMask |= existingStageStates.getStageMask();
+ if (existingStageStates != null) {
+ stageMask |= (byte) existingStageStates.getStageMask();
+ }
// stage 1 (base) should be shifted 0 times
int shifts = stage - 1;
- stageMask |= (1 << shifts);
+ stageMask |= (byte) (1 << shifts);
StageState stageState = StageState.fromMask(stageMask);
conflicts.put(path, stageState);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
index b791c64552..d65c1bdf1a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdRef.java
@@ -67,7 +67,7 @@ public abstract class ObjectIdRef implements Ref {
*/
public Unpeeled(@NonNull Storage st, @NonNull String name,
@Nullable ObjectId id) {
- super(st, name, id, -1);
+ super(st, name, id, UNDEFINED_UPDATE_INDEX);
}
/**
@@ -119,7 +119,7 @@ public abstract class ObjectIdRef implements Ref {
*/
public PeeledTag(@NonNull Storage st, @NonNull String name,
@Nullable ObjectId id, @NonNull ObjectId p) {
- super(st, name, id, -1);
+ super(st, name, id, UNDEFINED_UPDATE_INDEX);
peeledObjectId = p;
}
@@ -172,7 +172,7 @@ public abstract class ObjectIdRef implements Ref {
*/
public PeeledNonTag(@NonNull Storage st, @NonNull String name,
@Nullable ObjectId id) {
- super(st, name, id, -1);
+ super(st, name, id, UNDEFINED_UPDATE_INDEX);
}
/**
@@ -284,7 +284,7 @@ public abstract class ObjectIdRef implements Ref {
*/
@Override
public long getUpdateIndex() {
- if (updateIndex == -1) {
+ if (updateIndex == UNDEFINED_UPDATE_INDEX) {
throw new UnsupportedOperationException();
}
return updateIndex;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java
index cd57bda82e..470275beb1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectIdSubclassMap.java
@@ -103,8 +103,9 @@ public class ObjectIdSubclassMap<V extends ObjectId>
V obj;
while ((obj = tbl[i]) != null) {
- if (AnyObjectId.equals(obj, toFind))
+ if (AnyObjectId.isEqual(obj, toFind)) {
return obj;
+ }
i = (i + 1) & msk;
}
return null;
@@ -162,7 +163,7 @@ public class ObjectIdSubclassMap<V extends ObjectId>
V obj;
while ((obj = tbl[i]) != null) {
- if (AnyObjectId.equals(obj, newValue))
+ if (AnyObjectId.isEqual(obj, newValue))
return obj;
i = (i + 1) & msk;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
index 0d31851836..ebbb3a4844 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RebaseTodoFile.java
@@ -181,7 +181,7 @@ public class RebaseTodoFile {
int nextSpace = RawParseUtils.next(buf, tokenBegin, ' ');
int tokenCount = 0;
- while (tokenCount < 3 && nextSpace < lineEnd) {
+ while (tokenCount < 3 && nextSpace <= lineEnd) {
switch (tokenCount) {
case 0:
String actionToken = new String(buf, tokenBegin,
@@ -193,8 +193,14 @@ public class RebaseTodoFile {
break;
case 1:
nextSpace = RawParseUtils.next(buf, tokenBegin, ' ');
- String commitToken = new String(buf, tokenBegin,
- nextSpace - tokenBegin - 1, UTF_8);
+ String commitToken;
+ if (nextSpace > lineEnd + 1) {
+ commitToken = new String(buf, tokenBegin,
+ lineEnd - tokenBegin + 1, UTF_8);
+ } else {
+ commitToken = new String(buf, tokenBegin,
+ nextSpace - tokenBegin - 1, UTF_8);
+ }
tokenBegin = nextSpace;
commit = AbbreviatedObjectId.fromString(commitToken);
break;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
index 32c8b06c91..4082d21c2e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Ref.java
@@ -126,6 +126,13 @@ public interface Ref {
}
/**
+ * Update index value when a reference doesn't have one
+ *
+ * @since 5.4
+ */
+ long UNDEFINED_UPDATE_INDEX = -1L;
+
+ /**
* What this ref is called within the repository.
*
* @return name of this ref.
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 877792097c..4d9450e758 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java
@@ -44,6 +44,7 @@
package org.eclipse.jgit.lib;
import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
import java.io.IOException;
import java.util.ArrayList;
@@ -52,7 +53,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
+import java.util.Set;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
@@ -470,6 +471,31 @@ public abstract class RefDatabase {
return Collections.unmodifiableList(result);
}
+
+ /**
+ * Returns all refs that resolve directly to the given {@link ObjectId}.
+ * Includes peeled {@linkObjectId}s. This is the inverse lookup of
+ * {@link #exactRef(String...)}.
+ *
+ * <p>
+ * The default implementation uses a linear scan. Implementors of
+ * {@link RefDatabase} should override this method directly if a better
+ * implementation is possible.
+ *
+ * @param id
+ * {@link ObjectId} to resolve
+ * @return a {@link Set} of {@link Ref}s whose tips point to the provided
+ * id.
+ * @throws java.io.IOException
+ * the reference space cannot be accessed.
+ * @since 5.4
+ */
+ @NonNull
+ public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
+ return getRefs().stream().filter(r -> id.equals(r.getObjectId())
+ || id.equals(r.getPeeledObjectId())).collect(toSet());
+ }
+
/**
* Check if any refs exist in the ref database.
* <p>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
index 1ce1528344..eca15c032a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefUpdate.java
@@ -53,6 +53,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PushCertificate;
+import org.eclipse.jgit.util.References;
/**
* Creates, updates or deletes any reference.
@@ -599,6 +600,7 @@ public abstract class RefUpdate {
*/
public Result update() throws IOException {
try (RevWalk rw = new RevWalk(getRepository())) {
+ rw.setRetainBody(false);
return update(rw);
}
}
@@ -646,6 +648,7 @@ public abstract class RefUpdate {
*/
public Result delete() throws IOException {
try (RevWalk rw = new RevWalk(getRepository())) {
+ rw.setRetainBody(false);
return delete(rw);
}
}
@@ -751,7 +754,7 @@ public abstract class RefUpdate {
if (expValue != null) {
final ObjectId o;
o = oldValue != null ? oldValue : ObjectId.zeroId();
- if (!AnyObjectId.equals(expValue, o)) {
+ if (!AnyObjectId.isEqual(expValue, o)) {
return Result.LOCK_FAILURE;
}
}
@@ -766,7 +769,8 @@ public abstract class RefUpdate {
}
oldObj = safeParseOld(walk, oldValue);
- if (newObj == oldObj && !detachingSymbolicRef) {
+ if (References.isSameObject(newObj, oldObj)
+ && !detachingSymbolicRef) {
return store.execute(Result.NO_CHANGE);
}
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 a61897a652..68866ea279 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -240,6 +240,15 @@ public abstract class Repository implements AutoCloseable {
}
/**
+ * Get repository identifier.
+ *
+ * @return repository identifier. The returned identifier has to be unique
+ * within a given Git server.
+ * @since 5.4
+ */
+ public abstract String getIdentifier();
+
+ /**
* Get the object database which stores this repository's data.
*
* @return the object database which stores this repository's data.
@@ -489,6 +498,7 @@ public abstract class Repository implements AutoCloseable {
throws AmbiguousObjectException, IncorrectObjectTypeException,
RevisionSyntaxException, IOException {
try (RevWalk rw = new RevWalk(this)) {
+ rw.setRetainBody(false);
Object resolved = resolve(rw, revstr);
if (resolved instanceof String) {
final Ref ref = findRef((String) resolved);
@@ -515,6 +525,7 @@ public abstract class Repository implements AutoCloseable {
public String simplify(String revstr)
throws AmbiguousObjectException, IOException {
try (RevWalk rw = new RevWalk(this)) {
+ rw.setRetainBody(true);
Object resolved = resolve(rw, revstr);
if (resolved != null)
if (resolved instanceof String)
@@ -606,7 +617,7 @@ public abstract class Repository implements AutoCloseable {
if (!(rev instanceof RevBlob))
throw new IncorrectObjectTypeException(rev,
Constants.TYPE_BLOB);
- } else if (item.equals("")) { //$NON-NLS-1$
+ } else if (item.isEmpty()) {
rev = rw.peel(rev);
} else
throw new RevisionSyntaxException(revstr);
@@ -707,7 +718,7 @@ public abstract class Repository implements AutoCloseable {
if (time.equals("upstream")) { //$NON-NLS-1$
if (name == null)
name = new String(revChars, done, i);
- if (name.equals("")) //$NON-NLS-1$
+ if (name.isEmpty())
// Currently checked out branch, HEAD if
// detached
name = Constants.HEAD;
@@ -762,7 +773,7 @@ public abstract class Repository implements AutoCloseable {
} else {
if (name == null)
name = new String(revChars, done, i);
- if (name.equals("")) //$NON-NLS-1$
+ if (name.isEmpty())
name = Constants.HEAD;
if (!Repository.isValidRefName("x/" + name)) //$NON-NLS-1$
throw new RevisionSyntaxException(MessageFormat
@@ -788,7 +799,7 @@ public abstract class Repository implements AutoCloseable {
if (rev == null) {
if (name == null)
name = new String(revChars, done, i);
- if (name.equals("")) //$NON-NLS-1$
+ if (name.isEmpty())
name = Constants.HEAD;
rev = parseSimple(rw, name);
name = null;
@@ -921,7 +932,7 @@ public abstract class Repository implements AutoCloseable {
AbbreviatedObjectId id = AbbreviatedObjectId.fromString(revstr);
try (ObjectReader reader = newObjectReader()) {
Collection<ObjectId> matches = reader.resolve(id);
- if (matches.size() == 0)
+ if (matches.isEmpty())
return null;
else if (matches.size() == 1)
return matches.iterator().next();
@@ -1275,11 +1286,8 @@ public abstract class Repository implements AutoCloseable {
CorruptObjectException, IOException {
// we want DirCache to inform us so that we can inform registered
// listeners about index changes
- IndexChangedListener l = new IndexChangedListener() {
- @Override
- public void onIndexChanged(IndexChangedEvent event) {
- notifyIndexChanged(true);
- }
+ IndexChangedListener l = (IndexChangedEvent event) -> {
+ notifyIndexChanged(true);
};
return DirCache.lock(this, l);
}
@@ -1528,19 +1536,22 @@ public abstract class Repository implements AutoCloseable {
final String filePath = file.getPath();
final String workDirPath = workDir.getPath();
- if (filePath.length() <= workDirPath.length() ||
- filePath.charAt(workDirPath.length()) != File.separatorChar ||
- !filePath.startsWith(workDirPath)) {
- File absWd = workDir.isAbsolute() ? workDir : workDir.getAbsoluteFile();
+ if (filePath.length() <= workDirPath.length()
+ || filePath.charAt(workDirPath.length()) != File.separatorChar
+ || !filePath.startsWith(workDirPath)) {
+ File absWd = workDir.isAbsolute() ? workDir
+ : workDir.getAbsoluteFile();
File absFile = file.isAbsolute() ? file : file.getAbsoluteFile();
- if (absWd == workDir && absFile == file)
+ if (absWd.equals(workDir) && absFile.equals(file)) {
return ""; //$NON-NLS-1$
+ }
return stripWorkDir(absWd, absFile);
}
String relName = filePath.substring(workDirPath.length() + 1);
- if (File.separatorChar != '/')
+ if (File.separatorChar != '/') {
relName = relName.replace(File.separatorChar, '/');
+ }
return relName;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
index 400342b1bd..27befba5a4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java
@@ -255,14 +255,11 @@ public class RepositoryCache {
if (delay == RepositoryCacheConfig.NO_CLEANUP) {
return;
}
- cleanupTask = scheduler.scheduleWithFixedDelay(new Runnable() {
- @Override
- public void run() {
- try {
- cache.clearAllExpired();
- } catch (Throwable e) {
- LOG.error(e.getMessage(), e);
- }
+ cleanupTask = scheduler.scheduleWithFixedDelay(() -> {
+ try {
+ cache.clearAllExpired();
+ } catch (Throwable e) {
+ LOG.error(e.getMessage(), e);
}
}, delay, delay, TimeUnit.MILLISECONDS);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
index 00fcf52037..9f0568f0c2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/SymbolicRef.java
@@ -71,7 +71,7 @@ public class SymbolicRef implements Ref {
public SymbolicRef(@NonNull String refName, @NonNull Ref target) {
this.name = refName;
this.target = target;
- this.updateIndex = -1;
+ this.updateIndex = UNDEFINED_UPDATE_INDEX;
}
/**
@@ -155,7 +155,7 @@ public class SymbolicRef implements Ref {
*/
@Override
public long getUpdateIndex() {
- if (updateIndex == -1) {
+ if (updateIndex == UNDEFINED_UPDATE_INDEX) {
throw new UnsupportedOperationException();
}
return updateIndex;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java
index 091667db01..0d44317658 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgKeyLocator.java
@@ -54,6 +54,8 @@ import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Locale;
@@ -67,6 +69,7 @@ import org.bouncycastle.gpg.keybox.KeyBox;
import org.bouncycastle.gpg.keybox.KeyInformation;
import org.bouncycastle.gpg.keybox.PublicKeyRingBlob;
import org.bouncycastle.gpg.keybox.UserID;
+import org.bouncycastle.gpg.keybox.jcajce.JcaKeyBoxBuilder;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSecretKey;
@@ -85,6 +88,8 @@ import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Locates GPG keys from either <code>~/.gnupg/private-keys-v1.d</code> or
@@ -92,6 +97,9 @@ import org.eclipse.jgit.util.SystemReader;
*/
class BouncyCastleGpgKeyLocator {
+ private static final Logger log = LoggerFactory
+ .getLogger(BouncyCastleGpgKeyLocator.class);
+
private static final Path GPG_DIRECTORY = findGpgDirectory();
private static final Path USER_KEYBOX_PATH = GPG_DIRECTORY
@@ -157,11 +165,14 @@ class BouncyCastleGpgKeyLocator {
private PGPSecretKey attemptParseSecretKey(Path keyFile,
PGPDigestCalculatorProvider calculatorProvider,
PBEProtectionRemoverFactory passphraseProvider,
- PGPPublicKey publicKey) throws IOException {
+ PGPPublicKey publicKey) {
try (InputStream in = newInputStream(keyFile)) {
return new SExprParser(calculatorProvider).parseSecretKey(
new BufferedInputStream(in), passphraseProvider, publicKey);
- } catch (PGPException | ClassCastException e) {
+ } catch (IOException | PGPException | ClassCastException e) {
+ if (log.isDebugEnabled())
+ log.debug("Ignoring unreadable file '{}': {}", keyFile, //$NON-NLS-1$
+ e.getMessage(), e);
return null;
}
}
@@ -173,10 +184,11 @@ class BouncyCastleGpgKeyLocator {
private PGPPublicKey findPublicKeyByKeyId(KeyBlob keyBlob)
throws IOException {
+ String keyId = signingKey.toLowerCase(Locale.ROOT);
for (KeyInformation keyInfo : keyBlob.getKeyInformation()) {
- if (signingKey.toLowerCase(Locale.ROOT)
- .equals(Hex.toHexString(keyInfo.getKeyID())
- .toLowerCase(Locale.ROOT))) {
+ String fingerprint = Hex.toHexString(keyInfo.getFingerprint())
+ .toLowerCase(Locale.ROOT);
+ if (fingerprint.endsWith(keyId)) {
return getFirstPublicKey(keyBlob);
}
}
@@ -201,9 +213,12 @@ class BouncyCastleGpgKeyLocator {
* @return publicKey the public key (maybe <code>null</code>)
* @throws IOException
* in case of problems reading the file
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchProviderException
*/
private PGPPublicKey findPublicKeyInKeyBox(Path keyboxFile)
- throws IOException {
+ throws IOException, NoSuchAlgorithmException,
+ NoSuchProviderException {
KeyBox keyBox = readKeyBoxFile(keyboxFile);
for (KeyBlob keyBlob : keyBox.getKeyBlobs()) {
if (keyBlob.getType() == BlobType.OPEN_PGP_BLOB) {
@@ -227,15 +242,17 @@ class BouncyCastleGpgKeyLocator {
* @return the secret key
* @throws IOException
* in case of issues reading key files
+ * @throws NoSuchAlgorithmException
+ * @throws NoSuchProviderException
* @throws PGPException
* in case of issues finding a key
* @throws CanceledException
* @throws URISyntaxException
* @throws UnsupportedCredentialItem
*/
- public BouncyCastleGpgKey findSecretKey()
- throws IOException, PGPException, CanceledException,
- UnsupportedCredentialItem, URISyntaxException {
+ public BouncyCastleGpgKey findSecretKey() throws IOException,
+ NoSuchAlgorithmException, NoSuchProviderException, PGPException,
+ CanceledException, UnsupportedCredentialItem, URISyntaxException {
if (exists(USER_KEYBOX_PATH)) {
PGPPublicKey publicKey = //
findPublicKeyInKeyBox(USER_KEYBOX_PATH);
@@ -252,6 +269,10 @@ class BouncyCastleGpgKeyLocator {
USER_PGP_LEGACY_SECRING_FILE);
if (secretKey != null) {
+ if (!secretKey.isSigningKey()) {
+ throw new PGPException(MessageFormat.format(
+ JGitText.get().gpgNotASigningKey, signingKey));
+ }
return new BouncyCastleGpgKey(secretKey, USER_PGP_LEGACY_SECRING_FILE);
}
@@ -285,6 +306,10 @@ class BouncyCastleGpgKeyLocator {
PGPSecretKey secretKey = attemptParseSecretKey(keyFile,
calculatorProvider, passphraseProvider, publicKey);
if (secretKey != null) {
+ if (!secretKey.isSigningKey()) {
+ throw new PGPException(MessageFormat.format(
+ JGitText.get().gpgNotASigningKey, signingKey));
+ }
return new BouncyCastleGpgKey(secretKey, userKeyboxPath);
}
}
@@ -326,6 +351,7 @@ class BouncyCastleGpgKeyLocator {
PGPUtil.getDecoderStream(new BufferedInputStream(in)),
new JcaKeyFingerprintCalculator());
+ String keyId = signingkey.toLowerCase(Locale.ROOT);
Iterator<PGPSecretKeyRing> keyrings = pgpSec.getKeyRings();
while (keyrings.hasNext()) {
PGPSecretKeyRing keyRing = keyrings.next();
@@ -336,8 +362,7 @@ class BouncyCastleGpgKeyLocator {
String fingerprint = Hex
.toHexString(key.getPublicKey().getFingerprint())
.toLowerCase(Locale.ROOT);
- if (fingerprint
- .endsWith(signingkey.toLowerCase(Locale.ROOT))) {
+ if (fingerprint.endsWith(keyId)) {
return key;
}
// try user id
@@ -359,14 +384,12 @@ class BouncyCastleGpgKeyLocator {
.getPublicKey();
}
- private KeyBox readKeyBoxFile(Path keyboxFile) throws IOException {
+ private KeyBox readKeyBoxFile(Path keyboxFile) throws IOException,
+ NoSuchAlgorithmException, NoSuchProviderException {
KeyBox keyBox;
try (InputStream in = new BufferedInputStream(
newInputStream(keyboxFile))) {
- // note: KeyBox constructor reads in the whole InputStream at once
- // this code will change in 1.61 to
- // either 'new BcKeyBox(in)' or 'new JcaKeyBoxBuilder().build(in)'
- keyBox = new KeyBox(in, new JcaKeyFingerprintCalculator());
+ keyBox = new JcaKeyBoxBuilder().build(in);
}
return keyBox;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java
index 4d696dd9e7..cfe0931b47 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/BouncyCastleGpgSigner.java
@@ -45,6 +45,8 @@ package org.eclipse.jgit.lib.internal;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
import java.security.Security;
import org.bouncycastle.bcpg.ArmoredOutputStream;
@@ -100,7 +102,8 @@ public class BouncyCastleGpgSigner extends GpgSigner {
BouncyCastleGpgKey gpgKey = locateSigningKey(gpgSigningKey,
committer, passphrasePrompt);
return gpgKey != null;
- } catch (PGPException | IOException | URISyntaxException e) {
+ } catch (PGPException | IOException | NoSuchAlgorithmException
+ | NoSuchProviderException | URISyntaxException e) {
return false;
}
}
@@ -109,7 +112,8 @@ public class BouncyCastleGpgSigner extends GpgSigner {
PersonIdent committer,
BouncyCastleGpgKeyPassphrasePrompt passphrasePrompt)
throws CanceledException, UnsupportedCredentialItem, IOException,
- PGPException, URISyntaxException {
+ NoSuchAlgorithmException, NoSuchProviderException, PGPException,
+ URISyntaxException {
if (gpgSigningKey == null || gpgSigningKey.isEmpty()) {
gpgSigningKey = committer.getEmailAddress();
}
@@ -153,7 +157,8 @@ public class BouncyCastleGpgSigner extends GpgSigner {
signatureGenerator.generate().encode(out);
}
commit.setGpgSignature(new GpgSignature(buffer.toByteArray()));
- } catch (PGPException | IOException | URISyntaxException e) {
+ } catch (PGPException | IOException | NoSuchAlgorithmException
+ | NoSuchProviderException | URISyntaxException e) {
throw new JGitInternalException(e.getMessage(), e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java
index dd42e43841..a77cb4ffb9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java
@@ -86,6 +86,11 @@ public final class MergeAlgorithm {
private final static Edit END_EDIT = new Edit(Integer.MAX_VALUE,
Integer.MAX_VALUE);
+ @SuppressWarnings("ReferenceEquality")
+ private static boolean isEndEdit(Edit edit) {
+ return edit == END_EDIT;
+ }
+
/**
* Does the three way merge between a common base and two sequences.
*
@@ -145,7 +150,7 @@ public final class MergeAlgorithm {
// iterate over all edits from base to ours and from base to theirs
// leave the loop when there are no edits more for ours or for theirs
// (or both)
- while (theirsEdit != END_EDIT || oursEdit != END_EDIT) {
+ while (!isEndEdit(theirsEdit) || !isEndEdit(oursEdit)) {
if (oursEdit.getEndA() < theirsEdit.getBeginA()) {
// something was changed in ours not overlapping with any change
// from theirs. First add the common part in front of the edit
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
index 75334ddb0c..0b423fb5d4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -1182,7 +1182,7 @@ public class ResolveMerger extends ThreeWayMerger {
* fail.
*/
public Map<String, MergeFailureReason> getFailingPaths() {
- return (failingPaths.size() == 0) ? null : failingPaths;
+ return failingPaths.isEmpty() ? null : failingPaths;
}
/**
@@ -1193,7 +1193,7 @@ public class ResolveMerger extends ThreeWayMerger {
* otherwise
*/
public boolean failed() {
- return failingPaths.size() > 0;
+ return !failingPaths.isEmpty();
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/nls/GlobalBundleCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/nls/GlobalBundleCache.java
index fd425abf35..b437f635f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/nls/GlobalBundleCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/nls/GlobalBundleCache.java
@@ -43,6 +43,7 @@
package org.eclipse.jgit.nls;
+import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@@ -92,14 +93,13 @@ class GlobalBundleCache {
}
TranslationBundle bundle = bundles.get(type);
if (bundle == null) {
- bundle = type.newInstance();
+ bundle = type.getDeclaredConstructor().newInstance();
bundle.load(locale);
bundles.put(type, bundle);
}
return (T) bundle;
- } catch (InstantiationException e) {
- throw new Error(e);
- } catch (IllegalAccessException e) {
+ } catch (InstantiationException | IllegalAccessException
+ | InvocationTargetException | NoSuchMethodException e) {
throw new Error(e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/nls/TranslationBundle.java b/org.eclipse.jgit/src/org/eclipse/jgit/nls/TranslationBundle.java
index cdd7be266f..c41fb416d5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/nls/TranslationBundle.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/nls/TranslationBundle.java
@@ -182,9 +182,7 @@ public abstract class TranslationBundle {
field.set(this, translatedText);
} catch (MissingResourceException e) {
throw new TranslationStringMissingException(bundleClass, locale, field.getName(), e);
- } catch (IllegalArgumentException e) {
- throw new Error(e);
- } catch (IllegalAccessException e) {
+ } catch (IllegalArgumentException | IllegalAccessException e) {
throw new Error(e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMapMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMapMerger.java
index 325ff4f268..ba7223b8f0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMapMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteMapMerger.java
@@ -295,14 +295,14 @@ public class NoteMapMerger {
private static boolean sameNote(Note a, Note b) {
if (a == null && b == null)
return true;
- return a != null && b != null && AnyObjectId.equals(a, b);
+ return a != null && b != null && AnyObjectId.isEqual(a, b);
}
private static boolean sameContent(Note a, Note b) {
if (a == null && b == null)
return true;
return a != null && b != null
- && AnyObjectId.equals(a.getData(), b.getData());
+ && AnyObjectId.isEqual(a.getData(), b.getData());
}
private static InMemoryNoteBucket addIfNotNull(InMemoryNoteBucket result,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java
index d278132c61..74eec81209 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/CombinedHunkHeader.java
@@ -109,12 +109,13 @@ public class CombinedHunkHeader extends HunkHeader {
final MutableInteger ptr = new MutableInteger();
ptr.value = nextLF(buf, startOffset, ' ');
- for (int n = 0; n < old.length; n++) {
- old[n].startLine = -parseBase10(buf, ptr.value, ptr);
- if (buf[ptr.value] == ',')
- old[n].lineCount = parseBase10(buf, ptr.value + 1, ptr);
- else
- old[n].lineCount = 1;
+ for (CombinedOldImage o : old) {
+ o.startLine = -parseBase10(buf, ptr.value, ptr);
+ if (buf[ptr.value] == ',') {
+ o.lineCount = parseBase10(buf, ptr.value + 1, ptr);
+ } else {
+ o.lineCount = 1;
+ }
}
newStartLine = parseBase10(buf, ptr.value + 1, ptr);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java
index 58e2106fe2..b2f8d11921 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revplot/AbstractPlotRenderer.java
@@ -114,39 +114,39 @@ public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> {
drawLine(myColor, myLaneX, h, myLaneX, (h + dotSize) / 2,
LINE_WIDTH);
- for (int i = 0; i < commit.mergingLanes.length; i++) {
- final TLane pLane = (TLane) commit.mergingLanes[i];
+ for (PlotLane mergingLane : commit.mergingLanes) {
+ final TLane pLane = (TLane) mergingLane;
final TColor pColor = laneColor(pLane);
final int cx = laneC(pLane);
-
if (Math.abs(myLaneX - cx) > LANE_WIDTH) {
final int ix;
- if (myLaneX < cx)
+ if (myLaneX < cx) {
ix = cx - LANE_WIDTH / 2;
- else
+ } else {
ix = cx + LANE_WIDTH / 2;
+ }
drawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
drawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH);
} else
drawLine(pColor, myLaneX, h / 2, cx, h, LINE_WIDTH);
-
maxCenter = Math.max(maxCenter, cx);
}
}
if (commit.getChildCount() > 0) {
- for (int i = 0; i < commit.forkingOffLanes.length; i++) {
- final TLane childLane = (TLane) commit.forkingOffLanes[i];
+ for (PlotLane forkingOffLane : commit.forkingOffLanes) {
+ final TLane childLane = (TLane) forkingOffLane;
final TColor cColor = laneColor(childLane);
final int cx = laneC(childLane);
if (Math.abs(myLaneX - cx) > LANE_WIDTH) {
final int ix;
- if (myLaneX < cx)
+ if (myLaneX < cx) {
ix = cx - LANE_WIDTH / 2;
- else
+ } else {
ix = cx + LANE_WIDTH / 2;
+ }
drawLine(cColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
drawLine(cColor, ix, h / 2, cx, 0, LINE_WIDTH);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapCalculator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapCalculator.java
new file mode 100644
index 0000000000..14e95670aa
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapCalculator.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.revwalk;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.internal.revwalk.AddToBitmapFilter;
+import org.eclipse.jgit.lib.BitmapIndex;
+import org.eclipse.jgit.lib.BitmapIndex.Bitmap;
+import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
+import org.eclipse.jgit.lib.ProgressMonitor;
+
+/**
+ * Calculate the bitmap indicating what other commits are reachable from certain
+ * commit.
+ * <p>
+ * This bitmap refers only to commits. For a bitmap with ALL objects reachable
+ * from certain object, see {@code BitmapWalker}.
+ */
+class BitmapCalculator {
+
+ private final RevWalk walk;
+ private final BitmapIndex bitmapIndex;
+
+ BitmapCalculator(RevWalk walk) throws IOException {
+ this.walk = walk;
+ this.bitmapIndex = requireNonNull(
+ walk.getObjectReader().getBitmapIndex());
+ }
+
+ /**
+ * Get the reachability bitmap from certain commit to other commits.
+ * <p>
+ * This will return a precalculated bitmap if available or walk building one
+ * until finding a precalculated bitmap (and returning the union).
+ * <p>
+ * Beware that the returned bitmap it is guaranteed to include ONLY the
+ * commits reachable from the initial commit. It COULD include other objects
+ * (because precalculated bitmaps have them) but caller shouldn't count on
+ * that. See {@link BitmapWalker} for a full reachability bitmap.
+ *
+ * @param start
+ * the commit. Use {@code walk.parseCommit(objectId)} to get this
+ * object from the id.
+ * @param pm
+ * progress monitor. Updated by one per commit browsed in the
+ * graph
+ * @return the bitmap of reachable commits (and maybe some extra objects)
+ * for the commit
+ * @throws MissingObjectException
+ * the supplied id doesn't exist
+ * @throws IncorrectObjectTypeException
+ * the supplied id doesn't refer to a commit or a tag
+ * @throws IOException
+ * if the walk cannot open a packfile or loose object
+ */
+ BitmapBuilder getBitmap(RevCommit start, ProgressMonitor pm)
+ throws MissingObjectException,
+ IncorrectObjectTypeException, IOException {
+ Bitmap precalculatedBitmap = bitmapIndex.getBitmap(start);
+ if (precalculatedBitmap != null) {
+ return asBitmapBuilder(precalculatedBitmap);
+ }
+
+ walk.reset();
+ walk.sort(RevSort.TOPO);
+ walk.markStart(start);
+ // Unbounded walk. If the repo has bitmaps, it should bump into one at
+ // some point.
+
+ BitmapBuilder bitmapResult = bitmapIndex.newBitmapBuilder();
+ walk.setRevFilter(new AddToBitmapFilter(bitmapResult));
+ while (walk.next() != null) {
+ // Iterate through all of the commits. The BitmapRevFilter does
+ // the work.
+ //
+ // filter.include returns true for commits that do not have
+ // a bitmap in bitmapIndex and are not reachable from a
+ // bitmap in bitmapIndex encountered earlier in the walk.
+ // Thus the number of commits returned by next() measures how
+ // much history was traversed without being able to make use
+ // of bitmaps.
+ pm.update(1);
+ }
+
+ return bitmapResult;
+ }
+
+ private BitmapBuilder asBitmapBuilder(Bitmap bitmap) {
+ return bitmapIndex.newBitmapBuilder().or(bitmap);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmappedReachabilityChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmappedReachabilityChecker.java
new file mode 100644
index 0000000000..6e510f677b
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmappedReachabilityChecker.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019, Google LLC
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.revwalk;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+
+/**
+ * Checks the reachability using bitmaps.
+ */
+class BitmappedReachabilityChecker implements ReachabilityChecker {
+
+ private final RevWalk walk;
+
+ /**
+ * @param walk
+ * walk on the repository to get or create the bitmaps for the
+ * commits. It must have bitmaps.
+ * @throws AssertionError
+ * runtime exception if walk is over a repository without
+ * bitmaps
+ * @throws IOException
+ * if the index or the object reader cannot be opened.
+ */
+ public BitmappedReachabilityChecker(RevWalk walk)
+ throws IOException {
+ this.walk = walk;
+ if (walk.getObjectReader().getBitmapIndex() == null) {
+ throw new AssertionError(
+ "Trying to use bitmapped reachability check " //$NON-NLS-1$
+ + "on a repository without bitmaps"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Check all targets are reachable from the starters.
+ * <p>
+ * In this implementation, it is recommended to put the most popular
+ * starters (e.g. refs/heads tips) at the beginning of the collection
+ */
+ @Override
+ public Optional<RevCommit> areAllReachable(Collection<RevCommit> targets,
+ Collection<RevCommit> starters) throws MissingObjectException,
+ IncorrectObjectTypeException, IOException {
+ BitmapCalculator calculator = new BitmapCalculator(walk);
+
+ /**
+ * Iterate over starters bitmaps and remove targets as they become
+ * reachable.
+ *
+ * Building the total starters bitmap has the same cost (iterating over
+ * all starters adding the bitmaps) and this gives us the chance to
+ * shorcut the loop.
+ *
+ * This is based on the assuption that most of the starters will have
+ * the reachability bitmap precalculated. If many require a walk, the
+ * walk.reset() could start to take too much time.
+ */
+ List<RevCommit> remainingTargets = new ArrayList<>(targets);
+ for (RevCommit starter : starters) {
+ BitmapBuilder starterBitmap = calculator.getBitmap(starter,
+ NullProgressMonitor.INSTANCE);
+ remainingTargets.removeIf(starterBitmap::contains);
+ if (remainingTargets.isEmpty()) {
+ return Optional.empty();
+ }
+ }
+
+ return Optional.of(remainingTargets.get(0));
+ }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java
index 5154920393..5199a2927d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/DepthGenerator.java
@@ -108,12 +108,25 @@ class DepthGenerator extends Generator {
// Begin by sucking out all of the source's commits, and
// adding them to the pending queue
+ FIFORevQueue unshallowCommits = new FIFORevQueue();
for (;;) {
RevCommit c = s.next();
if (c == null)
break;
- if (((DepthWalk.Commit) c).getDepth() == 0)
+ if (c.has(UNSHALLOW)) {
+ unshallowCommits.add(c);
+ } else if (((DepthWalk.Commit) c).getDepth() == 0) {
pending.add(c);
+ }
+ }
+ // Move unshallow commits to the front so that the REINTERESTING flag
+ // carry over code is executed first.
+ for (;;) {
+ RevCommit c = unshallowCommits.next();
+ if (c == null) {
+ break;
+ }
+ pending.unpop(c);
}
// Mark DEEPEN_NOT on all deepen-not commits and their ancestors.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java
index d6fed66702..84b6d2e481 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterLine.java
@@ -95,7 +95,7 @@ public final class FooterLine {
for (int kPtr = 0; kPtr < len;) {
byte b = buffer[bPtr++];
if ('A' <= b && b <= 'Z')
- b += 'a' - 'A';
+ b += (byte) ('a' - 'A');
if (b != kRaw[kPtr++])
return false;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java
index fd578da333..b6c5810b32 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java
@@ -43,6 +43,7 @@
package org.eclipse.jgit.revwalk;
+import static java.util.Objects.requireNonNull;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
@@ -97,6 +98,55 @@ public class ObjectWalk extends RevWalk {
*/
private static final int IN_PENDING = RevWalk.REWRITE;
+ /**
+ * When walking over a tree and blob graph, objects are usually marked as
+ * seen as they are visited and this "seen" status is checked upon the next
+ * visit. If they are already "seen" then they are not processed (returned
+ * by {@link ObjectWalk#nextObject()}) again. However, this behavior can be
+ * overridden by supplying a different implementation of this class.
+ *
+ * @since 5.4
+ */
+ public interface VisitationPolicy {
+ /**
+ * Whenever the rev or object walk reaches a Git object, if that object
+ * already exists as a RevObject, this method is called to determine if
+ * that object should be visited.
+ *
+ * @param o
+ * the object to check if it should be visited
+ * @return true if the object should be visited
+ */
+ boolean shouldVisit(RevObject o);
+
+ /**
+ * Called when an object is visited.
+ *
+ * @param o
+ * the object that was visited
+ */
+ void visited(RevObject o);
+ }
+
+ /**
+ * The default visitation policy: causes all objects to be visited exactly
+ * once.
+ *
+ * @since 5.4
+ */
+ public static final VisitationPolicy SIMPLE_VISITATION_POLICY =
+ new VisitationPolicy() {
+ @Override
+ public boolean shouldVisit(RevObject o) {
+ return (o.flags & SEEN) == 0;
+ }
+
+ @Override
+ public void visited(RevObject o) {
+ o.flags |= SEEN;
+ }
+ };
+
private List<RevObject> rootObjects;
private BlockObjQueue pendingObjects;
@@ -113,6 +163,8 @@ public class ObjectWalk extends RevWalk {
private boolean boundary;
+ private VisitationPolicy visitationPolicy = SIMPLE_VISITATION_POLICY;
+
/**
* Create a new revision and object walker for a given repository.
*
@@ -299,6 +351,18 @@ public class ObjectWalk extends RevWalk {
objectFilter = newFilter != null ? newFilter : ObjectFilter.ALL;
}
+ /**
+ * Sets the visitation policy to use during this walk.
+ *
+ * @param policy
+ * the {@code VisitationPolicy} to use
+ * @since 5.4
+ */
+ public void setVisitationPolicy(VisitationPolicy policy) {
+ assertNotStarted();
+ visitationPolicy = requireNonNull(policy);
+ }
+
/** {@inheritDoc} */
@Override
public RevCommit next() throws MissingObjectException,
@@ -326,6 +390,17 @@ public class ObjectWalk extends RevWalk {
}
/**
+ * Skips the current tree such that {@link #nextObject()} does not return
+ * any objects inside it. This should be called right after
+ * {@link #nextObject()} returns the tree.
+ *
+ * @since 5.4
+ */
+ public void skipTree() {
+ currVisit.ptr = currVisit.buf.length;
+ }
+
+ /**
* Pop the next most recent object.
*
* @return next most recent object; null if traversal is over.
@@ -357,24 +432,23 @@ public class ObjectWalk extends RevWalk {
}
RevObject obj = objects.get(idBuffer);
- if (obj != null && (obj.flags & SEEN) != 0)
+ if (obj != null && !visitationPolicy.shouldVisit(obj))
continue;
int mode = parseMode(buf, startPtr, ptr, tv);
- int flags;
switch (mode >>> TYPE_SHIFT) {
case TYPE_FILE:
case TYPE_SYMLINK:
if (obj == null) {
obj = new RevBlob(idBuffer);
- obj.flags = SEEN;
+ visitationPolicy.visited(obj);
objects.add(obj);
return obj;
}
if (!(obj instanceof RevBlob))
throw new IncorrectObjectTypeException(obj, OBJ_BLOB);
- obj.flags = flags = obj.flags | SEEN;
- if ((flags & UNINTERESTING) == 0)
+ visitationPolicy.visited(obj);
+ if ((obj.flags & UNINTERESTING) == 0)
return obj;
if (boundary)
return obj;
@@ -383,17 +457,17 @@ public class ObjectWalk extends RevWalk {
case TYPE_TREE:
if (obj == null) {
obj = new RevTree(idBuffer);
- obj.flags = SEEN;
+ visitationPolicy.visited(obj);
objects.add(obj);
- return enterTree(obj);
+ return pushTree(obj);
}
if (!(obj instanceof RevTree))
throw new IncorrectObjectTypeException(obj, OBJ_TREE);
- obj.flags = flags = obj.flags | SEEN;
- if ((flags & UNINTERESTING) == 0)
- return enterTree(obj);
+ visitationPolicy.visited(obj);
+ if ((obj.flags & UNINTERESTING) == 0)
+ return pushTree(obj);
if (boundary)
- return enterTree(obj);
+ return pushTree(obj);
continue;
case TYPE_GITLINK:
@@ -419,30 +493,23 @@ public class ObjectWalk extends RevWalk {
if (o == null) {
return null;
}
- int flags = o.flags;
- if ((flags & SEEN) != 0)
+ if (!visitationPolicy.shouldVisit(o)) {
continue;
- flags |= SEEN;
- o.flags = flags;
- if ((flags & UNINTERESTING) == 0 | boundary) {
+ }
+ visitationPolicy.visited(o);
+ if ((o.flags & UNINTERESTING) == 0 || boundary) {
if (o instanceof RevTree) {
- tv = newTreeVisit(o);
- tv.parent = null;
- currVisit = tv;
+ // The previous while loop should have exhausted the stack
+ // of trees.
+ assert currVisit == null;
+
+ pushTree(o);
}
return o;
}
}
}
- private RevObject enterTree(RevObject obj) throws MissingObjectException,
- IncorrectObjectTypeException, IOException {
- TreeVisit tv = newTreeVisit(obj);
- tv.parent = currVisit;
- currVisit = tv;
- return obj;
- }
-
private static int findObjectId(byte[] buf, int ptr) {
// Skip over the mode and name until the NUL before the ObjectId
// can be located. Skip the NUL as the function returns.
@@ -582,6 +649,17 @@ public class ObjectWalk extends RevWalk {
}
/**
+ * @return the current traversal depth from the root tree object
+ * @since 5.4
+ */
+ public int getTreeDepth() {
+ if (currVisit == null) {
+ return 0;
+ }
+ return currVisit.depth;
+ }
+
+ /**
* Get the current object's path hash code.
* <p>
* This method computes a hash code on the fly for this path, the hash is
@@ -768,7 +846,7 @@ public class ObjectWalk extends RevWalk {
}
}
- private TreeVisit newTreeVisit(RevObject obj) throws LargeObjectException,
+ private RevObject pushTree(RevObject obj) throws LargeObjectException,
MissingObjectException, IncorrectObjectTypeException, IOException {
TreeVisit tv = freeVisit;
if (tv != null) {
@@ -782,7 +860,15 @@ public class ObjectWalk extends RevWalk {
}
tv.obj = obj;
tv.buf = reader.open(obj, OBJ_TREE).getCachedBytes();
- return tv;
+ tv.parent = currVisit;
+ currVisit = tv;
+ if (tv.parent == null) {
+ tv.depth = 1;
+ } else {
+ tv.depth = tv.parent.depth + 1;
+ }
+
+ return obj;
}
private void releaseTreeVisit(TreeVisit tv) {
@@ -812,5 +898,8 @@ public class ObjectWalk extends RevWalk {
/** Number of bytes in the path leading up to this tree. */
int pathLen;
+
+ /** Number of levels deep from the root tree. 0 for root tree. */
+ int depth;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PedestrianReachabilityChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PedestrianReachabilityChecker.java
new file mode 100644
index 0000000000..bba3c5cff3
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PedestrianReachabilityChecker.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.revwalk;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Optional;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+
+/**
+ * Checks the reachability walking the graph from the starters towards the
+ * target.
+ */
+class PedestrianReachabilityChecker implements ReachabilityChecker {
+
+ private final boolean topoSort;
+
+ private final RevWalk walk;
+
+ /**
+ * New instance of the reachability checker using a existing walk.
+ *
+ * @param topoSort
+ * walk commits in topological order
+ * @param walk
+ * RevWalk instance to reuse. Caller retains ownership.
+ */
+ public PedestrianReachabilityChecker(boolean topoSort,
+ RevWalk walk) {
+ this.topoSort = topoSort;
+ this.walk = walk;
+ }
+
+ @Override
+ public Optional<RevCommit> areAllReachable(Collection<RevCommit> targets,
+ Collection<RevCommit> starters)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ walk.reset();
+ if (topoSort) {
+ walk.sort(RevSort.TOPO);
+ }
+
+ for (RevCommit target: targets) {
+ walk.markStart(target);
+ }
+
+ for (RevCommit starter : starters) {
+ walk.markUninteresting(starter);
+ }
+
+ return Optional.ofNullable(walk.next());
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java
new file mode 100644
index 0000000000..2ed06d1769
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ReachabilityChecker.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.revwalk;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Optional;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+
+/**
+ * Check if a commit is reachable from a collection of starting commits.
+ * <p>
+ * Note that this checks the reachability of commits (and tags). Trees, blobs or
+ * any other object will cause IncorrectObjectTypeException exceptions.
+ *
+ * @since 5.4
+ */
+public interface ReachabilityChecker {
+
+ /**
+ * Check if all targets are reachable from the {@code starter} commits.
+ * <p>
+ * Caller should parse the objectIds (preferably with
+ * {@code walk.parseCommit()} and handle missing/incorrect type objects
+ * before calling this method.
+ *
+ * @param targets
+ * commits to reach.
+ * @param starters
+ * known starting points.
+ * @return An unreachable target if at least one of the targets is
+ * unreachable. An empty optional if all targets are reachable from
+ * the starters.
+ *
+ * @throws MissingObjectException
+ * if any of the incoming objects doesn't exist in the
+ * repository.
+ * @throws IncorrectObjectTypeException
+ * if any of the incoming objects is not a commit or a tag.
+ * @throws IOException
+ * if any of the underlying indexes or readers can not be
+ * opened.
+ */
+ Optional<RevCommit> areAllReachable(Collection<RevCommit> targets,
+ Collection<RevCommit> starters)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException;
+}
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 0a43e8fb1a..f50d189ce5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java
@@ -72,6 +72,7 @@ import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.eclipse.jgit.util.References;
/**
* Walks a commit graph and produces the matching commits in order.
@@ -250,6 +251,23 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable {
}
/**
+ * Get a reachability checker for commits over this revwalk.
+ *
+ * @return the most efficient reachability checker for this repository.
+ * @throws IOException
+ * if it cannot open any of the underlying indices.
+ *
+ * @since 5.4
+ */
+ public ReachabilityChecker createReachabilityChecker() throws IOException {
+ if (reader.getBitmapIndex() != null) {
+ return new BitmappedReachabilityChecker(this);
+ }
+
+ return new PedestrianReachabilityChecker(true, this);
+ }
+
+ /**
* {@inheritDoc}
* <p>
* Release any resources used by this walker's reader.
@@ -416,9 +434,11 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable {
markStart(tip);
markStart(base);
RevCommit mergeBase;
- while ((mergeBase = next()) != null)
- if (mergeBase == base)
+ while ((mergeBase = next()) != null) {
+ if (References.isSameObject(mergeBase, base)) {
return true;
+ }
+ }
return false;
} finally {
filter = oldRF;
@@ -506,7 +526,7 @@ public class RevWalk implements Iterable<RevCommit>, AutoCloseable {
if (sorting.size() > 1)
sorting.remove(RevSort.NONE);
- else if (sorting.size() == 0)
+ else if (sorting.isEmpty())
sorting.add(RevSort.NONE);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java
index f1252a4c4b..2b721b8877 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java
@@ -50,6 +50,9 @@ import java.util.List;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
/**
@@ -130,7 +133,7 @@ public final class RevWalkUtils {
/**
* Find the list of branches a given commit is reachable from when following
- * parent.s
+ * parents.
* <p>
* Note that this method calls
* {@link org.eclipse.jgit.revwalk.RevWalk#reset()} at the beginning.
@@ -153,15 +156,51 @@ public final class RevWalkUtils {
RevWalk revWalk, Collection<Ref> refs)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
+ return findBranchesReachableFrom(commit, revWalk, refs,
+ NullProgressMonitor.INSTANCE);
+ }
+
+ /**
+ * Find the list of branches a given commit is reachable from when following
+ * parents.
+ * <p>
+ * Note that this method calls
+ * {@link org.eclipse.jgit.revwalk.RevWalk#reset()} at the beginning.
+ * <p>
+ * In order to improve performance this method assumes clock skew among
+ * committers is never larger than 24 hours.
+ *
+ * @param commit
+ * the commit we are looking at
+ * @param revWalk
+ * The RevWalk to be used.
+ * @param refs
+ * the set of branches we want to see reachability from
+ * @param monitor
+ * the callback for progress and cancellation
+ * @return the list of branches a given commit is reachable from
+ * @throws org.eclipse.jgit.errors.MissingObjectException
+ * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException
+ * @throws java.io.IOException
+ * @since 5.4
+ */
+ public static List<Ref> findBranchesReachableFrom(RevCommit commit,
+ RevWalk revWalk, Collection<Ref> refs, ProgressMonitor monitor)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
// Make sure commit is from the same RevWalk
commit = revWalk.parseCommit(commit.getId());
revWalk.reset();
List<Ref> result = new ArrayList<>();
-
+ monitor.beginTask(JGitText.get().searchForReachableBranches,
+ refs.size());
final int SKEW = 24*3600; // one day clock skew
for (Ref ref : refs) {
+ if (monitor.isCancelled())
+ return result;
+ monitor.update(1);
RevObject maybehead = revWalk.parseAny(ref.getObjectId());
if (!(maybehead instanceof RevCommit))
continue;
@@ -176,6 +215,7 @@ public final class RevWalkUtils {
if (revWalk.isMergedInto(commit, headCommit))
result.add(ref);
}
+ monitor.endTask();
return result;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/RevFlagFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/RevFlagFilter.java
index c67c44b216..c3dc3dea66 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/RevFlagFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/filter/RevFlagFilter.java
@@ -44,6 +44,7 @@
package org.eclipse.jgit.revwalk.filter;
import java.io.IOException;
+import java.util.Arrays;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
@@ -78,8 +79,7 @@ public abstract class RevFlagFilter extends RevFilter {
*/
public static RevFilter hasAll(RevFlag... a) {
final RevFlagSet set = new RevFlagSet();
- for (RevFlag flag : a)
- set.add(flag);
+ set.addAll(Arrays.asList(a));
return new HasAll(set);
}
@@ -103,8 +103,7 @@ public abstract class RevFlagFilter extends RevFilter {
*/
public static RevFilter hasAny(RevFlag... a) {
final RevFlagSet set = new RevFlagSet();
- for (RevFlag flag : a)
- set.add(flag);
+ set.addAll(Arrays.asList(a));
return new HasAny(set);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
index bdbd7c9072..5bb8153a58 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java
@@ -148,7 +148,8 @@ public class FileBasedConfig extends StoredConfig {
*/
@Override
public void load() throws IOException, ConfigInvalidException {
- final int maxStaleRetries = 5;
+ final int maxRetries = 5;
+ int retryDelayMillis = 20;
int retries = 0;
while (true) {
final FileSnapshot oldSnapshot = snapshot;
@@ -179,6 +180,22 @@ public class FileBasedConfig extends StoredConfig {
}
return;
} catch (FileNotFoundException noFile) {
+ // might be locked by another process (see exception Javadoc)
+ if (retries < maxRetries && configFile.exists()) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(MessageFormat.format(
+ JGitText.get().configHandleMayBeLocked,
+ Integer.valueOf(retries)), noFile);
+ }
+ try {
+ Thread.sleep(retryDelayMillis);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ retries++;
+ retryDelayMillis *= 2; // max wait 1260 ms
+ continue;
+ }
if (configFile.exists()) {
throw noFile;
}
@@ -187,7 +204,7 @@ public class FileBasedConfig extends StoredConfig {
return;
} catch (IOException e) {
if (FileUtils.isStaleFileHandle(e)
- && retries < maxStaleRetries) {
+ && retries < maxRetries) {
if (LOG.isDebugEnabled()) {
LOG.debug(MessageFormat.format(
JGitText.get().configHandleIsStale,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java
index 68878e5a61..e6e3d4fb12 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java
@@ -266,6 +266,10 @@ public class PackStatistics {
/** Time in ms spent writing the pack. */
public long timeWriting;
+ /** Number of trees traversed in the walk when writing the pack.
+ * @since 5.4*/
+ public long treesTraversed;
+
/**
* Statistics about each object type in the pack (commits, tags, trees
* and blobs.)
@@ -586,6 +590,14 @@ public class PackStatistics {
}
/**
+ * @return number of trees traversed in the walk when writing the pack.
+ * @since 5.4
+ */
+ public long getTreesTraversed() {
+ return statistics.treesTraversed;
+ }
+
+ /**
* Get total time spent processing this pack.
*
* @return total time spent processing this pack.
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 ce8995ad8f..e5559dea09 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
@@ -144,7 +144,8 @@ public class SubmoduleWalk implements AutoCloseable {
* path and .gitmodules at the root.
* @param path
* a {@link java.lang.String} object.
- * @return generator at given path, null if no submodule at given path
+ * @return generator at given path. The caller is responsible for calling
+ * {@link #close()}. Null if no submodule at given path.
* @throws java.io.IOException
*/
public static SubmoduleWalk forPath(Repository repository,
@@ -177,7 +178,8 @@ public class SubmoduleWalk implements AutoCloseable {
* path and .gitmodules at the root.
* @param path
* a {@link java.lang.String} object.
- * @return generator at given path, null if no submodule at given path
+ * @return generator at given path. The caller is responsible for calling
+ * {@link #close()}. Null if no submodule at given path.
* @throws java.io.IOException
*/
public static SubmoduleWalk forPath(Repository repository,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
index fcf78ac7b9..e8724b72db 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
@@ -53,6 +53,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;
@@ -182,10 +183,7 @@ abstract class BasePackConnection extends BaseConnection {
} catch (TransportException err) {
close();
throw err;
- } catch (IOException err) {
- close();
- throw new TransportException(err.getMessage(), err);
- } catch (RuntimeException err) {
+ } catch (IOException | RuntimeException err) {
close();
throw new TransportException(err.getMessage(), err);
}
@@ -203,7 +201,7 @@ abstract class BasePackConnection extends BaseConnection {
throw noRepository();
throw eof;
}
- if (line == PacketLineIn.END)
+ if (PacketLineIn.isEnd(line))
break;
if (line.startsWith("ERR ")) { //$NON-NLS-1$
@@ -217,8 +215,8 @@ abstract class BasePackConnection extends BaseConnection {
if (nul >= 0) {
// The first line (if any) may contain "hidden"
// capability values after a NUL byte.
- for (String c : line.substring(nul + 1).split(" ")) //$NON-NLS-1$
- remoteCapablities.add(c);
+ remoteCapablities.addAll(
+ Arrays.asList(line.substring(nul + 1).split(" "))); //$NON-NLS-1$
line = line.substring(0, nul);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
index ed7465c82a..57d6bc2466 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java
@@ -245,8 +245,12 @@ public abstract class BasePackFetchConnection extends BasePackConnection
private PacketLineOut pckState;
- /** If not -1, the maximum blob size to be sent to the server. */
- private final long filterBlobLimit;
+ /**
+ * Either FilterSpec.NO_FILTER for a filter that doesn't filter
+ * anything, or a filter that indicates what and what not to send to the
+ * server.
+ */
+ private final FilterSpec filterSpec;
/**
* Create a new connection to fetch using the native git transport.
@@ -268,10 +272,11 @@ public abstract class BasePackFetchConnection extends BasePackConnection
includeTags = transport.getTagOpt() != TagOpt.NO_TAGS;
thinPack = transport.isFetchThin();
- filterBlobLimit = transport.getFilterBlobLimit();
+ filterSpec = transport.getFilterSpec();
if (local != null) {
walk = new RevWalk(local);
+ walk.setRetainBody(false);
reachableCommits = new RevCommitList<>();
REACHABLE = walk.newFlag("REACHABLE"); //$NON-NLS-1$
COMMON = walk.newFlag("COMMON"); //$NON-NLS-1$
@@ -395,10 +400,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
} catch (CancelledException ce) {
close();
return; // Caller should test (or just know) this themselves.
- } catch (IOException err) {
- close();
- throw new TransportException(err.getMessage(), err);
- } catch (RuntimeException err) {
+ } catch (IOException | RuntimeException err) {
close();
throw new TransportException(err.getMessage(), err);
}
@@ -520,10 +522,8 @@ public abstract class BasePackFetchConnection extends BasePackConnection
if (first) {
return false;
}
- if (filterBlobLimit == 0) {
- p.writeString(OPTION_FILTER + " blob:none"); //$NON-NLS-1$
- } else if (filterBlobLimit > 0) {
- p.writeString(OPTION_FILTER + " blob:limit=" + filterBlobLimit); //$NON-NLS-1$
+ if (!filterSpec.isNoOp()) {
+ p.writeString(filterSpec.filterLine());
}
p.end();
outNeedsEnd = false;
@@ -565,7 +565,7 @@ public abstract class BasePackFetchConnection extends BasePackConnection
OPTION_MULTI_ACK_DETAILED));
}
- if (filterBlobLimit >= 0 && !wantCapability(line, OPTION_FILTER)) {
+ if (!filterSpec.isNoOp() && !wantCapability(line, OPTION_FILTER)) {
throw new PackProtocolException(uri,
JGitText.get().filterRequiresCapability);
}
@@ -670,14 +670,14 @@ public abstract class BasePackFetchConnection extends BasePackConnection
}
}
- if (noDone & receivedReady) {
+ if (noDone && receivedReady) {
break SEND_HAVES;
}
if (statelessRPC) {
state.writeTo(out, null);
}
- if (receivedContinue && havesSinceLastContinue > MAX_HAVES
+ if ((receivedContinue && havesSinceLastContinue > MAX_HAVES)
|| havesSent >= maxHaves) {
// Our history must be really different from the remote's.
// We just sent a whole slew of have lines, and it did not
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
index 847e901980..35ea35ecb8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
@@ -383,8 +383,7 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
JGitText.get().errorOccurredDuringUnpackingOnTheRemoteEnd, unpackStatus));
}
- String refLine;
- while ((refLine = pckIn.readString()) != PacketLineIn.END) {
+ for (String refLine : pckIn.readStrings()) {
boolean ok = false;
int refNameEnd = -1;
if (refLine.startsWith("ok ")) { //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
index 6f17620d91..e402de0158 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
@@ -314,6 +314,7 @@ public abstract class BaseReceivePack {
protected BaseReceivePack(Repository into) {
db = into;
walk = new RevWalk(db);
+ walk.setRetainBody(false);
TransferConfig tc = db.getConfig().get(TransferConfig.KEY);
objectChecker = tc.newReceiveObjectChecker();
@@ -1240,7 +1241,7 @@ public abstract class BaseReceivePack {
adv.advertiseCapability(CAPABILITY_PUSH_OPTIONS);
}
adv.advertiseCapability(OPTION_AGENT, UserAgent.get());
- adv.send(getAdvertisedOrDefaultRefs());
+ adv.send(getAdvertisedOrDefaultRefs().values());
for (ObjectId obj : advertisedHaves)
adv.advertiseHave(obj);
if (adv.isEmpty())
@@ -1281,7 +1282,7 @@ public abstract class BaseReceivePack {
return;
throw eof;
}
- if (line == PacketLineIn.END) {
+ if (PacketLineIn.isEnd(line)) {
break;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java
index 84a0972723..6cf75031cd 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleFetchConnection.java
@@ -112,10 +112,7 @@ class BundleFetchConnection extends BaseFetchConnection {
} catch (TransportException err) {
close();
throw err;
- } catch (IOException err) {
- close();
- throw new TransportException(transport.uri, err.getMessage(), err);
- } catch (RuntimeException err) {
+ } catch (IOException | RuntimeException err) {
close();
throw new TransportException(transport.uri, err.getMessage(), err);
}
@@ -205,10 +202,7 @@ class BundleFetchConnection extends BaseFetchConnection {
packLock = parser.parse(NullProgressMonitor.INSTANCE);
ins.flush();
}
- } catch (IOException err) {
- close();
- throw new TransportException(transport.uri, err.getMessage(), err);
- } catch (RuntimeException err) {
+ } catch (IOException | RuntimeException err) {
close();
throw new TransportException(transport.uri, err.getMessage(), err);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleWriter.java
index 56aaede80d..d1db51eca6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleWriter.java
@@ -227,10 +227,11 @@ public class BundleWriter {
exc.add(r.getId());
packWriter.setIndexDisabled(true);
packWriter.setDeltaBaseAsOffset(true);
- packWriter.setThin(exc.size() > 0);
+ packWriter.setThin(!exc.isEmpty());
packWriter.setReuseValidatingObjects(false);
- if (exc.size() == 0)
+ if (exc.isEmpty()) {
packWriter.setTagTargets(tagTargets);
+ }
packWriter.preparePack(monitor, inc, exc);
final Writer w = new OutputStreamWriter(os, UTF_8);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java
index 7289ce7b6c..2b27df2b84 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java
@@ -115,36 +115,26 @@ public class Daemon {
repositoryResolver = (RepositoryResolver<DaemonClient>) RepositoryResolver.NONE;
- uploadPackFactory = new UploadPackFactory<DaemonClient>() {
- @Override
- public UploadPack create(DaemonClient req, Repository db)
- throws ServiceNotEnabledException,
- ServiceNotAuthorizedException {
- UploadPack up = new UploadPack(db);
- up.setTimeout(getTimeout());
- up.setPackConfig(getPackConfig());
- return up;
- }
+ uploadPackFactory = (DaemonClient req, Repository db) -> {
+ UploadPack up = new UploadPack(db);
+ up.setTimeout(getTimeout());
+ up.setPackConfig(getPackConfig());
+ return up;
};
- receivePackFactory = new ReceivePackFactory<DaemonClient>() {
- @Override
- public ReceivePack create(DaemonClient req, Repository db)
- throws ServiceNotEnabledException,
- ServiceNotAuthorizedException {
- ReceivePack rp = new ReceivePack(db);
-
- InetAddress peer = req.getRemoteAddress();
- String host = peer.getCanonicalHostName();
- if (host == null)
- host = peer.getHostAddress();
- String name = "anonymous"; //$NON-NLS-1$
- String email = name + "@" + host; //$NON-NLS-1$
- rp.setRefLogIdent(new PersonIdent(name, email));
- rp.setTimeout(getTimeout());
-
- return rp;
- }
+ receivePackFactory = (DaemonClient req, Repository db) -> {
+ ReceivePack rp = new ReceivePack(db);
+
+ InetAddress peer = req.getRemoteAddress();
+ String host = peer.getCanonicalHostName();
+ if (host == null)
+ host = peer.getHostAddress();
+ String name = "anonymous"; //$NON-NLS-1$
+ String email = name + "@" + host; //$NON-NLS-1$
+ rp.setRefLogIdent(new PersonIdent(name, email));
+ rp.setTimeout(getTimeout());
+
+ return rp;
};
services = new DaemonService[] {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
index 681ae125cb..e584440b3f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchProcess.java
@@ -200,6 +200,7 @@ class FetchProcess {
.setAllowNonFastForwards(true)
.setRefLogMessage("fetch", true); //$NON-NLS-1$
try (RevWalk walk = new RevWalk(transport.local)) {
+ walk.setRetainBody(false);
if (monitor instanceof BatchingProgressMonitor) {
((BatchingProgressMonitor) monitor).setDelayStart(
250, TimeUnit.MILLISECONDS);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java
index 40ba3a3ad2..4dd7d6ed8b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchRequest.java
@@ -62,7 +62,7 @@ abstract class FetchRequest {
final Set<ObjectId> clientShallowCommits;
- final long filterBlobLimit;
+ final FilterSpec filterSpec;
final Set<String> clientCapabilities;
@@ -82,8 +82,8 @@ abstract class FetchRequest {
* how deep to go in the tree
* @param clientShallowCommits
* commits the client has without history
- * @param filterBlobLimit
- * to exclude blobs on certain conditions
+ * @param filterSpec
+ * the filter spec
* @param clientCapabilities
* capabilities sent in the request
* @param deepenNotRefs
@@ -96,13 +96,14 @@ abstract class FetchRequest {
* agent as reported by the client in the request body
*/
FetchRequest(@NonNull Set<ObjectId> wantIds, int depth,
- @NonNull Set<ObjectId> clientShallowCommits, long filterBlobLimit,
+ @NonNull Set<ObjectId> clientShallowCommits,
+ @NonNull FilterSpec filterSpec,
@NonNull Set<String> clientCapabilities, int deepenSince,
@NonNull List<String> deepenNotRefs, @Nullable String agent) {
this.wantIds = requireNonNull(wantIds);
this.depth = depth;
this.clientShallowCommits = requireNonNull(clientShallowCommits);
- this.filterBlobLimit = filterBlobLimit;
+ this.filterSpec = requireNonNull(filterSpec);
this.clientCapabilities = requireNonNull(clientCapabilities);
this.deepenSince = deepenSince;
this.deepenNotRefs = requireNonNull(deepenNotRefs);
@@ -137,10 +138,11 @@ abstract class FetchRequest {
}
/**
- * @return the blob limit set in a "filter" line (-1 if not set)
+ * @return the filter spec given in a "filter" line
*/
- long getFilterBlobLimit() {
- return filterBlobLimit;
+ @NonNull
+ FilterSpec getFilterSpec() {
+ return filterSpec;
}
/**
@@ -191,4 +193,4 @@ abstract class FetchRequest {
String getAgent() {
return agent;
}
-} \ No newline at end of file
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java
index 05f4a8155f..231ab9f2cc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV0Request.java
@@ -42,6 +42,8 @@
*/
package org.eclipse.jgit.transport;
+import static java.util.Objects.requireNonNull;
+
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -57,10 +59,11 @@ import org.eclipse.jgit.lib.ObjectId;
final class FetchV0Request extends FetchRequest {
FetchV0Request(@NonNull Set<ObjectId> wantIds, int depth,
- @NonNull Set<ObjectId> clientShallowCommits, long filterBlobLimit,
+ @NonNull Set<ObjectId> clientShallowCommits,
+ @NonNull FilterSpec filterSpec,
@NonNull Set<String> clientCapabilities, @Nullable String agent) {
- super(wantIds, depth, clientShallowCommits, filterBlobLimit,
- clientCapabilities, 0, Collections.emptyList(), agent);
+ super(wantIds, depth, clientShallowCommits, filterSpec,
+ clientCapabilities, 0, Collections.emptyList(), agent);
}
static final class Builder {
@@ -71,7 +74,7 @@ final class FetchV0Request extends FetchRequest {
final Set<ObjectId> clientShallowCommits = new HashSet<>();
- long filterBlobLimit = -1;
+ FilterSpec filterSpec = FilterSpec.NO_FILTER;
final Set<String> clientCaps = new HashSet<>();
@@ -129,18 +132,18 @@ final class FetchV0Request extends FetchRequest {
}
/**
- * @param filterBlobLim
- * blob limit set in a "filter" line
+ * @param filter
+ * the filter set in a filter line
* @return this builder
*/
- Builder setFilterBlobLimit(long filterBlobLim) {
- filterBlobLimit = filterBlobLim;
+ Builder setFilterSpec(@NonNull FilterSpec filter) {
+ filterSpec = requireNonNull(filter);
return this;
}
FetchV0Request build() {
return new FetchV0Request(wantIds, depth, clientShallowCommits,
- filterBlobLimit, clientCaps, agent);
+ filterSpec, clientCaps, agent);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java
index ac6361cdeb..6c24269095 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FetchV2Request.java
@@ -77,11 +77,12 @@ public final class FetchV2Request extends FetchRequest {
@NonNull Set<ObjectId> wantIds,
@NonNull Set<ObjectId> clientShallowCommits, int deepenSince,
@NonNull List<String> deepenNotRefs, int depth,
- long filterBlobLimit,
+ @NonNull FilterSpec filterSpec,
boolean doneReceived, @NonNull Set<String> clientCapabilities,
@Nullable String agent, @NonNull List<String> serverOptions) {
- super(wantIds, depth, clientShallowCommits, filterBlobLimit,
- clientCapabilities, deepenSince, deepenNotRefs, agent);
+ super(wantIds, depth, clientShallowCommits, filterSpec,
+ clientCapabilities, deepenSince,
+ deepenNotRefs, agent);
this.peerHas = requireNonNull(peerHas);
this.wantedRefs = requireNonNull(wantedRefs);
this.doneReceived = doneReceived;
@@ -98,9 +99,11 @@ public final class FetchV2Request extends FetchRequest {
/**
* @return list of references received in "want-ref" lines
+ *
+ * @since 5.4
*/
@NonNull
- List<String> getWantedRefs() {
+ public List<String> getWantedRefs() {
return wantedRefs;
}
@@ -147,7 +150,7 @@ public final class FetchV2Request extends FetchRequest {
int deepenSince;
- long filterBlobLimit = -1;
+ FilterSpec filterSpec = FilterSpec.NO_FILTER;
boolean doneReceived;
@@ -266,12 +269,12 @@ public final class FetchV2Request extends FetchRequest {
}
/**
- * @param filterBlobLim
- * set in a "filter" line
+ * @param filter
+ * spec set in a "filter" line
* @return this builder
*/
- Builder setFilterBlobLimit(long filterBlobLim) {
- filterBlobLimit = filterBlobLim;
+ Builder setFilterSpec(@NonNull FilterSpec filter) {
+ filterSpec = requireNonNull(filter);
return this;
}
@@ -320,7 +323,7 @@ public final class FetchV2Request extends FetchRequest {
FetchV2Request build() {
return new FetchV2Request(peerHas, wantedRefs, wantIds,
clientShallowCommits, deepenSince, deepenNotRefs,
- depth, filterBlobLimit, doneReceived, clientCapabilities,
+ depth, filterSpec, doneReceived, clientCapabilities,
agent, Collections.unmodifiableList(serverOptions));
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java
new file mode 100644
index 0000000000..a663c9b470
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/FilterSpec.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2019, Google LLC.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.transport;
+
+import java.text.MessageFormat;
+
+import org.eclipse.jgit.annotations.Nullable;
+import org.eclipse.jgit.errors.PackProtocolException;
+import org.eclipse.jgit.internal.JGitText;
+
+/**
+ * Represents either a filter specified in a protocol "filter" line, or a
+ * placeholder to indicate no filtering.
+ *
+ * @since 5.4
+ */
+public final class FilterSpec {
+
+ private final long blobLimit;
+
+ private final long treeDepthLimit;
+
+ private FilterSpec(long blobLimit, long treeDepthLimit) {
+ this.blobLimit = blobLimit;
+ this.treeDepthLimit = treeDepthLimit;
+ }
+
+ /**
+ * Process the content of "filter" line from the protocol. It has a shape
+ * like:
+ *
+ * <ul>
+ * <li>"blob:none"
+ * <li>"blob:limit=N", with N &gt;= 0
+ * <li>"tree:DEPTH", with DEPTH &gt;= 0
+ * </ul>
+ *
+ * @param filterLine
+ * the content of the "filter" line in the protocol
+ * @return a FilterSpec representing the given filter
+ * @throws PackProtocolException
+ * invalid filter because due to unrecognized format or
+ * negative/non-numeric filter.
+ */
+ public static FilterSpec fromFilterLine(String filterLine)
+ throws PackProtocolException {
+ if (filterLine.equals("blob:none")) { //$NON-NLS-1$
+ return FilterSpec.withBlobLimit(0);
+ } else if (filterLine.startsWith("blob:limit=")) { //$NON-NLS-1$
+ long blobLimit = -1;
+ try {
+ blobLimit = Long
+ .parseLong(filterLine.substring("blob:limit=".length())); //$NON-NLS-1$
+ } catch (NumberFormatException e) {
+ // Do not change blobLimit so that we throw a
+ // PackProtocolException later.
+ }
+ if (blobLimit >= 0) {
+ return FilterSpec.withBlobLimit(blobLimit);
+ }
+ } else if (filterLine.startsWith("tree:")) { //$NON-NLS-1$
+ long treeDepthLimit = -1;
+ try {
+ treeDepthLimit = Long
+ .parseLong(filterLine.substring("tree:".length())); //$NON-NLS-1$
+ } catch (NumberFormatException e) {
+ // Do not change blobLimit so that we throw a
+ // PackProtocolException later.
+ }
+ if (treeDepthLimit >= 0) {
+ return FilterSpec.withTreeDepthLimit(treeDepthLimit);
+ }
+ }
+
+ // Did not match any known filter format.
+ throw new PackProtocolException(
+ MessageFormat.format(JGitText.get().invalidFilter, filterLine));
+ }
+
+ /**
+ * @param blobLimit
+ * the blob limit in a "blob:[limit]" or "blob:none" filter line
+ * @return a filter spec which filters blobs above a certain size
+ */
+ static FilterSpec withBlobLimit(long blobLimit) {
+ if (blobLimit < 0) {
+ throw new IllegalArgumentException(
+ "blobLimit cannot be negative: " + blobLimit); //$NON-NLS-1$
+ }
+ return new FilterSpec(blobLimit, -1);
+ }
+
+ /**
+ * @param treeDepthLimit
+ * the tree depth limit in a "tree:[depth]" filter line
+ * @return a filter spec which filters blobs and trees beyond a certain tree
+ * depth
+ */
+ static FilterSpec withTreeDepthLimit(long treeDepthLimit) {
+ if (treeDepthLimit < 0) {
+ throw new IllegalArgumentException(
+ "treeDepthLimit cannot be negative: " + treeDepthLimit); //$NON-NLS-1$
+ }
+ return new FilterSpec(-1, treeDepthLimit);
+ }
+
+ /**
+ * A placeholder that indicates no filtering.
+ */
+ public static final FilterSpec NO_FILTER = new FilterSpec(-1, -1);
+
+ /**
+ * @return -1 if this filter does not filter blobs based on size, or a
+ * non-negative integer representing the max size of blobs to allow
+ */
+ public long getBlobLimit() {
+ return blobLimit;
+ }
+
+ /**
+ * @return -1 if this filter does not filter blobs and trees based on depth,
+ * or a non-negative integer representing the max tree depth of
+ * blobs and trees to fetch
+ */
+ public long getTreeDepthLimit() {
+ return treeDepthLimit;
+ }
+
+ /**
+ * @return true if this filter doesn't filter out anything
+ */
+ public boolean isNoOp() {
+ return blobLimit == -1 && treeDepthLimit == -1;
+ }
+
+ /**
+ * @return the filter line which describes this spec, e.g. "filter blob:limit=42"
+ */
+ @Nullable
+ public String filterLine() {
+ if (blobLimit == 0) {
+ return GitProtocolConstants.OPTION_FILTER + " blob:none"; //$NON-NLS-1$
+ }
+
+ if (blobLimit > 0) {
+ return GitProtocolConstants.OPTION_FILTER + " blob:limit=" + blobLimit; //$NON-NLS-1$
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java
index 6c26b7026a..01f6fec7e4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HMACSHA1NonceGenerator.java
@@ -45,14 +45,12 @@ package org.eclipse.jgit.transport;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;
-import java.io.File;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
-import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PushCertificate.NonceStatus;
@@ -78,9 +76,7 @@ public class HMACSHA1NonceGenerator implements NonceGenerator {
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1"); //$NON-NLS-1$
mac = Mac.getInstance("HmacSHA1"); //$NON-NLS-1$
mac.init(signingKey);
- } catch (InvalidKeyException e) {
- throw new IllegalStateException(e);
- } catch (NoSuchAlgorithmException e) {
+ } catch (InvalidKeyException | NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}
@@ -89,19 +85,7 @@ public class HMACSHA1NonceGenerator implements NonceGenerator {
@Override
public synchronized String createNonce(Repository repo, long timestamp)
throws IllegalStateException {
- String path;
- if (repo instanceof DfsRepository) {
- path = ((DfsRepository) repo).getDescription().getRepositoryName();
- } else {
- File directory = repo.getDirectory();
- if (directory != null) {
- path = directory.getPath();
- } else {
- throw new IllegalStateException();
- }
- }
-
- String input = path + ":" + String.valueOf(timestamp); //$NON-NLS-1$
+ String input = repo.getIdentifier() + ":" + String.valueOf(timestamp); //$NON-NLS-1$
byte[] rawHmac = mac.doFinal(input.getBytes(UTF_8));
return Long.toString(timestamp) + "-" + toHex(rawHmac); //$NON-NLS-1$
}
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 ce9e1b3def..be7111d904 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
@@ -88,6 +88,30 @@ public class HttpConfig {
/** git config key for the "sslVerify" setting. */
public static final String SSL_VERIFY_KEY = "sslVerify"; //$NON-NLS-1$
+ /**
+ * git config key for the "cookieFile" setting.
+ *
+ * @since 5.4
+ */
+ public static final String COOKIE_FILE_KEY = "cookieFile"; //$NON-NLS-1$
+
+ /**
+ * git config key for the "saveCookies" setting.
+ *
+ * @since 5.4
+ */
+ public static final String SAVE_COOKIES_KEY = "saveCookies"; //$NON-NLS-1$
+
+ /**
+ * Custom JGit config key which holds the maximum number of cookie files to
+ * keep in the cache.
+ *
+ * @since 5.4
+ */
+ public static final String COOKIE_FILE_CACHE_LIMIT_KEY = "cookieFileCacheLimit"; //$NON-NLS-1$
+
+ private static final int DEFAULT_COOKIE_FILE_CACHE_LIMIT = 10;
+
private static final String MAX_REDIRECT_SYSTEM_PROPERTY = "http.maxRedirects"; //$NON-NLS-1$
private static final int DEFAULT_MAX_REDIRECTS = 5;
@@ -152,6 +176,12 @@ public class HttpConfig {
private int maxRedirects;
+ private String cookieFile;
+
+ private boolean saveCookies;
+
+ private int cookieFileCacheLimit;
+
/**
* Get the "http.postBuffer" setting
*
@@ -189,6 +219,40 @@ public class HttpConfig {
}
/**
+ * Get the "http.cookieFile" setting
+ *
+ * @return the value of the "http.cookieFile" setting
+ *
+ * @since 5.4
+ */
+ public String getCookieFile() {
+ return cookieFile;
+ }
+
+ /**
+ * Get the "http.saveCookies" setting
+ *
+ * @return the value of the "http.saveCookies" setting
+ *
+ * @since 5.4
+ */
+ public boolean getSaveCookies() {
+ return saveCookies;
+ }
+
+ /**
+ * Get the "http.cookieFileCacheLimit" setting (gives the maximum number of
+ * cookie files to keep in the LRU cache)
+ *
+ * @return the value of the "http.cookieFileCacheLimit" setting
+ *
+ * @since 5.4
+ */
+ public int getCookieFileCacheLimit() {
+ return cookieFileCacheLimit;
+ }
+
+ /**
* Creates a new {@link org.eclipse.jgit.transport.HttpConfig} tailored to
* the given {@link org.eclipse.jgit.transport.URIish}.
*
@@ -234,6 +298,10 @@ public class HttpConfig {
if (redirectLimit < 0) {
redirectLimit = MAX_REDIRECTS;
}
+ cookieFile = config.getString(HTTP, null, COOKIE_FILE_KEY);
+ saveCookies = config.getBoolean(HTTP, SAVE_COOKIES_KEY, false);
+ cookieFileCacheLimit = config.getInt(HTTP, COOKIE_FILE_CACHE_LIMIT_KEY,
+ DEFAULT_COOKIE_FILE_CACHE_LIMIT);
String match = findMatch(config.getSubsections(HTTP), uri);
if (match != null) {
// Override with more specific items
@@ -248,6 +316,13 @@ public class HttpConfig {
if (newMaxRedirects >= 0) {
redirectLimit = newMaxRedirects;
}
+ String urlSpecificCookieFile = config.getString(HTTP, match,
+ COOKIE_FILE_KEY);
+ if (urlSpecificCookieFile != null) {
+ cookieFile = urlSpecificCookieFile;
+ }
+ saveCookies = config.getBoolean(HTTP, match, SAVE_COOKIES_KEY,
+ saveCookies);
}
postBuffer = postBufferSize;
sslVerify = sslVerifyFlag;
@@ -319,8 +394,9 @@ public class HttpConfig {
// A longer path match is always preferred even over a user
// match. If the path matches are equal, a match with user wins
// over a match without user.
- if (matchLength > bestMatchLength || !withUser && hasUser
- && matchLength >= 0 && matchLength == bestMatchLength) {
+ if (matchLength > bestMatchLength
+ || (!withUser && hasUser && matchLength >= 0
+ && matchLength == bestMatchLength)) {
bestMatch = s;
bestMatchLength = matchLength;
withUser = hasUser;
@@ -366,7 +442,7 @@ public class HttpConfig {
int uLength = uriPath.length();
int mLength = matchPath.length();
if (mLength == uLength || matchPath.charAt(mLength - 1) == '/'
- || mLength < uLength && uriPath.charAt(mLength) == '/') {
+ || (mLength < uLength && uriPath.charAt(mLength) == '/')) {
return mLength;
}
return -1;
@@ -386,7 +462,7 @@ public class HttpConfig {
if (slash < 0) {
slash = length;
}
- if (slash == i || slash == i + 1 && path.charAt(i) == '.') {
+ if (slash == i || (slash == i + 1 && path.charAt(i) == '.')) {
// Skip /. or also double slashes
} else if (slash == i + 2 && path.charAt(i) == '.'
&& path.charAt(i + 1) == '.') {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java
index 9fb9062fbb..dc3dcbc545 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalFetchConnection.java
@@ -107,16 +107,12 @@ class InternalFetchConnection<C> extends BasePackFetchConnection {
try {
final UploadPack rp = uploadPackFactory.create(req, remote);
rp.upload(out_r, in_w, null);
- } catch (ServiceNotEnabledException e) {
+ } catch (ServiceNotEnabledException
+ | ServiceNotAuthorizedException e) {
// Ignored. Client cannot use this repository.
- } catch (ServiceNotAuthorizedException e) {
- // Ignored. Client cannot use this repository.
- } catch (IOException err) {
+ } catch (IOException | RuntimeException err) {
// Client side of the pipes should report the problem.
err.printStackTrace();
- } catch (RuntimeException err) {
- // Client side will notice we went away, and report.
- err.printStackTrace();
} finally {
try {
out_r.close();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java
index f05e0b8c7d..9663de09f4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/InternalPushConnection.java
@@ -100,16 +100,14 @@ class InternalPushConnection<C> extends BasePackPushConnection {
try {
final ReceivePack rp = receivePackFactory.create(req, remote);
rp.receive(out_r, in_w, System.err);
- } catch (ServiceNotEnabledException e) {
- // Ignored. Client cannot use this repository.
- } catch (ServiceNotAuthorizedException e) {
+ } catch (ServiceNotEnabledException
+ | ServiceNotAuthorizedException e) {
// Ignored. Client cannot use this repository.
} catch (IOException e) {
- // Since the InternalPushConnection
- // is used in tests, we want to avoid hiding exceptions
- // because they can point to programming errors on the server
- // side. By rethrowing, the default handler will dump it
- // to stderr.
+ // Since the InternalPushConnection is used in tests, we
+ // want to avoid hiding exceptions because they can point to
+ // programming errors on the server side. By rethrowing, the
+ // default handler will dump it to stderr.
throw new UncheckedIOException(e);
} finally {
try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
index c6e19d5762..d73e1939a6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PacketLineIn.java
@@ -49,7 +49,9 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UncheckedIOException;
import java.text.MessageFormat;
+import java.util.Iterator;
import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.internal.JGitText;
@@ -72,14 +74,25 @@ import org.slf4j.LoggerFactory;
public class PacketLineIn {
private static final Logger log = LoggerFactory.getLogger(PacketLineIn.class);
- /** Magic return from {@link #readString()} when a flush packet is found. */
+ /**
+ * Magic return from {@link #readString()} when a flush packet is found.
+ *
+ * @deprecated Callers should use {@link #isEnd(String)} to check if a
+ * string is the end marker, or
+ * {@link PacketLineIn#readStrings()} to iterate over all
+ * strings in the input stream until the marker is reached.
+ */
+ @Deprecated
public static final String END = new StringBuilder(0).toString(); /* must not string pool */
/**
* Magic return from {@link #readString()} when a delim packet is found.
*
* @since 5.0
+ * @deprecated Callers should use {@link #isDelimiter(String)} to check if a
+ * string is the delimiter.
*/
+ @Deprecated
public static final String DELIM = new StringBuilder(0).toString(); /* must not string pool */
static enum AckNackResult {
@@ -193,6 +206,20 @@ public class PacketLineIn {
}
/**
+ * Get an iterator to read strings from the input stream.
+ *
+ * @return an iterator that calls {@link #readString()} until {@link #END}
+ * is encountered.
+ *
+ * @throws IOException
+ * on failure to read the initial packet line.
+ * @since 5.4
+ */
+ public PacketLineInIterator readStrings() throws IOException {
+ return new PacketLineInIterator(this);
+ }
+
+ /**
* Read a single UTF-8 encoded string packet from the input stream.
* <p>
* Unlike {@link #readString()} a trailing LF will be retained.
@@ -224,6 +251,54 @@ public class PacketLineIn {
return s;
}
+ /**
+ * Check if a string is the delimiter marker.
+ *
+ * @param s
+ * the string to check
+ * @return true if the given string is {@link #DELIM}, otherwise false.
+ * @since 5.4
+ */
+ @SuppressWarnings({ "ReferenceEquality", "StringEquality" })
+ public static boolean isDelimiter(String s) {
+ return s == DELIM;
+ }
+
+ /**
+ * Get the delimiter marker.
+ * <p>
+ * Intended for use only in tests.
+ *
+ * @return The delimiter marker.
+ */
+ static String delimiter() {
+ return DELIM;
+ }
+
+ /**
+ * Get the end marker.
+ * <p>
+ * Intended for use only in tests.
+ *
+ * @return The end marker.
+ */
+ static String end() {
+ return END;
+ }
+
+ /**
+ * Check if a string is the packet end marker.
+ *
+ * @param s
+ * the string to check
+ * @return true if the given string is {@link #END}, otherwise false.
+ * @since 5.4
+ */
+ @SuppressWarnings({ "ReferenceEquality", "StringEquality" })
+ public static boolean isEnd(String s) {
+ return s == END;
+ }
+
void discardUntilEnd() throws IOException {
for (;;) {
int n = readLength();
@@ -282,4 +357,46 @@ public class PacketLineIn {
public static class InputOverLimitIOException extends IOException {
private static final long serialVersionUID = 1L;
}
+
+ /**
+ * Iterator over packet lines.
+ * <p>
+ * Calls {@link #readString()} on the {@link PacketLineIn} until
+ * {@link #END} is encountered.
+ *
+ * @since 5.4
+ *
+ */
+ public static class PacketLineInIterator implements Iterable<String> {
+ private PacketLineIn in;
+
+ private String current;
+
+ PacketLineInIterator(PacketLineIn in) throws IOException {
+ this.in = in;
+ current = in.readString();
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return new Iterator<String>() {
+ @Override
+ public boolean hasNext() {
+ return !PacketLineIn.isEnd(current);
+ }
+
+ @Override
+ public String next() {
+ String next = current;
+ try {
+ current = in.readString();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ return next;
+ }
+ };
+ }
+
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostReceiveHook.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostReceiveHook.java
index ba5d2f3c8f..28a146dde5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostReceiveHook.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostReceiveHook.java
@@ -63,12 +63,9 @@ import java.util.Collection;
*/
public interface PostReceiveHook {
/** A simple no-op hook. */
- PostReceiveHook NULL = new PostReceiveHook() {
- @Override
- public void onPostReceive(final ReceivePack rp,
- final Collection<ReceiveCommand> commands) {
- // Do nothing.
- }
+ PostReceiveHook NULL = (final ReceivePack rp,
+ final Collection<ReceiveCommand> commands) -> {
+ // Do nothing.
};
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHook.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHook.java
index 3aa3b127e5..251bfe271a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHook.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PostUploadHook.java
@@ -57,11 +57,8 @@ import org.eclipse.jgit.storage.pack.PackStatistics;
*/
public interface PostUploadHook {
/** A simple no-op hook. */
- PostUploadHook NULL = new PostUploadHook() {
- @Override
- public void onPostUpload(PackStatistics stats) {
- // Do nothing.
- }
+ PostUploadHook NULL = (PackStatistics stats) -> {
+ // Do nothing.
};
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreReceiveHook.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreReceiveHook.java
index 30845d3b68..b91756bd5e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreReceiveHook.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PreReceiveHook.java
@@ -79,12 +79,9 @@ import java.util.Collection;
*/
public interface PreReceiveHook {
/** A simple no-op hook. */
- PreReceiveHook NULL = new PreReceiveHook() {
- @Override
- public void onPreReceive(final ReceivePack rp,
- final Collection<ReceiveCommand> commands) {
- // Do nothing.
- }
+ PreReceiveHook NULL = (final ReceivePack rp,
+ final Collection<ReceiveCommand> commands) -> {
+ // Do nothing.
};
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV0Parser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV0Parser.java
index 21498d6f5c..428a45c09d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV0Parser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV0Parser.java
@@ -99,7 +99,7 @@ final class ProtocolV0Parser {
throw eof;
}
- if (line == PacketLineIn.END) {
+ if (PacketLineIn.isEnd(line)) {
break;
}
@@ -130,7 +130,7 @@ final class ProtocolV0Parser {
}
filterReceived = true;
- reqBuilder.setFilterBlobLimit(ProtocolV2Parser.filterLine(arg));
+ reqBuilder.setFilterSpec(FilterSpec.fromFilterLine(arg));
continue;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
index 8f4b86ee0a..caba15fc54 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ProtocolV2Parser.java
@@ -92,7 +92,7 @@ final class ProtocolV2Parser {
String agentPrefix = OPTION_AGENT + '=';
String line = pckIn.readString();
- while (line != PacketLineIn.DELIM && line != PacketLineIn.END) {
+ while (!PacketLineIn.isDelimiter(line) && !PacketLineIn.isEnd(line)) {
if (line.startsWith(serverOptionPrefix)) {
serverOptionConsumer
.accept(line.substring(serverOptionPrefix.length()));
@@ -133,40 +133,41 @@ final class ProtocolV2Parser {
serverOption -> reqBuilder.addServerOption(serverOption),
agent -> reqBuilder.setAgent(agent));
- if (line == PacketLineIn.END) {
+ if (PacketLineIn.isEnd(line)) {
return reqBuilder.build();
}
- if (line != PacketLineIn.DELIM) {
+ if (!PacketLineIn.isDelimiter(line)) {
throw new PackProtocolException(
MessageFormat.format(JGitText.get().unexpectedPacketLine,
line));
}
boolean filterReceived = false;
- while ((line = pckIn.readString()) != PacketLineIn.END) {
- if (line.startsWith("want ")) { //$NON-NLS-1$
- reqBuilder.addWantId(ObjectId.fromString(line.substring(5)));
+ for (String line2 : pckIn.readStrings()) {
+ if (line2.startsWith("want ")) { //$NON-NLS-1$
+ reqBuilder.addWantId(ObjectId.fromString(line2.substring(5)));
} else if (transferConfig.isAllowRefInWant()
- && line.startsWith(OPTION_WANT_REF + " ")) { //$NON-NLS-1$
- reqBuilder.addWantedRef(line.substring(OPTION_WANT_REF.length() + 1));
- } else if (line.startsWith("have ")) { //$NON-NLS-1$
- reqBuilder.addPeerHas(ObjectId.fromString(line.substring(5)));
- } else if (line.equals("done")) { //$NON-NLS-1$
+ && line2.startsWith(OPTION_WANT_REF + " ")) { //$NON-NLS-1$
+ reqBuilder.addWantedRef(
+ line2.substring(OPTION_WANT_REF.length() + 1));
+ } else if (line2.startsWith("have ")) { //$NON-NLS-1$
+ reqBuilder.addPeerHas(ObjectId.fromString(line2.substring(5)));
+ } else if (line2.equals("done")) { //$NON-NLS-1$
reqBuilder.setDoneReceived();
- } else if (line.equals(OPTION_THIN_PACK)) {
+ } else if (line2.equals(OPTION_THIN_PACK)) {
reqBuilder.addClientCapability(OPTION_THIN_PACK);
- } else if (line.equals(OPTION_NO_PROGRESS)) {
+ } else if (line2.equals(OPTION_NO_PROGRESS)) {
reqBuilder.addClientCapability(OPTION_NO_PROGRESS);
- } else if (line.equals(OPTION_INCLUDE_TAG)) {
+ } else if (line2.equals(OPTION_INCLUDE_TAG)) {
reqBuilder.addClientCapability(OPTION_INCLUDE_TAG);
- } else if (line.equals(OPTION_OFS_DELTA)) {
+ } else if (line2.equals(OPTION_OFS_DELTA)) {
reqBuilder.addClientCapability(OPTION_OFS_DELTA);
- } else if (line.startsWith("shallow ")) { //$NON-NLS-1$
+ } else if (line2.startsWith("shallow ")) { //$NON-NLS-1$
reqBuilder.addClientShallowCommit(
- ObjectId.fromString(line.substring(8)));
- } else if (line.startsWith("deepen ")) { //$NON-NLS-1$
- int parsedDepth = Integer.parseInt(line.substring(7));
+ ObjectId.fromString(line2.substring(8)));
+ } else if (line2.startsWith("deepen ")) { //$NON-NLS-1$
+ int parsedDepth = Integer.parseInt(line2.substring(7));
if (parsedDepth <= 0) {
throw new PackProtocolException(
MessageFormat.format(JGitText.get().invalidDepth,
@@ -181,19 +182,19 @@ final class ProtocolV2Parser {
JGitText.get().deepenNotWithDeepen);
}
reqBuilder.setDepth(parsedDepth);
- } else if (line.startsWith("deepen-not ")) { //$NON-NLS-1$
- reqBuilder.addDeepenNotRef(line.substring(11));
+ } else if (line2.startsWith("deepen-not ")) { //$NON-NLS-1$
+ reqBuilder.addDeepenNotRef(line2.substring(11));
if (reqBuilder.getDepth() != 0) {
throw new PackProtocolException(
JGitText.get().deepenNotWithDeepen);
}
- } else if (line.equals(OPTION_DEEPEN_RELATIVE)) {
+ } else if (line2.equals(OPTION_DEEPEN_RELATIVE)) {
reqBuilder.addClientCapability(OPTION_DEEPEN_RELATIVE);
- } else if (line.startsWith("deepen-since ")) { //$NON-NLS-1$
- int ts = Integer.parseInt(line.substring(13));
+ } else if (line2.startsWith("deepen-since ")) { //$NON-NLS-1$
+ int ts = Integer.parseInt(line2.substring(13));
if (ts <= 0) {
throw new PackProtocolException(MessageFormat
- .format(JGitText.get().invalidTimestamp, line));
+ .format(JGitText.get().invalidTimestamp, line2));
}
if (reqBuilder.getDepth() != 0) {
throw new PackProtocolException(
@@ -201,17 +202,17 @@ final class ProtocolV2Parser {
}
reqBuilder.setDeepenSince(ts);
} else if (transferConfig.isAllowFilter()
- && line.startsWith(OPTION_FILTER + ' ')) {
+ && line2.startsWith(OPTION_FILTER + ' ')) {
if (filterReceived) {
throw new PackProtocolException(
JGitText.get().tooManyFilters);
}
filterReceived = true;
- reqBuilder.setFilterBlobLimit(filterLine(
- line.substring(OPTION_FILTER.length() + 1)));
+ reqBuilder.setFilterSpec(FilterSpec.fromFilterLine(
+ line2.substring(OPTION_FILTER.length() + 1)));
} else {
throw new PackProtocolException(MessageFormat
- .format(JGitText.get().unexpectedPacketLine, line));
+ .format(JGitText.get().unexpectedPacketLine, line2));
}
}
@@ -244,67 +245,29 @@ final class ProtocolV2Parser {
serverOption -> builder.addServerOption(serverOption),
agent -> builder.setAgent(agent));
- if (line == PacketLineIn.END) {
+ if (PacketLineIn.isEnd(line)) {
return builder.build();
}
- if (line != PacketLineIn.DELIM) {
+ if (!PacketLineIn.isDelimiter(line)) {
throw new PackProtocolException(MessageFormat
.format(JGitText.get().unexpectedPacketLine, line));
}
- while ((line = pckIn.readString()) != PacketLineIn.END) {
- if (line.equals("peel")) { //$NON-NLS-1$
+ for (String line2 : pckIn.readStrings()) {
+ if (line2.equals("peel")) { //$NON-NLS-1$
builder.setPeel(true);
- } else if (line.equals("symrefs")) { //$NON-NLS-1$
+ } else if (line2.equals("symrefs")) { //$NON-NLS-1$
builder.setSymrefs(true);
- } else if (line.startsWith("ref-prefix ")) { //$NON-NLS-1$
- prefixes.add(line.substring("ref-prefix ".length())); //$NON-NLS-1$
+ } else if (line2.startsWith("ref-prefix ")) { //$NON-NLS-1$
+ prefixes.add(line2.substring("ref-prefix ".length())); //$NON-NLS-1$
} else {
throw new PackProtocolException(MessageFormat
- .format(JGitText.get().unexpectedPacketLine, line));
+ .format(JGitText.get().unexpectedPacketLine, line2));
}
}
return builder.setRefPrefixes(prefixes).build();
}
- /*
- * Process the content of "filter" line from the protocol. It has a shape
- * like "blob:none" or "blob:limit=N", with limit a positive number.
- *
- * @param blobLine
- * the content of the "filter" line in the protocol
- * @return N, the limit, defaulting to 0 if "none"
- * @throws PackProtocolException
- * invalid filter because due to unrecognized format or
- * negative/non-numeric filter.
- */
- static long filterLine(String blobLine) throws PackProtocolException {
- long blobLimit = -1;
-
- if (blobLine.equals("blob:none")) { //$NON-NLS-1$
- blobLimit = 0;
- } else if (blobLine.startsWith("blob:limit=")) { //$NON-NLS-1$
- try {
- blobLimit = Long
- .parseLong(blobLine.substring("blob:limit=".length())); //$NON-NLS-1$
- } catch (NumberFormatException e) {
- throw new PackProtocolException(MessageFormat
- .format(JGitText.get().invalidFilter, blobLine));
- }
- }
- /*
- * We must have (1) either "blob:none" or "blob:limit=" set (because we
- * only support blob size limits for now), and (2) if the latter, then
- * it must be nonnegative. Throw if (1) or (2) is not met.
- */
- if (blobLimit < 0) {
- throw new PackProtocolException(
- MessageFormat.format(JGitText.get().invalidFilter, blobLine));
- }
-
- return blobLimit;
- }
-
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java
index aeca63500a..14afc44eec 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java
@@ -57,7 +57,6 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -193,81 +192,78 @@ public class PushCertificateStore implements AutoCloseable {
* close resources.
*/
public Iterable<PushCertificate> getAll(String refName) {
- return new Iterable<PushCertificate>() {
- @Override
- public Iterator<PushCertificate> iterator() {
- return new Iterator<PushCertificate>() {
- private final String path = pathName(refName);
- private PushCertificate next;
+ return () -> new Iterator<PushCertificate>() {
+ private final String path = pathName(refName);
+
+ private PushCertificate next;
+
+ private RevWalk rw;
+ {
+ try {
+ if (reader == null) {
+ load();
+ }
+ if (commit != null) {
+ rw = new RevWalk(reader);
+ rw.setTreeFilter(AndTreeFilter.create(
+ PathFilterGroup.create(Collections
+ .singleton(PathFilter.create(path))),
+ TreeFilter.ANY_DIFF));
+ rw.setRewriteParents(false);
+ rw.markStart(rw.parseCommit(commit));
+ } else {
+ rw = null;
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
- private RevWalk rw;
- {
+ @Override
+ public boolean hasNext() {
+ try {
+ if (next == null) {
+ if (rw == null) {
+ return false;
+ }
try {
- if (reader == null) {
- load();
- }
- if (commit != null) {
- rw = new RevWalk(reader);
- rw.setTreeFilter(AndTreeFilter.create(
- PathFilterGroup.create(
- Collections.singleton(PathFilter.create(path))),
- TreeFilter.ANY_DIFF));
- rw.setRewriteParents(false);
- rw.markStart(rw.parseCommit(commit));
+ RevCommit c = rw.next();
+ if (c != null) {
+ try (TreeWalk tw = TreeWalk.forPath(
+ rw.getObjectReader(), path,
+ c.getTree())) {
+ next = read(tw);
+ }
} else {
- rw = null;
+ next = null;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
-
- @Override
- public boolean hasNext() {
- try {
- if (next == null) {
- if (rw == null) {
- return false;
- }
- try {
- RevCommit c = rw.next();
- if (c != null) {
- try (TreeWalk tw = TreeWalk.forPath(
- rw.getObjectReader(), path, c.getTree())) {
- next = read(tw);
- }
- } else {
- next = null;
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- return next != null;
- } finally {
- if (next == null && rw != null) {
- rw.close();
- rw = null;
- }
- }
+ return next != null;
+ } finally {
+ if (next == null && rw != null) {
+ rw.close();
+ rw = null;
}
+ }
+ }
- @Override
- public PushCertificate next() {
- hasNext();
- PushCertificate n = next;
- if (n == null) {
- throw new NoSuchElementException();
- }
- next = null;
- return n;
- }
+ @Override
+ public PushCertificate next() {
+ hasNext();
+ PushCertificate n = next;
+ if (n == null) {
+ throw new NoSuchElementException();
+ }
+ next = null;
+ return n;
+ }
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
}
};
}
@@ -442,13 +438,8 @@ public class PushCertificateStore implements AutoCloseable {
}
private static void sortPending(List<PendingCert> pending) {
- Collections.sort(pending, new Comparator<PendingCert>() {
- @Override
- public int compare(PendingCert a, PendingCert b) {
- return Long.signum(
- a.ident.getWhen().getTime() - b.ident.getWhen().getTime());
- }
- });
+ Collections.sort(pending, (PendingCert a, PendingCert b) -> Long.signum(
+ a.ident.getWhen().getTime() - b.ident.getWhen().getTime()));
}
private DirCache newDirCache() throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java
index d61aeb04d2..a9a995cd3f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java
@@ -429,7 +429,7 @@ public class ReceiveCommand {
this.newId = ObjectId.zeroId();
this.newSymref = newSymref;
this.name = name;
- if (AnyObjectId.equals(ObjectId.zeroId(), oldId)) {
+ if (AnyObjectId.isEqual(ObjectId.zeroId(), oldId)) {
type = Type.CREATE;
} else if (newSymref != null) {
type = Type.UPDATE;
@@ -468,7 +468,7 @@ public class ReceiveCommand {
this.name = name;
if (oldSymref == null) {
type = Type.CREATE;
- } else if (!AnyObjectId.equals(ObjectId.zeroId(), newId)) {
+ } else if (!AnyObjectId.isEqual(ObjectId.zeroId(), newId)) {
type = Type.UPDATE;
} else {
type = Type.DELETE;
@@ -750,7 +750,7 @@ public class ReceiveCommand {
public void updateType(RevWalk walk) throws IOException {
if (typeIsCorrect)
return;
- if (type == Type.UPDATE && !AnyObjectId.equals(oldId, newId)) {
+ if (type == Type.UPDATE && !AnyObjectId.isEqual(oldId, newId)) {
RevObject o = walk.parseAny(oldId);
RevObject n = walk.parseAny(newId);
if (!(o instanceof RevCommit)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
index 4652c3fda8..d6adf1e0d8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
@@ -348,7 +348,7 @@ public class ReceivePack extends BaseReceivePack {
pushOptions = new ArrayList<>(4);
for (;;) {
String option = in.readString();
- if (option == PacketLineIn.END) {
+ if (PacketLineIn.isEnd(option)) {
break;
}
pushOptions.add(option);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefFilter.java
index d6d6198f5b..d19c652c25 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefFilter.java
@@ -61,12 +61,7 @@ public interface RefFilter {
/**
* The default filter, allows all refs to be shown.
*/
- RefFilter DEFAULT = new RefFilter() {
- @Override
- public Map<String, Ref> filter (Map<String, Ref> refs) {
- return refs;
- }
- };
+ RefFilter DEFAULT = (Map<String, Ref> refs) -> refs;
/**
* Filters a {@code Map} of refs before it is advertised to the client.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java
index afd3adaacc..16c6faf277 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefSpec.java
@@ -49,6 +49,7 @@ import java.text.MessageFormat;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.util.References;
/**
* Describes how refs in one repository copy into another repository.
@@ -585,8 +586,9 @@ public class RefSpec implements Serializable {
}
private static boolean eq(String a, String b) {
- if (a == b)
+ if (References.isSameObject(a, b)) {
return true;
+ }
if (a == null || b == null)
return false;
return a.equals(b);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
index 005a0c2d0e..fdb19df91a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshSessionFactory.java
@@ -100,13 +100,9 @@ public abstract class SshSessionFactory {
* @since 5.2
*/
public static String getLocalUserName() {
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
- @Override
- public String run() {
- return SystemReader.getInstance()
- .getProperty(Constants.OS_USER_NAME_KEY);
- }
- });
+ return AccessController
+ .doPrivileged((PrivilegedAction<String>) () -> SystemReader
+ .getInstance().getProperty(Constants.OS_USER_NAME_KEY));
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java
index ba2a673a18..550a9ef372 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TrackingRefUpdate.java
@@ -175,7 +175,7 @@ public class TrackingRefUpdate {
private RefUpdate.Result decode(ReceiveCommand.Result status) {
switch (status) {
case OK:
- if (AnyObjectId.equals(oldObjectId, newObjectId))
+ if (AnyObjectId.isEqual(oldObjectId, newObjectId))
return RefUpdate.Result.NO_CHANGE;
switch (getType()) {
case CREATE:
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
index 621c2ea56c..0b7907035e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -47,6 +47,7 @@
package org.eclipse.jgit.transport;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Objects.requireNonNull;
import java.io.BufferedReader;
import java.io.IOException;
@@ -70,6 +71,7 @@ import java.util.Map;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
+import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.api.errors.AbortedByHookException;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
@@ -178,10 +180,7 @@ public abstract class Transport implements AutoCloseable {
TransportProtocol proto;
try {
proto = (TransportProtocol) f.get(null);
- } catch (IllegalArgumentException e) {
- // If we cannot access the field, don't.
- continue;
- } catch (IllegalAccessException e) {
+ } catch (IllegalArgumentException | IllegalAccessException e) {
// If we cannot access the field, don't.
continue;
}
@@ -790,7 +789,7 @@ public abstract class Transport implements AutoCloseable {
/** Should refs no longer on the source be pruned from the destination? */
private boolean removeDeletedRefs;
- private long filterBlobLimit = -1;
+ private FilterSpec filterSpec = FilterSpec.NO_FILTER;
/** Timeout in seconds to wait before aborting an IO read or write. */
private int timeout;
@@ -1067,20 +1066,42 @@ public abstract class Transport implements AutoCloseable {
}
/**
- * @return the last value passed to {@link #setFilterBlobLimit}, or -1 if
- * it was never invoked.
+ * @return the blob limit value set with {@link #setFilterBlobLimit} or
+ * {@link #setFilterSpec(FilterSpec)}, or -1 if no blob limit value
+ * was set
* @since 5.0
+ * @deprecated Use {@link #getFilterSpec()} instead
*/
- public long getFilterBlobLimit() {
- return filterBlobLimit;
+ @Deprecated
+ public final long getFilterBlobLimit() {
+ return filterSpec.getBlobLimit();
}
/**
* @param bytes exclude blobs of size greater than this
* @since 5.0
+ * @deprecated Use {@link #setFilterSpec(FilterSpec)} instead
+ */
+ @Deprecated
+ public final void setFilterBlobLimit(long bytes) {
+ setFilterSpec(FilterSpec.withBlobLimit(bytes));
+ }
+
+ /**
+ * @return the last filter spec set with {@link #setFilterSpec(FilterSpec)},
+ * or {@link FilterSpec#NO_FILTER} if it was never invoked.
+ * @since 5.4
+ */
+ public final FilterSpec getFilterSpec() {
+ return filterSpec;
+ }
+
+ /**
+ * @param filter a new filter to use for this transport
+ * @since 5.4
*/
- public void setFilterBlobLimit(long bytes) {
- filterBlobLimit = bytes;
+ public final void setFilterSpec(@NonNull FilterSpec filter) {
+ filterSpec = requireNonNull(filter);
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
index 0df1b70cb7..a591dbae2a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -54,8 +54,11 @@ import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT;
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_ENCODING;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_ENCODING;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
+import static org.eclipse.jgit.util.HttpSupport.HDR_COOKIE;
import static org.eclipse.jgit.util.HttpSupport.HDR_LOCATION;
import static org.eclipse.jgit.util.HttpSupport.HDR_PRAGMA;
+import static org.eclipse.jgit.util.HttpSupport.HDR_SET_COOKIE;
+import static org.eclipse.jgit.util.HttpSupport.HDR_SET_COOKIE2;
import static org.eclipse.jgit.util.HttpSupport.HDR_USER_AGENT;
import static org.eclipse.jgit.util.HttpSupport.HDR_WWW_AUTHENTICATE;
import static org.eclipse.jgit.util.HttpSupport.METHOD_GET;
@@ -68,11 +71,15 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.net.HttpCookie;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
@@ -84,6 +91,8 @@ import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -100,6 +109,8 @@ import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.RefDirectory;
+import org.eclipse.jgit.internal.transport.http.NetscapeCookieFile;
+import org.eclipse.jgit.internal.transport.http.NetscapeCookieFileCache;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
@@ -114,6 +125,7 @@ import org.eclipse.jgit.transport.http.HttpConnection;
import org.eclipse.jgit.util.HttpSupport;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.StringUtils;
import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.TemporaryBuffer;
import org.eclipse.jgit.util.io.DisabledOutputStream;
@@ -272,6 +284,19 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
private boolean sslFailure = false;
+ /**
+ * All stored cookies bound to this repo (independent of the baseUrl)
+ */
+ private final NetscapeCookieFile cookieFile;
+
+ /**
+ * The cookies to be sent with each request to the given {@link #baseUrl}.
+ * Filtered view on top of {@link #cookieFile} where only cookies which
+ * apply to the current url are left. This set needs to be filtered for
+ * expired entries each time prior to sending them.
+ */
+ private final Set<HttpCookie> relevantCookies;
+
TransportHttp(Repository local, URIish uri)
throws NotSupportedException {
super(local, uri);
@@ -279,6 +304,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
http = new HttpConfig(local.getConfig(), uri);
proxySelector = ProxySelector.getDefault();
sslVerify = http.isSslVerify();
+ cookieFile = getCookieFileFromConfig(http);
+ relevantCookies = filterCookies(cookieFile, baseUrl);
}
private URL toURL(URIish urish) throws MalformedURLException {
@@ -319,6 +346,8 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
http = new HttpConfig(uri);
proxySelector = ProxySelector.getDefault();
sslVerify = http.isSslVerify();
+ cookieFile = getCookieFileFromConfig(http);
+ relevantCookies = filterCookies(cookieFile, baseUrl);
}
/**
@@ -361,9 +390,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
try (InputStream in = openInputStream(c)) {
return getConnection(c, in, service);
}
- } catch (NotSupportedException err) {
- throw err;
- } catch (TransportException err) {
+ } catch (NotSupportedException | TransportException err) {
throw err;
} catch (IOException err) {
throw new TransportException(uri, JGitText.get().errorReadingInfoRefs, err);
@@ -447,9 +474,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
throw new NotSupportedException(msg);
}
}
- } catch (NotSupportedException err) {
- throw err;
- } catch (TransportException err) {
+ } catch (NotSupportedException | TransportException err) {
throw err;
} catch (IOException err) {
throw new TransportException(uri, JGitText.get().errorReadingInfoRefs, err);
@@ -510,6 +535,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
conn.setRequestProperty(HDR_ACCEPT, "*/*"); //$NON-NLS-1$
}
final int status = HttpSupport.response(conn);
+ processResponseCookies(conn);
switch (status) {
case HttpConnection.HTTP_OK:
// Check if HttpConnection did some authentication in the
@@ -573,9 +599,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
String err = status + " " + conn.getResponseMessage(); //$NON-NLS-1$
throw new TransportException(uri, err);
}
- } catch (NotSupportedException e) {
- throw e;
- } catch (TransportException e) {
+ } catch (NotSupportedException | TransportException e) {
throw e;
} catch (SSLHandshakeException e) {
handleSslFailure(e);
@@ -600,6 +624,57 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
}
}
+ void processResponseCookies(HttpConnection conn) {
+ if (cookieFile != null && http.getSaveCookies()) {
+ List<HttpCookie> foundCookies = new LinkedList<>();
+
+ List<String> cookieHeaderValues = conn
+ .getHeaderFields(HDR_SET_COOKIE);
+ if (!cookieHeaderValues.isEmpty()) {
+ foundCookies.addAll(
+ extractCookies(HDR_SET_COOKIE, cookieHeaderValues));
+ }
+ cookieHeaderValues = conn.getHeaderFields(HDR_SET_COOKIE2);
+ if (!cookieHeaderValues.isEmpty()) {
+ foundCookies.addAll(
+ extractCookies(HDR_SET_COOKIE2, cookieHeaderValues));
+ }
+ if (!foundCookies.isEmpty()) {
+ try {
+ // update cookie lists with the newly received cookies!
+ Set<HttpCookie> cookies = cookieFile.getCookies(false);
+ cookies.addAll(foundCookies);
+ cookieFile.write(baseUrl);
+ relevantCookies.addAll(foundCookies);
+ } catch (IOException | IllegalArgumentException
+ | InterruptedException e) {
+ LOG.warn(MessageFormat.format(
+ JGitText.get().couldNotPersistCookies,
+ cookieFile.getPath()), e);
+ }
+ }
+ }
+ }
+
+ private List<HttpCookie> extractCookies(String headerKey,
+ List<String> headerValues) {
+ List<HttpCookie> foundCookies = new LinkedList<>();
+ for (String headerValue : headerValues) {
+ foundCookies
+ .addAll(HttpCookie.parse(headerKey + ':' + headerValue));
+ }
+ // HttpCookies.parse(...) is only compliant with RFC 2965. Make it RFC
+ // 6265 compliant by applying the logic from
+ // https://tools.ietf.org/html/rfc6265#section-5.2.3
+ for (HttpCookie foundCookie : foundCookies) {
+ String domain = foundCookie.getDomain();
+ if (domain != null && domain.startsWith(".")) { //$NON-NLS-1$
+ foundCookie.setDomain(domain.substring(1));
+ }
+ }
+ return foundCookies;
+ }
+
private static class CredentialItems {
CredentialItem.InformationalMessage message;
@@ -775,7 +850,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
}
// git allows only rewriting the root, i.e., everything before INFO_REFS
// or the service name
- if (next.indexOf(checkFor) < 0) {
+ if (!next.contains(checkFor)) {
return false;
}
// Basically we should test here that whatever follows INFO_REFS is
@@ -849,14 +924,35 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
conn.setConnectTimeout(effTimeOut);
conn.setReadTimeout(effTimeOut);
}
+ // set cookie header if necessary
+ if (!relevantCookies.isEmpty()) {
+ setCookieHeader(conn);
+ }
+
if (this.headers != null && !this.headers.isEmpty()) {
- for (Map.Entry<String, String> entry : this.headers.entrySet())
+ for (Map.Entry<String, String> entry : this.headers.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
+ }
}
authMethod.configureRequest(conn);
return conn;
}
+ private void setCookieHeader(HttpConnection conn) {
+ StringBuilder cookieHeaderValue = new StringBuilder();
+ for (HttpCookie cookie : relevantCookies) {
+ if (!cookie.hasExpired()) {
+ if (cookieHeaderValue.length() > 0) {
+ cookieHeaderValue.append(';');
+ }
+ cookieHeaderValue.append(cookie.toString());
+ }
+ }
+ if (cookieHeaderValue.length() > 0) {
+ conn.setRequestProperty(HDR_COOKIE, cookieHeaderValue.toString());
+ }
+ }
+
final InputStream openInputStream(HttpConnection conn)
throws IOException {
InputStream input = conn.getInputStream();
@@ -870,6 +966,150 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
return new TransportException(uri, why);
}
+ private static NetscapeCookieFile getCookieFileFromConfig(
+ HttpConfig config) {
+ if (!StringUtils.isEmptyOrNull(config.getCookieFile())) {
+ try {
+ Path cookieFilePath = Paths.get(config.getCookieFile());
+ return NetscapeCookieFileCache.getInstance(config)
+ .getEntry(cookieFilePath);
+ } catch (InvalidPathException e) {
+ LOG.warn(MessageFormat.format(
+ JGitText.get().couldNotReadCookieFile,
+ config.getCookieFile()), e);
+ }
+ }
+ return null;
+ }
+
+ private static Set<HttpCookie> filterCookies(NetscapeCookieFile cookieFile,
+ URL url) {
+ if (cookieFile != null) {
+ return filterCookies(cookieFile.getCookies(true), url);
+ }
+ return Collections.emptySet();
+ }
+
+ /**
+ *
+ * @param allCookies
+ * a list of cookies.
+ * @param url
+ * the url for which to filter the list of cookies.
+ * @return only the cookies from {@code allCookies} which are relevant (i.e.
+ * are not expired, have a matching domain, have a matching path and
+ * have a matching secure attribute)
+ */
+ private static Set<HttpCookie> filterCookies(Set<HttpCookie> allCookies,
+ URL url) {
+ Set<HttpCookie> filteredCookies = new HashSet<>();
+ for (HttpCookie cookie : allCookies) {
+ if (cookie.hasExpired()) {
+ continue;
+ }
+ if (!matchesCookieDomain(url.getHost(), cookie.getDomain())) {
+ continue;
+ }
+ if (!matchesCookiePath(url.getPath(), cookie.getPath())) {
+ continue;
+ }
+ if (cookie.getSecure() && !"https".equals(url.getProtocol())) { //$NON-NLS-1$
+ continue;
+ }
+ filteredCookies.add(cookie);
+ }
+ return filteredCookies;
+ }
+
+ /**
+ *
+ * The utility method to check whether a host name is in a cookie's domain
+ * or not. Similar to {@link HttpCookie#domainMatches(String, String)} but
+ * implements domain matching rules according to
+ * <a href="https://tools.ietf.org/html/rfc6265#section-5.1.3">RFC 6265,
+ * section 5.1.3</a> instead of the rules from
+ * <a href="https://tools.ietf.org/html/rfc2965#section-3.3">RFC 2965,
+ * section 3.3.1</a>.
+ * <p>
+ * The former rules are also used by libcurl internally.
+ * <p>
+ * The rules are as follows
+ *
+ * A string matches another domain string if at least one of the following
+ * conditions holds:
+ * <ul>
+ * <li>The domain string and the string are identical. (Note that both the
+ * domain string and the string will have been canonicalized to lower case
+ * at this point.)</li>
+ * <li>All of the following conditions hold
+ * <ul>
+ * <li>The domain string is a suffix of the string.</li>
+ * <li>The last character of the string that is not included in the domain
+ * string is a %x2E (".") character.</li>
+ * <li>The string is a host name (i.e., not an IP address).</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @param host
+ * the host to compare against the cookieDomain
+ * @param cookieDomain
+ * the domain to compare against
+ * @return {@code true} if they domain-match; {@code false} if not
+ *
+ * @see <a href= "https://tools.ietf.org/html/rfc6265#section-5.1.3">RFC
+ * 6265, section 5.1.3 (Domain Matching)</a>
+ * @see <a href=
+ * "https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8206092">JDK-8206092
+ * : HttpCookie.domainMatches() does not match to sub-sub-domain</a>
+ */
+ static boolean matchesCookieDomain(String host, String cookieDomain) {
+ cookieDomain = cookieDomain.toLowerCase(Locale.ROOT);
+ host = host.toLowerCase(Locale.ROOT);
+ if (host.equals(cookieDomain)) {
+ return true;
+ } else {
+ if (!host.endsWith(cookieDomain)) {
+ return false;
+ }
+ return host
+ .charAt(host.length() - cookieDomain.length() - 1) == '.';
+ }
+ }
+
+ /**
+ * The utility method to check whether a path is matching a cookie path
+ * domain or not. The rules are defined by
+ * <a href="https://tools.ietf.org/html/rfc6265#section-5.1.4">RFC 6265,
+ * section 5.1.4</a>:
+ *
+ * A request-path path-matches a given cookie-path if at least one of the
+ * following conditions holds:
+ * <ul>
+ * <li>The cookie-path and the request-path are identical.</li>
+ * <li>The cookie-path is a prefix of the request-path, and the last
+ * character of the cookie-path is %x2F ("/").</li>
+ * <li>The cookie-path is a prefix of the request-path, and the first
+ * character of the request-path that is not included in the cookie- path is
+ * a %x2F ("/") character.</li>
+ * </ul>
+ * @param path
+ * the path to check
+ * @param cookiePath
+ * the cookie's path
+ *
+ * @return {@code true} if they path-match; {@code false} if not
+ */
+ static boolean matchesCookiePath(String path, String cookiePath) {
+ if (cookiePath.equals(path)) {
+ return true;
+ }
+ if (!cookiePath.endsWith("/")) { //$NON-NLS-1$
+ cookiePath += "/"; //$NON-NLS-1$
+ }
+ return path.startsWith(cookiePath);
+ }
+
private boolean isSmartHttp(HttpConnection c, String service) {
final String expType = "application/x-" + service + "-advertisement"; //$NON-NLS-1$ //$NON-NLS-2$
final String actType = c.getContentType();
@@ -904,7 +1144,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
JGitText.get().expectedGot, exp, act));
}
- while (pckIn.readString() != PacketLineIn.END) {
+ while (!PacketLineIn.isEnd(pckIn.readString())) {
// for now, ignore the remaining header lines
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
index fbb2c44100..f2a2b0a1c2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportLocal.java
@@ -188,12 +188,8 @@ class TransportLocal extends Transport implements PackTransport {
&& !"git upload-pack".equals(up)) //$NON-NLS-1$
return new ForkLocalFetchConnection();
- UploadPackFactory<Void> upf = new UploadPackFactory<Void>() {
- @Override
- public UploadPack create(Void req, Repository db) {
- return createUploadPack(db);
- }
- };
+ UploadPackFactory<Void> upf = (Void req,
+ Repository db) -> createUploadPack(db);
return new InternalFetchConnection<>(this, upf, null, openRepo());
}
@@ -205,12 +201,8 @@ class TransportLocal extends Transport implements PackTransport {
&& !"git receive-pack".equals(rp)) //$NON-NLS-1$
return new ForkLocalPushConnection();
- ReceivePackFactory<Void> rpf = new ReceivePackFactory<Void>() {
- @Override
- public ReceivePack create(Void req, Repository db) {
- return createReceivePack(db);
- }
- };
+ ReceivePackFactory<Void> rpf = (Void req,
+ Repository db) -> createReceivePack(db);
return new InternalPushConnection<>(this, rpf, null, openRepo());
}
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 70fb1f0e56..7ca9cc134c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/URIish.java
@@ -62,6 +62,7 @@ import java.util.regex.Pattern;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.RawParseUtils;
+import org.eclipse.jgit.util.References;
import org.eclipse.jgit.util.StringUtils;
/**
@@ -362,8 +363,8 @@ public class URIish implements Serializable {
if (p.length() >= 3
&& p.charAt(0) == '/'
&& p.charAt(2) == ':'
- && (p.charAt(1) >= 'A' && p.charAt(1) <= 'Z' || p.charAt(1) >= 'a'
- && p.charAt(1) <= 'z'))
+ && ((p.charAt(1) >= 'A' && p.charAt(1) <= 'Z')
+ || (p.charAt(1) >= 'a' && p.charAt(1) <= 'z')))
return p.substring(1);
else if (s != null && p.length() >= 2 && p.charAt(0) == '/'
&& p.charAt(1) == '~')
@@ -624,8 +625,9 @@ public class URIish implements Serializable {
}
private static boolean eq(String a, String b) {
- if (a == b)
+ if (References.isSameObject(a, b)) {
return true;
+ }
if (StringUtils.isEmptyOrNull(a) && StringUtils.isEmptyOrNull(b))
return true;
if (a == null || b == null)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
index 1d0f836619..9278f42adf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -44,13 +44,11 @@
package org.eclipse.jgit.transport;
import static java.util.Collections.unmodifiableMap;
-import static java.util.function.Function.identity;
-import static java.util.stream.Collectors.toMap;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REF_IN_WANT;
+import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SERVER_OPTION;
import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_FETCH;
import static org.eclipse.jgit.transport.GitProtocolConstants.COMMAND_LS_REFS;
-import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SERVER_OPTION;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT;
@@ -66,6 +64,7 @@ import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SHALLOW;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
+import static org.eclipse.jgit.util.RefMap.toRefMap;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
@@ -81,8 +80,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
+import java.util.stream.Collectors;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
@@ -107,6 +108,7 @@ import org.eclipse.jgit.revwalk.AsyncRevObjectQueue;
import org.eclipse.jgit.revwalk.BitmapWalker;
import org.eclipse.jgit.revwalk.DepthWalk;
import org.eclipse.jgit.revwalk.ObjectWalk;
+import org.eclipse.jgit.revwalk.ReachabilityChecker;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevFlagSet;
@@ -817,7 +819,7 @@ public class UploadPack {
// Fall back to all refs.
setAdvertisedRefs(
db.getRefDatabase().getRefs().stream()
- .collect(toMap(Ref::getName, identity())));
+ .collect(toRefMap((a, b) -> b)));
}
return refs;
}
@@ -836,7 +838,7 @@ public class UploadPack {
String[] prefixes = refPrefixes.toArray(new String[0]);
Map<String, Ref> rs =
db.getRefDatabase().getRefsByPrefix(prefixes).stream()
- .collect(toMap(Ref::getName, identity(), (a, b) -> b));
+ .collect(toRefMap((a, b) -> b));
if (refFilter != RefFilter.DEFAULT) {
return refFilter.filter(rs);
}
@@ -848,7 +850,7 @@ public class UploadPack {
return refs.values().stream()
.filter(ref -> refPrefixes.stream()
.anyMatch(ref.getName()::startsWith))
- .collect(toMap(Ref::getName, identity()));
+ .collect(toRefMap((a, b) -> b));
}
/**
@@ -871,7 +873,7 @@ public class UploadPack {
names.stream()
.map(refs::get)
.filter(Objects::nonNull)
- .collect(toMap(Ref::getName, identity(), (a, b) -> b)));
+ .collect(toRefMap((a, b) -> b)));
}
/**
@@ -1066,7 +1068,7 @@ public class UploadPack {
findSymrefs(adv, refsToSend);
}
- adv.send(refsToSend);
+ adv.send(refsToSend.values());
adv.end();
}
@@ -1227,7 +1229,7 @@ public class UploadPack {
/* EOF when awaiting command is fine */
return true;
}
- if (command == PacketLineIn.END) {
+ if (PacketLineIn.isEnd(command)) {
// A blank request is valid according
// to the protocol; do nothing in this
// case.
@@ -1477,7 +1479,8 @@ public class UploadPack {
}
adv.setDerefTags(true);
findSymrefs(adv, advertisedOrDefaultRefs);
- advertised = adv.send(advertisedOrDefaultRefs);
+ advertised = adv.send(advertisedOrDefaultRefs.values());
+
if (adv.isEmpty())
adv.advertiseId(ObjectId.zeroId(), "capabilities^{}"); //$NON-NLS-1$
adv.end();
@@ -1526,17 +1529,30 @@ public class UploadPack {
}
/**
- * Returns the filter blob limit for the current request. Valid only after
- * calling recvWants(). A limit -1 means no limit.
+ * Deprecated synonym for {@code getFilterSpec().getBlobLimit()}.
*
* @return filter blob limit requested by the client, or -1 if no limit
* @since 5.3
+ * @deprecated Use {@link #getFilterSpec()} instead
*/
- public long getFilterBlobLimit() {
+ @Deprecated
+ public final long getFilterBlobLimit() {
+ return getFilterSpec().getBlobLimit();
+ }
+
+ /**
+ * Returns the filter spec for the current request. Valid only after
+ * calling recvWants(). This may be a no-op filter spec, but it won't be
+ * null.
+ *
+ * @return filter requested by the client
+ * @since 5.4
+ */
+ public final FilterSpec getFilterSpec() {
if (currentRequest == null) {
throw new RequestNotYetReadException();
}
- return currentRequest.getFilterBlobLimit();
+ return currentRequest.getFilterSpec();
}
/**
@@ -1584,7 +1600,7 @@ public class UploadPack {
throw eof;
}
- if (line == PacketLineIn.END) {
+ if (PacketLineIn.isEnd(line)) {
last = processHaveLines(peerHas, last, pckOut);
if (commonBase.isEmpty() || multiAck != MultiAck.OFF)
pckOut.writeString("NAK\n"); //$NON-NLS-1$
@@ -1854,58 +1870,88 @@ public class UploadPack {
private static void checkNotAdvertisedWants(UploadPack up,
List<ObjectId> notAdvertisedWants, Set<ObjectId> reachableFrom)
- throws MissingObjectException, IncorrectObjectTypeException, IOException {
- // Walk the requested commits back to the provided set of commits. If any
- // commit exists, a branch was deleted or rewound and the repository owner
- // no longer exports that requested item. If the requested commit is merged
- // into an advertised branch it will be marked UNINTERESTING and no commits
- // return.
+ throws IOException {
ObjectReader reader = up.getRevWalk().getObjectReader();
try (RevWalk walk = new RevWalk(reader)) {
- AsyncRevObjectQueue q = walk.parseAny(notAdvertisedWants, true);
- try {
- RevObject obj;
- while ((obj = q.next()) != null) {
- if (!(obj instanceof RevCommit)) {
- // If unadvertized non-commits are requested, use
- // bitmaps. If there are no bitmaps, instead of
- // incurring the expense of a manual walk, reject
- // the request.
- BitmapIndex bitmapIndex = reader.getBitmapIndex();
- if (bitmapIndex != null) {
- checkNotAdvertisedWantsUsingBitmap(
- reader,
- bitmapIndex,
- notAdvertisedWants,
- reachableFrom);
- return;
- }
- throw new WantNotValidException(obj);
- }
- walk.markStart((RevCommit) obj);
+ walk.setRetainBody(false);
+ // Missing "wants" throw exception here
+ List<RevObject> wantsAsObjs = objectIdsToRevObjects(walk,
+ notAdvertisedWants);
+ List<RevCommit> wantsAsCommits = wantsAsObjs.stream()
+ .filter(obj -> obj instanceof RevCommit)
+ .map(obj -> (RevCommit) obj)
+ .collect(Collectors.toList());
+ boolean allWantsAreCommits = wantsAsObjs.size() == wantsAsCommits
+ .size();
+ boolean repoHasBitmaps = reader.getBitmapIndex() != null;
+
+ if (!allWantsAreCommits) {
+ if (!repoHasBitmaps) {
+ // If unadvertized non-commits are requested, use
+ // bitmaps. If there are no bitmaps, instead of
+ // incurring the expense of a manual walk, reject
+ // the request.
+ RevObject nonCommit = wantsAsObjs
+ .stream()
+ .filter(obj -> !(obj instanceof RevCommit))
+ .limit(1)
+ .collect(Collectors.toList()).get(0);
+ throw new WantNotValidException(nonCommit);
+
}
- } catch (MissingObjectException notFound) {
- throw new WantNotValidException(notFound.getObjectId(),
- notFound);
- } finally {
- q.release();
+ checkNotAdvertisedWantsUsingBitmap(reader,
+ reader.getBitmapIndex(), notAdvertisedWants,
+ reachableFrom);
+ return;
}
- for (ObjectId id : reachableFrom) {
- try {
- walk.markUninteresting(walk.parseCommit(id));
- } catch (IncorrectObjectTypeException notCommit) {
- continue;
- }
+
+ // All wants are commits, we can use ReachabilityChecker
+ ReachabilityChecker reachabilityChecker = walk
+ .createReachabilityChecker();
+
+ List<RevCommit> starters = objectIdsToRevCommits(walk,
+ reachableFrom);
+ Optional<RevCommit> unreachable = reachabilityChecker
+ .areAllReachable(wantsAsCommits, starters);
+ if (unreachable.isPresent()) {
+ throw new WantNotValidException(unreachable.get());
}
- RevCommit bad = walk.next();
- if (bad != null) {
- throw new WantNotValidException(bad);
+ } catch (MissingObjectException notFound) {
+ throw new WantNotValidException(notFound.getObjectId(), notFound);
+ }
+ }
+
+ // Resolve the ObjectIds into RevObjects. Any missing object raises an
+ // exception
+ private static List<RevObject> objectIdsToRevObjects(RevWalk walk,
+ Iterable<ObjectId> objectIds)
+ throws MissingObjectException, IOException {
+ List<RevObject> result = new ArrayList<>();
+ for (ObjectId objectId : objectIds) {
+ result.add(walk.parseAny(objectId));
+ }
+ return result;
+ }
+
+ // Get commits from object ids. If the id is not a commit, ignore it. If the
+ // id doesn't exist, report the missing object in a exception.
+ private static List<RevCommit> objectIdsToRevCommits(RevWalk walk,
+ Iterable<ObjectId> objectIds)
+ throws MissingObjectException, IOException {
+ List<RevCommit> result = new ArrayList<>();
+ for (ObjectId objectId : objectIds) {
+ try {
+ result.add(walk.parseCommit(objectId));
+ } catch (IncorrectObjectTypeException e) {
+ continue;
}
}
+ return result;
}
+
private void addCommonBase(RevObject o) {
if (!o.has(COMMON)) {
o.add(COMMON);
@@ -1988,21 +2034,12 @@ public class UploadPack {
} catch (ServiceMayNotContinueException noPack) {
// This was already reported on (below).
throw noPack;
- } catch (IOException err) {
- if (reportInternalServerErrorOverSideband())
- throw new UploadPackInternalServerErrorException(err);
- else
- throw err;
- } catch (RuntimeException err) {
- if (reportInternalServerErrorOverSideband())
- throw new UploadPackInternalServerErrorException(err);
- else
- throw err;
- } catch (Error err) {
- if (reportInternalServerErrorOverSideband())
+ } catch (IOException | RuntimeException | Error err) {
+ if (reportInternalServerErrorOverSideband()) {
throw new UploadPackInternalServerErrorException(err);
- else
+ } else {
throw err;
+ }
}
} else {
sendPack(false, req, accumulator, allTags, unshallowCommits, deepenNots);
@@ -2097,15 +2134,16 @@ public class UploadPack {
accumulator);
try {
pw.setIndexDisabled(true);
- if (req.getFilterBlobLimit() >= 0) {
- pw.setFilterBlobLimit(req.getFilterBlobLimit());
- pw.setUseCachedPacks(false);
- } else {
+ if (req.getFilterSpec().isNoOp()) {
pw.setUseCachedPacks(true);
+ } else {
+ pw.setFilterSpec(req.getFilterSpec());
+ pw.setUseCachedPacks(false);
}
pw.setUseBitmaps(
req.getDepth() == 0
- && req.getClientShallowCommits().isEmpty());
+ && req.getClientShallowCommits().isEmpty()
+ && req.getFilterSpec().getTreeDepthLimit() == -1);
pw.setClientShallowCommits(req.getClientShallowCommits());
pw.setReuseDeltaCommits(true);
pw.setDeltaBaseAsOffset(
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java
index 2bb58144ba..b289e42177 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkFetchConnection.java
@@ -657,7 +657,7 @@ class WalkFetchConnection extends BaseFetchConnection {
}
ObjectId act = inserter.insert(type, raw);
- if (!AnyObjectId.equals(id, act)) {
+ if (!AnyObjectId.isEqual(id, act)) {
throw new TransportException(MessageFormat.format(
JGitText.get().incorrectHashFor, id.name(), act.name(),
Constants.typeString(type),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
index 4c754252a3..d9103f8b27 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java
@@ -165,7 +165,7 @@ class WalkPushConnection extends BaseConnection implements PushConnection {
continue;
}
- if (AnyObjectId.equals(ObjectId.zeroId(), u.getNewObjectId()))
+ if (AnyObjectId.isEqual(ObjectId.zeroId(), u.getNewObjectId()))
deleteCommand(u);
else
updates.add(u);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/FileResolver.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/FileResolver.java
index 60acd2f8ae..b4a7af094d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/FileResolver.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/FileResolver.java
@@ -127,11 +127,7 @@ public class FileResolver<C> implements RepositoryResolver<C> {
} else
throw new ServiceNotEnabledException();
- } catch (RuntimeException e) {
- db.close();
- throw new RepositoryNotFoundException(name, e);
-
- } catch (IOException e) {
+ } catch (RuntimeException | IOException e) {
db.close();
throw new RepositoryNotFoundException(name, e);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/ReceivePackFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/ReceivePackFactory.java
index b850d1ef94..5d36e58c01 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/ReceivePackFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/ReceivePackFactory.java
@@ -57,12 +57,8 @@ public interface ReceivePackFactory<C> {
/**
* A factory disabling the ReceivePack service for all repositories
*/
- ReceivePackFactory<?> DISABLED = new ReceivePackFactory<Object>() {
- @Override
- public ReceivePack create(Object req, Repository db)
- throws ServiceNotEnabledException {
- throw new ServiceNotEnabledException();
- }
+ ReceivePackFactory<?> DISABLED = (Object req, Repository db) -> {
+ throw new ServiceNotEnabledException();
};
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/RepositoryResolver.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/RepositoryResolver.java
index 4816f21bcc..dd24b7a0f2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/RepositoryResolver.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/RepositoryResolver.java
@@ -57,12 +57,8 @@ public interface RepositoryResolver<C> {
/**
* Resolver configured to open nothing.
*/
- RepositoryResolver<?> NONE = new RepositoryResolver<Object>() {
- @Override
- public Repository open(Object req, String name)
- throws RepositoryNotFoundException {
- throw new RepositoryNotFoundException(name);
- }
+ RepositoryResolver<?> NONE = (Object req, String name) -> {
+ throw new RepositoryNotFoundException(name);
};
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/UploadPackFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/UploadPackFactory.java
index bb43b136d8..b8673f5eb5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/UploadPackFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/resolver/UploadPackFactory.java
@@ -57,12 +57,8 @@ public interface UploadPackFactory<C> {
/**
* A factory disabling the UploadPack service for all repositories.
*/
- UploadPackFactory<?> DISABLED = new UploadPackFactory<Object>() {
- @Override
- public UploadPack create(Object req, Repository db)
- throws ServiceNotEnabledException {
- throw new ServiceNotEnabledException();
- }
+ UploadPackFactory<?> DISABLED = (Object req, Repository db) -> {
+ throw new ServiceNotEnabledException();
};
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java
index 61b130f93f..2f8af78f82 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java
@@ -323,8 +323,7 @@ public class NameConflictTreeWalk extends TreeWalk {
@Override
void popEntriesEqual() throws CorruptObjectException {
final AbstractTreeIterator ch = currentHead;
- for (int i = 0; i < trees.length; i++) {
- final AbstractTreeIterator t = trees[i];
+ for (AbstractTreeIterator t : trees) {
if (t.matches == ch) {
if (t.matchShift == 0)
t.next(1);
@@ -343,8 +342,7 @@ public class NameConflictTreeWalk extends TreeWalk {
@Override
void skipEntriesEqual() throws CorruptObjectException {
final AbstractTreeIterator ch = currentHead;
- for (int i = 0; i < trees.length; i++) {
- final AbstractTreeIterator t = trees[i];
+ for (AbstractTreeIterator t : trees) {
if (t.matches == ch) {
if (t.matchShift == 0)
t.skip();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
index 69303d6ee3..65d8512179 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java
@@ -1338,8 +1338,7 @@ public class TreeWalk implements AutoCloseable, AttributesProvider {
void popEntriesEqual() throws CorruptObjectException {
final AbstractTreeIterator ch = currentHead;
- for (int i = 0; i < trees.length; i++) {
- final AbstractTreeIterator t = trees[i];
+ for (AbstractTreeIterator t : trees) {
if (t.matches == ch) {
t.next(1);
t.matches = null;
@@ -1349,8 +1348,7 @@ public class TreeWalk implements AutoCloseable, AttributesProvider {
void skipEntriesEqual() throws CorruptObjectException {
final AbstractTreeIterator ch = currentHead;
- for (int i = 0; i < trees.length; i++) {
- final AbstractTreeIterator t = trees[i];
+ for (AbstractTreeIterator t : trees) {
if (t.matches == ch) {
t.skip();
t.matches = null;
@@ -1398,10 +1396,8 @@ public class TreeWalk implements AutoCloseable, AttributesProvider {
* @param <T>
* a tree type.
*/
- public <T extends AbstractTreeIterator> T getTree(
- Class<T> type) {
- for (int i = 0; i < trees.length; i++) {
- AbstractTreeIterator tree = trees[i];
+ public <T extends AbstractTreeIterator> T getTree(Class<T> type) {
+ for (AbstractTreeIterator tree : trees) {
if (type.isInstance(tree)) {
return type.cast(tree);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index 90524fedaf..f816ff370e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -787,14 +787,10 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
return attributesNode;
}
- private static final Comparator<Entry> ENTRY_CMP = new Comparator<Entry>() {
- @Override
- public int compare(Entry a, Entry b) {
- return Paths.compare(
- a.encodedName, 0, a.encodedNameLen, a.getMode().getBits(),
- b.encodedName, 0, b.encodedNameLen, b.getMode().getBits());
- }
- };
+ private static final Comparator<Entry> ENTRY_CMP = (Entry a,
+ Entry b) -> Paths.compare(a.encodedName, 0, a.encodedNameLen,
+ a.getMode().getBits(), b.encodedName, 0, b.encodedNameLen,
+ b.getMode().getBits());
/**
* Constructor helper.
@@ -1547,6 +1543,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
ObjectId blobId = entry.getObjectId();
if (entry.getStage() > 0
&& entry.getStage() != DirCacheEntry.STAGE_2) {
+ blobId = null;
// Merge conflict: check ours (stage 2)
byte[] name = entry.getRawPath();
int i = 0;
@@ -1554,7 +1551,8 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
dirCache.next(1);
i++;
entry = dirCache.getDirCacheEntry();
- if (!Arrays.equals(name, entry.getRawPath())) {
+ if (entry == null
+ || !Arrays.equals(name, entry.getRawPath())) {
break;
}
if (entry.getStage() == DirCacheEntry.STAGE_2) {
@@ -1564,17 +1562,20 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
}
dirCache.back(i);
}
- try (ObjectReader reader = repository.newObjectReader()) {
- ObjectLoader loader = reader.open(blobId, Constants.OBJ_BLOB);
- try {
- return RawText.isCrLfText(loader.getCachedBytes());
- } catch (LargeObjectException e) {
- try (InputStream in = loader.openStream()) {
- return RawText.isCrLfText(in);
+ if (blobId != null) {
+ try (ObjectReader reader = repository.newObjectReader()) {
+ ObjectLoader loader = reader.open(blobId,
+ Constants.OBJ_BLOB);
+ try {
+ return RawText.isCrLfText(loader.getCachedBytes());
+ } catch (LargeObjectException e) {
+ try (InputStream in = loader.openStream()) {
+ return RawText.isCrLfText(in);
+ }
}
+ } catch (IOException e) {
+ // Ignore and return false below
}
- } catch (IOException e) {
- // Ignore and return false below
}
}
return false;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilterMarker.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilterMarker.java
index 738ccbd8b7..c28f03534c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilterMarker.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/TreeFilterMarker.java
@@ -113,7 +113,7 @@ public class TreeFilterMarker {
try {
boolean marked = filter.include(walk);
if (marked)
- marks |= (1L << index);
+ marks |= (1 << index);
} catch (StopWalkException e) {
// Don't check tree filter anymore, it will no longer
// match
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 a9cef59636..90305013f5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -363,7 +363,7 @@ public abstract class FS {
}
return attributes;
});
- f.exceptionally(e -> {
+ f = f.exceptionally(e -> {
LOG.error(e.getLocalizedMessage(), e);
return Optional.empty();
});
@@ -1042,13 +1042,9 @@ public abstract class FS {
* @return the user's home directory; null if the user does not have one.
*/
protected File userHomeImpl() {
- final String home = AccessController
- .doPrivileged(new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty("user.home"); //$NON-NLS-1$
- }
- });
+ final String home = AccessController.doPrivileged(
+ (PrivilegedAction<String>) () -> System.getProperty("user.home") //$NON-NLS-1$
+ );
if (home == null || home.length() == 0)
return null;
return new File(home).getAbsoluteFile();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
index eda0fae247..a485389a9a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java
@@ -51,8 +51,9 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.nio.charset.Charset;
-import java.nio.file.AccessDeniedException;
import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
@@ -62,9 +63,11 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.errors.JGitInternalException;
@@ -88,7 +91,7 @@ public class FS_POSIX extends FS {
private static final int DEFAULT_UMASK = 0022;
private volatile int umask = -1;
- private volatile boolean supportsUnixNLink = true;
+ private static final Map<FileStore, Boolean> CAN_HARD_LINK = new ConcurrentHashMap<>();
private volatile AtomicFileCreation supportsAtomicFileCreation = AtomicFileCreation.UNDEFINED;
@@ -375,12 +378,23 @@ public class FS_POSIX extends FS {
if (!lock.createNewFile()) {
return false;
}
- if (supportsAtomicCreateNewFile() || !supportsUnixNLink) {
+ if (supportsAtomicCreateNewFile()) {
return true;
}
Path lockPath = lock.toPath();
Path link = null;
+ FileStore store = null;
try {
+ store = Files.getFileStore(lockPath);
+ } catch (SecurityException e) {
+ return true;
+ }
+ try {
+ Boolean canLink = CAN_HARD_LINK.computeIfAbsent(store,
+ s -> Boolean.TRUE);
+ if (Boolean.FALSE.equals(canLink)) {
+ return true;
+ }
link = Files.createLink(
Paths.get(lock.getAbsolutePath() + ".lnk"), //$NON-NLS-1$
lockPath);
@@ -392,11 +406,11 @@ public class FS_POSIX extends FS {
nlink));
return false;
} else if (nlink < 2) {
- supportsUnixNLink = false;
+ CAN_HARD_LINK.put(store, Boolean.FALSE);
}
return true;
} catch (UnsupportedOperationException | IllegalArgumentException e) {
- supportsUnixNLink = false;
+ CAN_HARD_LINK.put(store, Boolean.FALSE);
return true;
} finally {
if (link != null) {
@@ -439,11 +453,22 @@ public class FS_POSIX extends FS {
} catch (FileAlreadyExistsException | InvalidPathException e) {
return token(false, null);
}
- if (supportsAtomicCreateNewFile() || !supportsUnixNLink) {
+ if (supportsAtomicCreateNewFile()) {
return token(true, null);
}
Path link = null;
+ FileStore store = null;
try {
+ store = Files.getFileStore(path);
+ } catch (SecurityException e) {
+ return token(true, null);
+ }
+ try {
+ Boolean canLink = CAN_HARD_LINK.computeIfAbsent(store,
+ s -> Boolean.TRUE);
+ if (Boolean.FALSE.equals(canLink)) {
+ return token(true, null);
+ }
link = Files.createLink(Paths.get(uniqueLinkPath(file)), path);
Integer nlink = (Integer) (Files.getAttribute(path,
"unix:nlink")); //$NON-NLS-1$
@@ -452,12 +477,12 @@ public class FS_POSIX extends FS {
JGitText.get().failedAtomicFileCreation, path, nlink));
return token(false, link);
} else if (nlink.intValue() < 2) {
- supportsUnixNLink = false;
+ CAN_HARD_LINK.put(store, Boolean.FALSE);
}
return token(true, link);
} catch (UnsupportedOperationException | IllegalArgumentException
- | AccessDeniedException | SecurityException e) {
- supportsUnixNLink = false;
+ | FileSystemException | SecurityException e) {
+ CAN_HARD_LINK.put(store, Boolean.FALSE);
return token(true, link);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java
index 7c07270363..7fe80bb21a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java
@@ -205,18 +205,21 @@ public class FS_Win32 extends FS {
@Override
protected File userHomeImpl() {
String home = SystemReader.getInstance().getenv("HOME"); //$NON-NLS-1$
- if (home != null)
+ if (home != null) {
return resolve(null, home);
+ }
String homeDrive = SystemReader.getInstance().getenv("HOMEDRIVE"); //$NON-NLS-1$
if (homeDrive != null) {
String homePath = SystemReader.getInstance().getenv("HOMEPATH"); //$NON-NLS-1$
- if (homePath != null)
+ if (homePath != null) {
return new File(homeDrive, homePath);
+ }
}
String homeShare = SystemReader.getInstance().getenv("HOMESHARE"); //$NON-NLS-1$
- if (homeShare != null)
+ if (homeShare != null) {
return new File(homeShare);
+ }
return super.userHomeImpl();
}
@@ -237,8 +240,9 @@ public class FS_Win32 extends FS {
/** {@inheritDoc} */
@Override
public boolean supportsSymlinks() {
- if (supportSymlinks == null)
+ if (supportSymlinks == null) {
detectSymlinkSupport();
+ }
return Boolean.TRUE.equals(supportSymlinks);
}
@@ -254,12 +258,13 @@ public class FS_Win32 extends FS {
| InternalError e) {
supportSymlinks = Boolean.FALSE;
} finally {
- if (tempFile != null)
+ if (tempFile != null) {
try {
FileUtils.delete(tempFile);
} catch (IOException e) {
throw new RuntimeException(e); // panic
}
+ }
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java
index e5c8d9d398..9a163e8e38 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32_Cygwin.java
@@ -80,12 +80,9 @@ public class FS_Win32_Cygwin extends FS_Win32 {
*/
public static boolean isCygwin() {
final String path = AccessController
- .doPrivileged(new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty("java.library.path"); //$NON-NLS-1$
- }
- });
+ .doPrivileged((PrivilegedAction<String>) () -> System
+ .getProperty("java.library.path") //$NON-NLS-1$
+ );
if (path == null)
return false;
File found = FS.searchPath(path, "cygpath.exe"); //$NON-NLS-1$
@@ -141,13 +138,9 @@ public class FS_Win32_Cygwin extends FS_Win32 {
/** {@inheritDoc} */
@Override
protected File userHomeImpl() {
- final String home = AccessController
- .doPrivileged(new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getenv("HOME"); //$NON-NLS-1$
- }
- });
+ final String home = AccessController.doPrivileged(
+ (PrivilegedAction<String>) () -> System.getenv("HOME") //$NON-NLS-1$
+ );
if (home == null || home.length() == 0)
return super.userHomeImpl();
return resolve(new File("."), home); //$NON-NLS-1$
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index 9f7d9a236e..4d791e470a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -48,6 +48,7 @@ package org.eclipse.jgit.util;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.AtomicMoveNotSupportedException;
@@ -200,31 +201,50 @@ public class FileUtils {
if ((options & EMPTY_DIRECTORIES_ONLY) != 0) {
if (f.isDirectory()) {
delete = true;
- } else {
- if ((options & IGNORE_ERRORS) == 0)
- throw new IOException(MessageFormat.format(
- JGitText.get().deleteFileFailed,
- f.getAbsolutePath()));
+ } else if ((options & IGNORE_ERRORS) == 0) {
+ throw new IOException(MessageFormat.format(
+ JGitText.get().deleteFileFailed, f.getAbsolutePath()));
}
} else {
delete = true;
}
- if (delete && !f.delete()) {
- if ((options & RETRY) != 0 && fs.exists(f)) {
+ if (delete) {
+ Throwable t = null;
+ Path p = f.toPath();
+ try {
+ Files.delete(p);
+ return;
+ } catch (FileNotFoundException e) {
+ if ((options & (SKIP_MISSING | IGNORE_ERRORS)) == 0) {
+ throw new IOException(MessageFormat.format(
+ JGitText.get().deleteFileFailed,
+ f.getAbsolutePath()), e);
+ }
+ return;
+ } catch (IOException e) {
+ t = e;
+ }
+ if ((options & RETRY) != 0) {
for (int i = 1; i < 10; i++) {
try {
Thread.sleep(100);
- } catch (InterruptedException e) {
+ } catch (InterruptedException ex) {
// ignore
}
- if (f.delete())
+ try {
+ Files.deleteIfExists(p);
return;
+ } catch (IOException e) {
+ t = e;
+ }
}
}
- if ((options & IGNORE_ERRORS) == 0)
+ if ((options & IGNORE_ERRORS) == 0) {
throw new IOException(MessageFormat.format(
- JGitText.get().deleteFileFailed, f.getAbsolutePath()));
+ JGitText.get().deleteFileFailed, f.getAbsolutePath()),
+ t);
+ }
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/GSSManagerFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/GSSManagerFactory.java
index da57999e29..5927b33355 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/GSSManagerFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/GSSManagerFactory.java
@@ -145,13 +145,8 @@ public abstract class GSSManagerFactory {
return (GSSManager) GSS_MANAGER_IMPL_CONSTRUCTOR
.newInstance(httpCaller);
- } catch (InstantiationException e) {
- throw new Error(e);
- } catch (IllegalAccessException e) {
- throw new Error(e);
- } catch (IllegalArgumentException e) {
- throw new Error(e);
- } catch (InvocationTargetException e) {
+ } catch (InstantiationException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException e) {
throw new Error(e);
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java
index a339b9aba0..56a173163d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/GitDateParser.java
@@ -126,7 +126,7 @@ public class GitDateParser {
DEFAULT("EEE MMM dd HH:mm:ss yyyy Z"), // //$NON-NLS-1$
LOCAL("EEE MMM dd HH:mm:ss yyyy"); //$NON-NLS-1$
- String formatStr;
+ private final String formatStr;
private ParseableSimpleDateFormat(String formatStr) {
this.formatStr = formatStr;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
index 9190a5915a..640670debc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
@@ -170,6 +170,27 @@ public class HttpSupport {
public static final String HDR_WWW_AUTHENTICATE = "WWW-Authenticate"; //$NON-NLS-1$
/**
+ * The {@code Cookie} header.
+ *
+ * @since 5.4
+ */
+ public static final String HDR_COOKIE = "Cookie"; //$NON-NLS-1$
+
+ /**
+ * The {@code Set-Cookie} header.
+ *
+ * @since 5.4
+ */
+ public static final String HDR_SET_COOKIE = "Set-Cookie"; //$NON-NLS-1$
+
+ /**
+ * The {@code Set-Cookie2} header.
+ *
+ * @since 5.4
+ */
+ public static final String HDR_SET_COOKIE2 = "Set-Cookie2"; //$NON-NLS-1$
+
+ /**
* URL encode a value string into an output buffer.
*
* @param urlstr
@@ -303,9 +324,7 @@ public class HttpSupport {
try {
conn.configure(null, trustAllCerts, null);
conn.setHostnameVerifier(new DummyHostnameVerifier());
- } catch (KeyManagementException e) {
- throw new IOException(e.getMessage());
- } catch (NoSuchAlgorithmException e) {
+ } catch (KeyManagementException | NoSuchAlgorithmException e) {
throw new IOException(e.getMessage());
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/LRUMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/LRUMap.java
new file mode 100644
index 0000000000..41c15363f8
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/LRUMap.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018, Konrad Windszus <konrad_w@gmx.de>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.util;
+
+import java.util.LinkedHashMap;
+
+/**
+ * Map with only up to n entries. If a new entry is added so that the map
+ * contains more than those n entries the least-recently used entry is removed
+ * from the map.
+ *
+ * @param <K>
+ * the type of keys maintained by this map
+ * @param <V>
+ * the type of mapped values
+ *
+ * @since 5.4
+ */
+public class LRUMap<K, V> extends LinkedHashMap<K, V> {
+
+ private static final long serialVersionUID = 4329609127403759486L;
+
+ private final int limit;
+
+ /**
+ * Constructs an empty map which may contain at most the given amount of
+ * entries.
+ *
+ * @param initialCapacity
+ * the initial capacity
+ * @param limit
+ * the number of entries the map should have at most
+ */
+ public LRUMap(int initialCapacity, int limit) {
+ super(initialCapacity, 0.75f, true);
+ this.limit = limit;
+ }
+
+ @Override
+ protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
+ return size() > limit;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
index 639c353621..60dead51b2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefList.java
@@ -48,7 +48,10 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collector;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefComparator;
@@ -333,6 +336,32 @@ public class RefList<T extends Ref> implements Iterable<Ref> {
}
/**
+ * Create a {@link Collector} for {@link Ref}.
+ *
+ * @param mergeFunction
+ * if specified the result will be sorted and deduped.
+ * @return {@link Collector} for {@link Ref}
+ * @since 5.4
+ */
+ public static <T extends Ref> Collector<T, ?, RefList<T>> toRefList(
+ @Nullable BinaryOperator<T> mergeFunction) {
+ return Collector.of(
+ () -> new Builder<>(),
+ Builder<T>::add, (b1, b2) -> {
+ Builder<T> b = new Builder<>();
+ b.addAll(b1);
+ b.addAll(b2);
+ return b;
+ }, (b) -> {
+ if (mergeFunction != null) {
+ b.sort();
+ b.dedupe(mergeFunction);
+ }
+ return b.toRefList();
+ });
+ }
+
+ /**
* Builder to facilitate fast construction of an immutable RefList.
*
* @param <T>
@@ -405,6 +434,16 @@ public class RefList<T extends Ref> implements Iterable<Ref> {
}
/**
+ * Add all items from another builder.
+ *
+ * @param other
+ * @since 5.4
+ */
+ public void addAll(Builder other) {
+ addAll(other.list, 0, other.size);
+ }
+
+ /**
* Add all items from a source array.
* <p>
* References must be added in sort order, or the array must be sorted
@@ -444,6 +483,31 @@ public class RefList<T extends Ref> implements Iterable<Ref> {
Arrays.sort(list, 0, size, RefComparator.INSTANCE);
}
+ /**
+ * Dedupe the refs in place. Must be called after {@link #sort}.
+ *
+ * @param mergeFunction
+ */
+ @SuppressWarnings("unchecked")
+ void dedupe(BinaryOperator<T> mergeFunction) {
+ if (size == 0) {
+ return;
+ }
+ int lastElement = 0;
+ for (int i = 1; i < size; i++) {
+ if (RefComparator.INSTANCE.compare(list[lastElement],
+ list[i]) == 0) {
+ list[lastElement] = mergeFunction
+ .apply((T) list[lastElement], (T) list[i]);
+ } else {
+ list[lastElement + 1] = list[i];
+ lastElement++;
+ }
+ }
+ size = lastElement + 1;
+ Arrays.fill(list, size, list.length, null);
+ }
+
/** @return an unmodifiable list using this collection's backing array. */
public RefList<T> toRefList() {
return new RefList<>(list, size);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java
index a3f9730f13..9663e3cef5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java
@@ -49,6 +49,9 @@ import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
@@ -285,6 +288,21 @@ public class RefMap extends AbstractMap<String, Ref> {
return r.toString();
}
+ /**
+ * Create a {@link Collector} for {@link Ref}.
+ *
+ * @param mergeFunction
+ * @return {@link Collector} for {@link Ref}
+ * @since 5.4
+ */
+ public static Collector<Ref, ?, RefMap> toRefMap(
+ BinaryOperator<Ref> mergeFunction) {
+ return Collectors.collectingAndThen(RefList.toRefList(mergeFunction),
+ (refs) -> new RefMap("", //$NON-NLS-1$
+ refs, RefList.emptyList(),
+ RefList.emptyList()));
+ }
+
private String toRefName(String name) {
if (0 < prefix.length())
name = prefix + name;
@@ -425,8 +443,10 @@ public class RefMap extends AbstractMap<String, Ref> {
if (r.getName().equals(ref.getName())) {
final ObjectId a = r.getObjectId();
final ObjectId b = ref.getObjectId();
- if (a != null && b != null && AnyObjectId.equals(a, b))
+ if (a != null && b != null
+ && AnyObjectId.isEqual(a, b)) {
return true;
+ }
}
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/References.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/References.java
new file mode 100644
index 0000000000..341fbfa943
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/References.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019, Matthias Sohn <matthias.sohn@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.util;
+
+/**
+ * Utility methods for object references
+ *
+ * @since 5.4
+ */
+public interface References {
+
+ /**
+ * Compare two references
+ *
+ * @param <T>
+ * type of the references
+ * @param ref1
+ * first reference
+ * @param ref2
+ * second reference
+ * @return {@code true} if both references refer to the same object
+ */
+ @SuppressWarnings("ReferenceEquality")
+ public static <T> boolean isSameObject(T ref1, T ref2) {
+ return ref1 == ref2;
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SimpleLruCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SimpleLruCache.java
index 709d9ee73d..7235b15548 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SimpleLruCache.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SimpleLruCache.java
@@ -159,6 +159,7 @@ public class SimpleLruCache<K, V> {
*
* @return value mapped for this key, or {@code null} if no value is mapped
*/
+ @SuppressWarnings("NonAtomicVolatileUpdate")
public V get(Object key) {
Entry<K, V> entry = map.get(key);
if (entry != null) {
@@ -185,6 +186,7 @@ public class SimpleLruCache<K, V> {
* @throws NullPointerException
* if the specified key or value is null
*/
+ @SuppressWarnings("NonAtomicVolatileUpdate")
public V put(@NonNull K key, @NonNull V value) {
map.put(key, new Entry<>(key, value, ++time));
if (map.size() > maximumSize) {
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 3868e56f50..f4b6f9d0df 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/StringUtils.java
@@ -139,8 +139,9 @@ public final class StringUtils {
* @return true if a equals b
*/
public static boolean equalsIgnoreCase(String a, String b) {
- if (a == b)
+ if (References.isSameObject(a, b)) {
return true;
+ }
if (a.length() != b.length())
return false;
for (int i = 0; i < a.length(); i++) {
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 d554562a75..8431196cb5 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java
@@ -461,12 +461,9 @@ public abstract class SystemReader {
}
private String getOsName() {
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
- @Override
- public String run() {
- return getProperty("os.name"); //$NON-NLS-1$
- }
- });
+ return AccessController.doPrivileged(
+ (PrivilegedAction<String>) () -> getProperty("os.name") //$NON-NLS-1$
+ );
}
/**
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java
index 65470d4ef1..18de7052d9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/IsolatedOutputStream.java
@@ -88,7 +88,7 @@ public class IsolatedOutputStream extends OutputStream {
public IsolatedOutputStream(OutputStream out) {
dst = out;
copier = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS,
- new ArrayBlockingQueue<Runnable>(1), new NamedThreadFactory());
+ new ArrayBlockingQueue<>(1), new NamedThreadFactory());
}
/** {@inheritDoc} */
@@ -102,12 +102,9 @@ public class IsolatedOutputStream extends OutputStream {
public void write(byte[] buf, int pos, int cnt)
throws IOException {
checkClosed();
- execute(new Callable<Void>() {
- @Override
- public Void call() throws IOException {
- dst.write(buf, pos, cnt);
- return null;
- }
+ execute(() -> {
+ dst.write(buf, pos, cnt);
+ return null;
});
}
@@ -115,12 +112,9 @@ public class IsolatedOutputStream extends OutputStream {
@Override
public void flush() throws IOException {
checkClosed();
- execute(new Callable<Void>() {
- @Override
- public Void call() throws IOException {
- dst.flush();
- return null;
- }
+ execute(() -> {
+ dst.flush();
+ return null;
});
}
@@ -159,12 +153,9 @@ public class IsolatedOutputStream extends OutputStream {
}
private void cleanClose() throws IOException {
- execute(new Callable<Void>() {
- @Override
- public Void call() throws IOException {
- dst.close();
- return null;
- }
+ execute(() -> {
+ dst.close();
+ return null;
});
}
@@ -178,12 +169,9 @@ public class IsolatedOutputStream extends OutputStream {
Future<Void> close;
try {
- close = copier.submit(new Callable<Void>() {
- @Override
- public Void call() throws IOException {
- dst.close();
- return null;
- }
+ close = copier.submit(() -> {
+ dst.close();
+ return null;
});
} catch (RejectedExecutionException e) {
throw new IOException(e);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/ThrowingPrintWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/ThrowingPrintWriter.java
index caabcef574..9431aafbde 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/ThrowingPrintWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/ThrowingPrintWriter.java
@@ -68,12 +68,10 @@ public class ThrowingPrintWriter extends Writer {
*/
public ThrowingPrintWriter(Writer out) {
this.out = out;
- LF = AccessController.doPrivileged(new PrivilegedAction<String>() {
- @Override
- public String run() {
- return SystemReader.getInstance().getProperty("line.separator"); //$NON-NLS-1$
- }
- });
+ LF = AccessController
+ .doPrivileged((PrivilegedAction<String>) () -> SystemReader
+ .getInstance().getProperty("line.separator") //$NON-NLS-1$
+ );
}
/** {@inheritDoc} */

Back to the top